From 19f9172d6429166c9237d16b2f8a27990be4631f Mon Sep 17 00:00:00 2001 From: Fredrik Mellbin Date: Wed, 3 Sep 2008 22:26:27 +0000 Subject: [PATCH] FFmpegSource2: fix lots of memory leaks, improve the api, add a progress callback Originally committed to SVN as r2315. --- FFmpegSource2/ffavsfilters.cpp | 40 ++++++-- FFmpegSource2/ffms.cpp | 12 +-- FFmpegSource2/ffms.h | 13 +-- FFmpegSource2/ffvideosource.cpp | 2 +- FFmpegSource2/ffvideosource.h | 5 +- FFmpegSource2/indexing.cpp | 177 +++++++++++++++++++++----------- FFmpegSource2/indexing.h | 4 +- 7 files changed, 162 insertions(+), 91 deletions(-) diff --git a/FFmpegSource2/ffavsfilters.cpp b/FFmpegSource2/ffavsfilters.cpp index 2058cbefb..1f88ef27e 100644 --- a/FFmpegSource2/ffavsfilters.cpp +++ b/FFmpegSource2/ffavsfilters.cpp @@ -54,12 +54,14 @@ AVSValue __cdecl CreateFFIndex(AVSValue Args, void* UserData, IScriptEnvironment // 1: Index generated // 2: Index forced to be overwritten - FrameIndex *Index = FFMS_CreateFrameIndex(); - if (OverWrite || FFMS_ReadIndex(CacheFile, Index, ErrorMsg, MsgSize)) { - if (FFMS_MakeIndex(Source, Index, TrackMask, AudioFile, NULL, ErrorMsg, MsgSize)) + FrameIndex *Index; + if (OverWrite || !(Index = FFMS_ReadIndex(CacheFile, ErrorMsg, MsgSize))) { + if (!(Index = FFMS_MakeIndex(Source, TrackMask, AudioFile, NULL, NULL, ErrorMsg, MsgSize))) Env->ThrowError("FFIndex: %s", ErrorMsg); - if (FFMS_WriteIndex(CacheFile, Index, ErrorMsg, MsgSize)) + if (FFMS_WriteIndex(CacheFile, Index, ErrorMsg, MsgSize)) { + FFMS_DestroyFrameIndex(Index); Env->ThrowError("FFIndex: %s", ErrorMsg); + } FFMS_DestroyFrameIndex(Index); if (!OverWrite) return AVSValue(1); @@ -100,28 +102,44 @@ AVSValue __cdecl CreateFFVideoSource(AVSValue Args, void* UserData, IScriptEnvir if (Threads < 1) Env->ThrowError("FFVideoSource: Invalid thread count"); + if (!_stricmp(Source, Timecodes)) + Env->ThrowError("FFVideoSource: Timecodes will overwrite the source"); + std::string DefaultCache(Source); DefaultCache.append(".ffindex"); if (!strcmp(CacheFile, "")) CacheFile = DefaultCache.c_str(); - FrameIndex *Index = FFMS_CreateFrameIndex(); + FrameIndex *Index; if (Cache) { - if (FFMS_ReadIndex(CacheFile, Index, ErrorMsg, MsgSize)) { - if (FFMS_MakeIndex(Source, Index, 0, NULL, NULL, ErrorMsg, MsgSize)) + if (!(Index = FFMS_ReadIndex(CacheFile, ErrorMsg, MsgSize))) { + if (!(Index = FFMS_MakeIndex(Source, 0, NULL, NULL, NULL, ErrorMsg, MsgSize))) Env->ThrowError("FFVideoSource: %s", ErrorMsg); if (Cache) - if (FFMS_WriteIndex(CacheFile, Index, ErrorMsg, MsgSize)) + if (FFMS_WriteIndex(CacheFile, Index, ErrorMsg, MsgSize)) { + FFMS_DestroyFrameIndex(Index); Env->ThrowError("FFVideoSource: %s", ErrorMsg); + } } } - AvisynthVideoSource *Filter = new AvisynthVideoSource(Source, Track, Index, PP, Threads, SeekMode, Env, ErrorMsg, MsgSize); + AvisynthVideoSource *Filter; - if (strcmp(Timecodes, "")) - if (FFMS_WriteTimecodes(FFMS_GetTITrackIndex(Index, Filter->GetTrack(), ErrorMsg, MsgSize), Timecodes, ErrorMsg, MsgSize)) + try { + Filter = new AvisynthVideoSource(Source, Track, Index, PP, Threads, SeekMode, Env, ErrorMsg, MsgSize); + } catch (...) { + FFMS_DestroyFrameIndex(Index); + throw; + } + + if (strcmp(Timecodes, "")) { + if (FFMS_WriteTimecodes(FFMS_GetTITrackIndex(Index, Filter->GetTrack(), ErrorMsg, MsgSize), Timecodes, ErrorMsg, MsgSize)) { + FFMS_DestroyFrameIndex(Index); + delete Filter; Env->ThrowError("FFVideoSource: %s", ErrorMsg); + } + } return Filter; } diff --git a/FFmpegSource2/ffms.cpp b/FFmpegSource2/ffms.cpp index 7f11b1ef2..37522d4a0 100644 --- a/FFmpegSource2/ffms.cpp +++ b/FFmpegSource2/ffms.cpp @@ -53,10 +53,6 @@ FFMS_API(const AVFrameLite *) FFMS_GetFrame(VideoBase *VB, int n, char *ErrorMsg return (AVFrameLite *)VB->GetFrame(n, ErrorMsg, MsgSize); } -FFMS_API(FrameIndex *) FFMS_CreateFrameIndex() { - return new FrameIndex(); -} - FFMS_API(void) FFMS_DestroyFrameIndex(FrameIndex *FI) { delete FI; } @@ -116,12 +112,12 @@ FFMS_API(int) FFMS_WriteTimecodes(FrameInfoVector *FIV, const char *TimecodeFile return FIV->WriteTimecodes(TimecodeFile, ErrorMsg, MsgSize); } -FFMS_API(int) FFMS_MakeIndex(const char *SourceFile, FrameIndex *TrackIndices, int AudioTrackMask, const char *AudioFile, IndexProgress *IP, char *ErrorMsg, unsigned MsgSize) { - return MakeIndex(SourceFile, TrackIndices, AudioTrackMask, AudioFile, IP, ErrorMsg, MsgSize); +FFMS_API(FrameIndex *) FFMS_MakeIndex(const char *SourceFile, int AudioTrackMask, const char *AudioFile, IndexCallback *IP, void *Private, char *ErrorMsg, unsigned MsgSize) { + return MakeIndex(SourceFile, AudioTrackMask, AudioFile, IP, Private, ErrorMsg, MsgSize); } -FFMS_API(int) FFMS_ReadIndex(const char *IndexFile, FrameIndex *TrackIndices, char *ErrorMsg, unsigned MsgSize) { - return ReadIndex(IndexFile, TrackIndices, ErrorMsg, MsgSize); +FFMS_API(FrameIndex *) FFMS_ReadIndex(const char *IndexFile, char *ErrorMsg, unsigned MsgSize) { + return ReadIndex(IndexFile, ErrorMsg, MsgSize); } FFMS_API(int) FFMS_WriteIndex(const char *IndexFile, FrameIndex *TrackIndices, char *ErrorMsg, unsigned MsgSize) { diff --git a/FFmpegSource2/ffms.h b/FFmpegSource2/ffms.h index 1aabe480c..2be941acb 100644 --- a/FFmpegSource2/ffms.h +++ b/FFmpegSource2/ffms.h @@ -31,17 +31,19 @@ # define EXTERN_C #endif +#define FFMS_CC __stdcall + #ifdef FFMS_EXPORTS -# define FFMS_API(ret) EXTERN_C __declspec(dllexport) ret __stdcall +# define FFMS_API(ret) EXTERN_C __declspec(dllexport) ret FFMS_CC #else -# define FFMS_API(ret) EXTERN_C __declspec(dllimport) ret __stdcall +# define FFMS_API(ret) EXTERN_C __declspec(dllimport) ret FFMS_CC #endif class VideoBase; class FrameIndex; class FrameInfoVector; -typedef int (*IndexProgress)(int64_t, int); +typedef int (*IndexCallback)(int State, int64_t Current, int64_t Total, void *Private); // This is a subset of the original AVFrame only containing the most used parts. // Even if it might seem like a good idea to cast it back to a full AVFrame to @@ -89,7 +91,6 @@ FFMS_API(void) FFMS_DestroyVideoSource(VideoBase *VB); FFMS_API(int) FFMS_GetVSTrack(VideoBase *VB); FFMS_API(const VideoProperties *) FFMS_GetVideoProperties(VideoBase *VB); FFMS_API(const AVFrameLite *) FFMS_GetFrame(VideoBase *VB, int n, char *ErrorMsg, unsigned MsgSize); -FFMS_API(FrameIndex *) FFMS_CreateFrameIndex(); FFMS_API(void) FFMS_DestroyFrameIndex(FrameIndex *FI); FFMS_API(int) FFMS_GetNumTracks(FrameIndex *TrackIndices, char *ErrorMsg, unsigned MsgSize); FFMS_API(int) FFMS_GetNumFrames(FrameInfoVector *FIV, char *ErrorMsg, unsigned MsgSize); @@ -101,8 +102,8 @@ FFMS_API(int) FFMS_FrameFromDTS(FrameInfoVector *FIV, int64_t DTS, char *ErrorMs FFMS_API(int) FFMS_ClosestFrameFromDTS(FrameInfoVector *FIV, int64_t DTS, char *ErrorMsg, unsigned MsgSize); FFMS_API(const TrackTimeBase *) FFMS_GetTimeBase(FrameInfoVector *FIV, char *ErrorMsg, unsigned MsgSize); FFMS_API(int) FFMS_WriteTimecodes(FrameInfoVector *FIV, const char *TimecodeFile, char *ErrorMsg, unsigned MsgSize); -FFMS_API(int) FFMS_MakeIndex(const char *SourceFile, FrameIndex *TrackIndices, int AudioTrackMask, const char *AudioFile, IndexProgress *IP, char *ErrorMsg, unsigned MsgSize); -FFMS_API(int) FFMS_ReadIndex(const char *IndexFile, FrameIndex *TrackIndices, char *ErrorMsg, unsigned MsgSize); +FFMS_API(FrameIndex *) FFMS_MakeIndex(const char *SourceFile, int AudioTrackMask, const char *AudioFile, IndexCallback *IP, void *Private, char *ErrorMsg, unsigned MsgSize); +FFMS_API(FrameIndex *) FFMS_ReadIndex(const char *IndexFile, char *ErrorMsg, unsigned MsgSize); FFMS_API(int) FFMS_WriteIndex(const char *IndexFile, FrameIndex *TrackIndices, char *ErrorMsg, unsigned MsgSize); #endif diff --git a/FFmpegSource2/ffvideosource.cpp b/FFmpegSource2/ffvideosource.cpp index c8e333b79..4b85ba5f6 100644 --- a/FFmpegSource2/ffvideosource.cpp +++ b/FFmpegSource2/ffvideosource.cpp @@ -21,7 +21,7 @@ #include "ffvideosource.h" int VideoBase::InitPP(const char *PP, int PixelFormat, char *ErrorMsg, unsigned MsgSize) { - if (!strcmp(PP, "")) + if (PP == NULL || !strcmp(PP, "")) return 0; PPMode = pp_get_mode_by_name_and_quality(PP, PP_QUALITY_MAX); diff --git a/FFmpegSource2/ffvideosource.h b/FFmpegSource2/ffvideosource.h index 0fc9e3fd5..4cefa414d 100644 --- a/FFmpegSource2/ffvideosource.h +++ b/FFmpegSource2/ffvideosource.h @@ -77,11 +77,10 @@ public: class MatroskaVideoSource : public VideoBase { private: - unsigned int BufferSize; - CompressedStream *CS; MatroskaFile *MF; - char ErrorMessage[256]; MatroskaReaderContext MC; + CompressedStream *CS; + char ErrorMessage[256]; int DecodeNextFrame(AVFrame *AFrame, int64_t *AFirstStartTime, char *ErrorMsg, unsigned MsgSize); int GetTrackIndex(int &Index, char *ErrorMsg, unsigned MsgSize); diff --git a/FFmpegSource2/indexing.cpp b/FFmpegSource2/indexing.cpp index 32ca3e87b..2ac33bfca 100644 --- a/FFmpegSource2/indexing.cpp +++ b/FFmpegSource2/indexing.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include "indexing.h" #include "wave64writer.h" @@ -48,6 +49,41 @@ public: } }; +class IndexMemory { +private: + int16_t *DecodingBuffer; + AudioContext *AudioContexts; +public: + IndexMemory(int Tracks, int16_t *&DecodingBuffer, AudioContext *&AudioContexts) { + DecodingBuffer = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE*10]; + AudioContexts = new AudioContext[Tracks]; + this->DecodingBuffer = DecodingBuffer; + this->AudioContexts = AudioContexts; + } + + ~IndexMemory() { + delete [] DecodingBuffer; + delete [] AudioContexts; + } +}; + +class MatroskaMemory { +private: + MatroskaFile *MF; + MatroskaReaderContext *MC; +public: + MatroskaMemory(MatroskaFile *MF, MatroskaReaderContext *MC) { + this->MF = MF; + this->MC = MC; + } + + ~MatroskaMemory() { + mkv_Close(MF); + fclose(MC->ST.fp); + } +}; + + static bool DTSComparison(FrameInfo FI1, FrameInfo FI2) { return FI1.DTS < FI2.DTS; } @@ -86,14 +122,10 @@ int WriteIndex(const char *IndexFile, FrameIndex *TrackIndices, char *ErrorMsg, Index.write(reinterpret_cast(&(TrackIndices->at(i)[j])), sizeof(FrameInfo)); } - Index.close(); - return 0; } -static int MakeMatroskaIndex(const char *SourceFile, FrameIndex *TrackIndices, int AudioTrackMask, const char *AudioFile, IndexProgress *IP, char *ErrorMsg, unsigned MsgSize) { - TrackIndices->Decoder = 1; - +static FrameIndex *MakeMatroskaIndex(const char *SourceFile, int AudioTrackMask, const char *AudioFile, IndexCallback *IP, void *Private, char *ErrorMsg, unsigned MsgSize) { MatroskaFile *MF; char ErrorMessage[256]; MatroskaReaderContext MC; @@ -104,7 +136,7 @@ static int MakeMatroskaIndex(const char *SourceFile, FrameIndex *TrackIndices, i MC.ST.fp = fopen(SourceFile, "rb"); if (MC.ST.fp == NULL) { _snprintf(ErrorMsg, MsgSize, "Can't open '%s': %s", SourceFile, strerror(errno)); - return 1; + return NULL; } setvbuf(MC.ST.fp, NULL, _IOFBF, CACHESIZE); @@ -113,12 +145,16 @@ static int MakeMatroskaIndex(const char *SourceFile, FrameIndex *TrackIndices, i if (MF == NULL) { fclose(MC.ST.fp); _snprintf(ErrorMsg, MsgSize, "Can't parse Matroska file: %s", ErrorMessage); - return 2; + return NULL; } + MatroskaMemory MM = MatroskaMemory(MF, &MC); + // Audio stuff - AudioContext *AudioContexts = new AudioContext[mkv_GetNumTracks(MF)]; + int16_t *db; + AudioContext *AudioContexts; + IndexMemory IM = IndexMemory(mkv_GetNumTracks(MF), db, AudioContexts); for (unsigned int i = 0; i < mkv_GetNumTracks(MF); i++) { if (AudioTrackMask & (1 << i) && mkv_GetTrackInfo(MF, i)->Type == TT_AUDIO) { @@ -131,19 +167,19 @@ static int MakeMatroskaIndex(const char *SourceFile, FrameIndex *TrackIndices, i AudioContexts[i].CS = cs_Create(MF, i, ErrorMessage, sizeof(ErrorMessage)); if (AudioContexts[i].CS == NULL) { _snprintf(ErrorMsg, MsgSize, "Can't create decompressor: %s", ErrorMessage); - return 3; + return NULL; } } AVCodec *AudioCodec = avcodec_find_decoder(MatroskaToFFCodecID(mkv_GetTrackInfo(MF, i))); if (AudioCodec == NULL) { _snprintf(ErrorMsg, MsgSize, "Audio codec not found"); - return 4; + return NULL; } if (avcodec_open(AudioCodecContext, AudioCodec) < 0) { _snprintf(ErrorMsg, MsgSize, "Could not open audio codec"); - return 5; + return NULL; } } else { AudioTrackMask &= ~(1 << i); @@ -152,15 +188,29 @@ static int MakeMatroskaIndex(const char *SourceFile, FrameIndex *TrackIndices, i // + int64_t CurrentPos = _ftelli64(MC.ST.fp); + _fseeki64(MC.ST.fp, 0, SEEK_END); + int64_t SourceSize = _ftelli64(MC.ST.fp); + _fseeki64(MC.ST.fp, CurrentPos, SEEK_SET); + + FrameIndex *TrackIndices = new FrameIndex(); + TrackIndices->Decoder = 1; + for (unsigned int i = 0; i < mkv_GetNumTracks(MF); i++) TrackIndices->push_back(FrameInfoVector(mkv_TruncFloat(mkv_GetTrackInfo(MF, i)->TimecodeScale), 1000000)); uint64_t StartTime, EndTime, FilePos; unsigned int Track, FrameFlags, FrameSize; - int16_t *db = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE*10]; - while (mkv_ReadFrame(MF, 0, &Track, &StartTime, &EndTime, &FilePos, &FrameSize, &FrameFlags) == 0) { + // Update progress + if (IP) { + if ((*IP)(0, _ftelli64(MC.ST.fp), SourceSize, Private)) { + _snprintf(ErrorMsg, MsgSize, "Cancelled by user"); + return NULL; + } + } + // Only create index entries for video for now to save space if (mkv_GetTrackInfo(MF, Track)->Type == TT_VIDEO) (*TrackIndices)[Track].push_back(FrameInfo(StartTime, (FrameFlags & FRAME_KF) != 0)); @@ -177,7 +227,7 @@ static int MakeMatroskaIndex(const char *SourceFile, FrameIndex *TrackIndices, i int Ret = avcodec_decode_audio2(AudioCodecContext, db, &dbsize, Data, Size); if (Ret < 0) { _snprintf(ErrorMsg, MsgSize, "Audio decoding error"); - return 5; + return NULL; } if (Ret > 0) { @@ -203,42 +253,35 @@ static int MakeMatroskaIndex(const char *SourceFile, FrameIndex *TrackIndices, i } } - delete [] db; - delete [] AudioContexts; - - mkv_Close(MF); - fclose(MC.ST.fp); - SortTrackIndices(TrackIndices); - return 0; + return TrackIndices; } -int MakeIndex(const char *SourceFile, FrameIndex *TrackIndices, int AudioTrackMask, const char *AudioFile, IndexProgress *IP, char *ErrorMsg, unsigned MsgSize) { - TrackIndices->Decoder = 0; - TrackIndices->clear(); - +FrameIndex *MakeIndex(const char *SourceFile, int AudioTrackMask, const char *AudioFile, IndexCallback *IP, void *Private, char *ErrorMsg, unsigned MsgSize) { AVFormatContext *FormatContext = NULL; if (av_open_input_file(&FormatContext, SourceFile, NULL, 0, NULL) != 0) { _snprintf(ErrorMsg, MsgSize, "Can't open '%s'", SourceFile); - return 1; + return NULL; } // Do matroska indexing instead? if (!strcmp(FormatContext->iformat->name, "matroska")) { av_close_input_file(FormatContext); - return MakeMatroskaIndex(SourceFile, TrackIndices, AudioTrackMask, AudioFile, IP, ErrorMsg, MsgSize); + return MakeMatroskaIndex(SourceFile, AudioTrackMask, AudioFile, IP, Private, ErrorMsg, MsgSize); } if (av_find_stream_info(FormatContext) < 0) { av_close_input_file(FormatContext); _snprintf(ErrorMsg, MsgSize, "Couldn't find stream information"); - return 2; + return NULL; } // Audio stuff - AudioContext *AudioContexts = new AudioContext[FormatContext->nb_streams]; + int16_t *db; + AudioContext *AudioContexts; + IndexMemory IM = IndexMemory(FormatContext->nb_streams, db, AudioContexts); for (unsigned int i = 0; i < FormatContext->nb_streams; i++) { if (AudioTrackMask & (1 << i) && FormatContext->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) { @@ -247,12 +290,12 @@ int MakeIndex(const char *SourceFile, FrameIndex *TrackIndices, int AudioTrackMa AVCodec *AudioCodec = avcodec_find_decoder(AudioCodecContext->codec_id); if (AudioCodec == NULL) { _snprintf(ErrorMsg, MsgSize, "Audio codec not found"); - return 3; + return NULL; } if (avcodec_open(AudioCodecContext, AudioCodec) < 0) { _snprintf(ErrorMsg, MsgSize, "Could not open audio codec"); - return 4; + return NULL; } } else { AudioTrackMask &= ~(1 << i); @@ -261,14 +304,23 @@ int MakeIndex(const char *SourceFile, FrameIndex *TrackIndices, int AudioTrackMa // + FrameIndex *TrackIndices = new FrameIndex(); + TrackIndices->Decoder = 0; + for (unsigned int i = 0; i < FormatContext->nb_streams; i++) TrackIndices->push_back(FrameInfoVector(FormatContext->streams[i]->time_base.den, FormatContext->streams[i]->time_base.num * 1000)); - int16_t *db = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE*10]; - AVPacket Packet; while (av_read_frame(FormatContext, &Packet) >= 0) { + // Update progress + if (IP) { + if ((*IP)(0, FormatContext->pb->pos, FormatContext->file_size, Private)) { + _snprintf(ErrorMsg, MsgSize, "Cancelled by user"); + return NULL; + } + } + // Only create index entries for video for now to save space if (FormatContext->streams[Packet.stream_index]->codec->codec_type == CODEC_TYPE_VIDEO) (*TrackIndices)[Packet.stream_index].push_back(FrameInfo(Packet.dts, (Packet.flags & PKT_FLAG_KEY) ? 1 : 0)); @@ -283,7 +335,7 @@ int MakeIndex(const char *SourceFile, FrameIndex *TrackIndices, int AudioTrackMa int Ret = avcodec_decode_audio2(AudioCodecContext, db, &dbsize, Data, Size); if (Ret < 0) { _snprintf(ErrorMsg, MsgSize, "Audio decoding error"); - return 5; + return NULL; } if (Ret > 0) { @@ -313,21 +365,18 @@ int MakeIndex(const char *SourceFile, FrameIndex *TrackIndices, int AudioTrackMa av_free_packet(&Packet); } - delete [] db; - delete [] AudioContexts; - av_close_input_file(FormatContext); SortTrackIndices(TrackIndices); - return 0; + return TrackIndices; } -int ReadIndex(const char *IndexFile, FrameIndex *TrackIndices, char *ErrorMsg, unsigned MsgSize) { +FrameIndex *ReadIndex(const char *IndexFile, char *ErrorMsg, unsigned MsgSize) { std::ifstream Index(IndexFile, std::ios::in | std::ios::binary); if (!Index.is_open()) { _snprintf(ErrorMsg, MsgSize, "Failed to open '%s' for reading", IndexFile); - return 1; + return NULL; } // Read the index file header @@ -335,37 +384,44 @@ int ReadIndex(const char *IndexFile, FrameIndex *TrackIndices, char *ErrorMsg, u Index.read(reinterpret_cast(&IH), sizeof(IH)); if (IH.Id != INDEXID) { _snprintf(ErrorMsg, MsgSize, "'%s' is not a valid index file", IndexFile); - return 2; + return NULL; } if (IH.Version != INDEXVERSION) { _snprintf(ErrorMsg, MsgSize, "'%s' is not the expected index version", IndexFile); - return 3; + return NULL; } - TrackIndices->Decoder = IH.Decoder; - TrackIndices->clear(); + FrameIndex *TrackIndices = new FrameIndex(); - for (unsigned int i = 0; i < IH.Tracks; i++) { - // Read how many records belong to the current stream - size_t Frames; - Index.read(reinterpret_cast(&Frames), sizeof(Frames)); - int Num; - Index.read(reinterpret_cast(&Num), sizeof(Num)); - int Den; - Index.read(reinterpret_cast(&Den), sizeof(Den)); - TrackIndices->push_back(FrameInfoVector(Num, Den)); + try { - FrameInfo FI(0, false); - for (size_t j = 0; j < Frames; j++) { - Index.read(reinterpret_cast(&FI), sizeof(FrameInfo)); - TrackIndices->at(i).push_back(FI); + TrackIndices->Decoder = IH.Decoder; + + for (unsigned int i = 0; i < IH.Tracks; i++) { + // Read how many records belong to the current stream + size_t Frames; + Index.read(reinterpret_cast(&Frames), sizeof(Frames)); + int Num; + Index.read(reinterpret_cast(&Num), sizeof(Num)); + int Den; + Index.read(reinterpret_cast(&Den), sizeof(Den)); + TrackIndices->push_back(FrameInfoVector(Num, Den)); + + FrameInfo FI(0, false); + for (size_t j = 0; j < Frames; j++) { + Index.read(reinterpret_cast(&FI), sizeof(FrameInfo)); + TrackIndices->at(i).push_back(FI); + } } + + } catch (...) { + delete TrackIndices; + _snprintf(ErrorMsg, MsgSize, "Unknown error while reading index information in '%s'", IndexFile); + return NULL; } - Index.close(); - - return 0; + return TrackIndices; } FrameInfo::FrameInfo(int64_t DTS, bool KeyFrame) { @@ -410,6 +466,7 @@ int FrameInfoVector::ClosestFrameFromDTS(int64_t DTS) { } int FrameInfoVector::FindClosestKeyFrame(int Frame) { + Frame = FFMIN(FFMAX(Frame, 0), size() - 1); for (int i = Frame; i > 0; i--) if (at(i).KeyFrame) return i; diff --git a/FFmpegSource2/indexing.h b/FFmpegSource2/indexing.h index ec81749bd..fb2734030 100644 --- a/FFmpegSource2/indexing.h +++ b/FFmpegSource2/indexing.h @@ -61,8 +61,8 @@ public: int Decoder; }; -int MakeIndex(const char *SourceFile, FrameIndex *TrackIndices, int AudioTrackMask, const char *AudioFile, IndexProgress *IP, char *ErrorMsg, unsigned MsgSize); -int ReadIndex(const char *IndexFile, FrameIndex *TrackIndices, char *ErrorMsg, unsigned MsgSize); +FrameIndex *MakeIndex(const char *SourceFile, int AudioTrackMask, const char *AudioFile, IndexCallback *IP, void *Private, char *ErrorMsg, unsigned MsgSize); +FrameIndex *ReadIndex(const char *IndexFile, char *ErrorMsg, unsigned MsgSize); int WriteIndex(const char *IndexFile, FrameIndex *TrackIndices, char *ErrorMsg, unsigned MsgSize); #endif