diff --git a/aegisub/libffms/src/core/haaliaudio.cpp b/aegisub/libffms/src/core/haaliaudio.cpp deleted file mode 100644 index 304cdbdb2..000000000 --- a/aegisub/libffms/src/core/haaliaudio.cpp +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright (c) 2007-2009 Fredrik Mellbin -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#ifdef HAALISOURCE - -#include "audiosource.h" - - - -void FFHaaliAudio::Free(bool CloseCodec) { - if (CloseCodec) - avcodec_close(CodecContext); - av_freep(&CodecContext); -} - -void FFHaaliAudio::DecodeNextAudioBlock(int64_t *AFirstStartTime, int64_t *Count) { - const size_t SizeConst = (av_get_bits_per_sample_format(CodecContext->sample_fmt) * CodecContext->channels) / 8; - int Ret = -1; - *AFirstStartTime = -1; - *Count = 0; - uint8_t *Buf = &DecodingBuffer[0]; - AVPacket Packet; - InitNullPacket(Packet); - - for (;;) { - CComPtr pMMF; - if (pMMC->ReadFrame(NULL, &pMMF) != S_OK) - break; - - REFERENCE_TIME Ts, Te; - if (*AFirstStartTime < 0 && SUCCEEDED(pMMF->GetTime(&Ts, &Te))) - *AFirstStartTime = Ts; - - if (pMMF->GetTrack() == AudioTrack) { - BYTE *Data = NULL; - if (FAILED(pMMF->GetPointer(&Data))) - goto Done; - - Packet.data = Data; - Packet.size = pMMF->GetActualDataLength(); - if (pMMF->IsSyncPoint() == S_OK) - Packet.flags = AV_PKT_FLAG_KEY; - else - Packet.flags = 0; - - while (Packet.size > 0) { - int TempOutputBufSize = AVCODEC_MAX_AUDIO_FRAME_SIZE * 10; - Ret = avcodec_decode_audio3(CodecContext, (int16_t *)Buf, &TempOutputBufSize, &Packet); - - if (Ret < 0) {// throw error or something? - goto Done; - } - - if (Ret > 0) { - Packet.size -= Ret; - Packet.data += Ret; - Buf += TempOutputBufSize; - if (SizeConst) - *Count += TempOutputBufSize / SizeConst; - } - } - - goto Done; - } - } - -Done:; -} - -FFHaaliAudio::FFHaaliAudio(const char *SourceFile, int Track, FFMS_Index *Index, enum FFMS_Sources SourceMode) - : Res(FFSourceResources(this)), FFMS_AudioSource(SourceFile, Index, Track) { - AVCodec *Codec = NULL; - CodecContext = NULL; - AudioTrack = Track; - Frames = (*Index)[AudioTrack]; - - pMMC = HaaliOpenFile(SourceFile, SourceMode); - - int CodecPrivateSize = 0; - int CurrentTrack = 0; - CComPtr pEU; - CComQIPtr pBag; - if (SUCCEEDED(pMMC->EnumTracks(&pEU))) { - CComPtr pU; - while (pEU->Next(1, &pU, NULL) == S_OK) { - if (CurrentTrack++ == Track) { - pBag = pU; - - if (pBag) { - CComVariant pV; - - pV.Clear(); - if (SUCCEEDED(pBag->Read(L"CodecPrivate", &pV, NULL))) { - CodecPrivateSize = vtSize(pV); - CodecPrivate.resize(CodecPrivateSize); - vtCopy(pV, FFMS_GET_VECTOR_PTR(CodecPrivate)); - } - - pV.Clear(); - if (SUCCEEDED(pBag->Read(L"CodecID", &pV, NULL)) && SUCCEEDED(pV.ChangeType(VT_BSTR))) { - char ACodecID[2048]; - wcstombs(ACodecID, pV.bstrVal, 2000); - - int BitDepth = 0; - pV.Clear(); - if (SUCCEEDED(pBag->Read(L"Audio.BitDepth", &pV, NULL)) && SUCCEEDED(pV.ChangeType(VT_UI4))) - BitDepth = pV.uintVal; - - Codec = avcodec_find_decoder(MatroskaToFFCodecID(ACodecID, FFMS_GET_VECTOR_PTR(CodecPrivate), 0, BitDepth)); - } - } - } - pU = NULL; - } - } - - CodecContext = avcodec_alloc_context(); - CodecContext->extradata = FFMS_GET_VECTOR_PTR(CodecPrivate); - CodecContext->extradata_size = CodecPrivateSize; - - if (Codec == NULL) - throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC, - "Audio codec not found"); - - InitializeCodecContextFromHaaliInfo(pBag, CodecContext); - - if (avcodec_open(CodecContext, Codec) < 0) - throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC, - "Could not open audio codec"); - - Res.CloseCodec(true); - - // Always try to decode a frame to make sure all required parameters are known - int64_t Dummy1, Dummy2; - DecodeNextAudioBlock(&Dummy1, &Dummy2); - - pMMC->Seek(Frames[0].DTS, MKVF_SEEK_TO_PREV_KEYFRAME_STRICT); - avcodec_flush_buffers(CodecContext); - - FillAP(AP, CodecContext, Frames); - - if (AP.SampleRate <= 0 || AP.BitsPerSample <= 0) - throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC, - "Codec returned zero size audio"); - - AudioCache.Initialize((AP.Channels * AP.BitsPerSample) / 8, 50); -} - -void FFHaaliAudio::GetAudio(void *Buf, int64_t Start, int64_t Count) { - GetAudioCheck(Start, Count); - - const int64_t SizeConst = (av_get_bits_per_sample_format(CodecContext->sample_fmt) * CodecContext->channels) / 8; - memset(Buf, 0, static_cast(SizeConst * Count)); - bool HasSeeked = false; - - int PreDecBlocks = 0; - uint8_t *DstBuf = static_cast(Buf); - - // Fill with everything in the cache - int64_t CacheEnd = AudioCache.FillRequest(Start, Count, DstBuf); - // Was everything in the cache? - if (CacheEnd == Start + Count) - return; - - int CurrentAudioBlock; - // Is seeking required to decode the requested samples? -// if (!(CurrentSample >= Start && CurrentSample <= CacheEnd)) { - if (CurrentSample != CacheEnd) { - PreDecBlocks = 15; - CurrentAudioBlock = FFMAX((int64_t)Frames.FindClosestAudioKeyFrame(CacheEnd) - PreDecBlocks - 20, (int64_t)0); - pMMC->Seek(Frames[CurrentAudioBlock].DTS, MKVF_SEEK_TO_PREV_KEYFRAME_STRICT); - avcodec_flush_buffers(CodecContext); - HasSeeked = true; - } else { - CurrentAudioBlock = Frames.FindClosestAudioKeyFrame(CurrentSample); - } - - int64_t FirstTime, DecodeCount; - - do { - DecodeNextAudioBlock(&FirstTime, &DecodeCount); - - if (HasSeeked) { - CurrentAudioBlock = Frames.ClosestFrameFromDTS(FirstTime); - HasSeeked = false; - } - - // Cache the block if enough blocks before it have been decoded to avoid garbage - if (PreDecBlocks == 0) { - AudioCache.CacheBlock(Frames[CurrentAudioBlock].SampleStart, DecodeCount, &DecodingBuffer[0]); - CacheEnd = AudioCache.FillRequest(CacheEnd, Start + Count - CacheEnd, DstBuf + (CacheEnd - Start) * SizeConst); - } else { - PreDecBlocks--; - } - - CurrentAudioBlock++; - if (CurrentAudioBlock < static_cast(Frames.size())) - CurrentSample = Frames[CurrentAudioBlock].SampleStart; - } while (Start + Count - CacheEnd > 0 && CurrentAudioBlock < static_cast(Frames.size())); -} - -#endif // HAALISOURCE diff --git a/aegisub/libffms/src/core/haaliindexer.cpp b/aegisub/libffms/src/core/haaliindexer.cpp deleted file mode 100644 index 92f6f0290..000000000 --- a/aegisub/libffms/src/core/haaliindexer.cpp +++ /dev/null @@ -1,270 +0,0 @@ -// Copyright (c) 2007-2009 Fredrik Mellbin -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#ifdef HAALISOURCE - -#include "indexing.h" - - - -FFHaaliIndexer::FFHaaliIndexer(const char *Filename, enum FFMS_Sources SourceMode) : FFMS_Indexer(Filename) { - this->SourceMode = SourceMode; - SourceFile = Filename; - Duration = 0; - for (int i = 0; i < 32; i++) { - TrackType[i] = FFMS_TYPE_UNKNOWN; - Codec[i] = NULL; - CodecPrivateSize[i] = 0; - } - - pMMC = HaaliOpenFile(SourceFile, SourceMode); - - CComQIPtr pBag2 = pMMC; - CComVariant pV2; - if (SUCCEEDED(pBag2->Read(L"Duration", &pV2, NULL)) && SUCCEEDED(pV2.ChangeType(VT_UI8))) - Duration = pV2.ullVal; - - NumTracks = 0; - CComPtr pEU; - if (SUCCEEDED(pMMC->EnumTracks(&pEU))) { - CComPtr pU; - while (pEU->Next(1, &pU, NULL) == S_OK) { - CComQIPtr pBag = pU; - PropertyBags[NumTracks] = pBag; - - if (pBag) { - CComVariant pV; - unsigned int FourCC = 0; - - pV.Clear(); - if (SUCCEEDED(pBag->Read(L"Type", &pV, NULL)) && SUCCEEDED(pV.ChangeType(VT_UI4))) - TrackType[NumTracks] = HaaliTrackTypeToFFTrackType(pV.uintVal); - - pV.Clear(); - if (SUCCEEDED(pBag->Read(L"CodecPrivate", &pV, NULL))) { - CodecPrivateSize[NumTracks] = vtSize(pV); - CodecPrivate[NumTracks].resize(CodecPrivateSize[NumTracks]); - vtCopy(pV, FFMS_GET_VECTOR_PTR(CodecPrivate[NumTracks])); - } - - pV.Clear(); - if (SUCCEEDED(pBag->Read(L"FOURCC", &pV, NULL)) && SUCCEEDED(pV.ChangeType(VT_UI4))) { - FourCC = pV.uintVal; - - // Reconstruct the missing codec private part for VC1 - std::vector bihvect; - bihvect.resize(sizeof(FFMS_BITMAPINFOHEADER)); - FFMS_BITMAPINFOHEADER *bih = reinterpret_cast(FFMS_GET_VECTOR_PTR(bihvect)); - memset(bih, 0, sizeof(FFMS_BITMAPINFOHEADER)); - bih->biSize = sizeof(FFMS_BITMAPINFOHEADER) + CodecPrivateSize[NumTracks]; - bih->biCompression = FourCC; - bih->biBitCount = 24; - bih->biPlanes = 1; - - pV.Clear(); - if (SUCCEEDED(pBag->Read(L"Video.PixelWidth", &pV, NULL)) && SUCCEEDED(pV.ChangeType(VT_UI4))) - bih->biWidth = pV.uintVal; - - pV.Clear(); - if (SUCCEEDED(pBag->Read(L"Video.PixelHeight", &pV, NULL)) && SUCCEEDED(pV.ChangeType(VT_UI4))) - bih->biHeight = pV.uintVal; - - CodecPrivate[NumTracks].insert(CodecPrivate[NumTracks].begin(), bihvect.begin(), bihvect.end()); - CodecPrivateSize[NumTracks] += sizeof(FFMS_BITMAPINFOHEADER); - } - - pV.Clear(); - if (SUCCEEDED(pBag->Read(L"CodecID", &pV, NULL)) && SUCCEEDED(pV.ChangeType(VT_BSTR))) { - char CodecStr[2048]; - wcstombs(CodecStr, pV.bstrVal, 2000); - - int BitDepth = 0; - pV.Clear(); - if (SUCCEEDED(pBag->Read(L"Audio.BitDepth", &pV, NULL)) && SUCCEEDED(pV.ChangeType(VT_UI4))) - BitDepth = pV.uintVal; - - Codec[NumTracks] = avcodec_find_decoder(MatroskaToFFCodecID(CodecStr, FFMS_GET_VECTOR_PTR(CodecPrivate[NumTracks]), FourCC, BitDepth)); - } - } - - pU = NULL; - NumTracks++; - } - } -} - -FFMS_Index *FFHaaliIndexer::DoIndexing() { - std::vector AudioContexts(NumTracks, SharedAudioContext(true)); - std::vector VideoContexts(NumTracks, SharedVideoContext(true)); - - std::auto_ptr TrackIndices(new FFMS_Index(Filesize, Digest)); - TrackIndices->Decoder = FFMS_SOURCE_HAALIMPEG; - if (SourceMode == FFMS_SOURCE_HAALIOGG) - TrackIndices->Decoder = FFMS_SOURCE_HAALIOGG; - - for (int i = 0; i < NumTracks; i++) { - TrackIndices->push_back(FFMS_Track(1, 1000000, TrackType[i])); - - if (TrackType[i] == FFMS_TYPE_VIDEO && Codec[i] && (VideoContexts[i].Parser = av_parser_init(Codec[i]->id))) { - - AVCodecContext *CodecContext = avcodec_alloc_context(); - CodecContext->extradata = FFMS_GET_VECTOR_PTR(CodecPrivate[i]); - CodecContext->extradata_size = CodecPrivateSize[i]; - - InitializeCodecContextFromHaaliInfo(PropertyBags[i], CodecContext); - - if (avcodec_open(CodecContext, Codec[i]) < 0) { - av_freep(&CodecContext); - throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_DECODING, - "Could not open video codec"); - } - - VideoContexts[i].CodecContext = CodecContext; - VideoContexts[i].Parser->flags = PARSER_FLAG_COMPLETE_FRAMES; - } - - if (IndexMask & (1 << i) && TrackType[i] == FFMS_TYPE_AUDIO) { - if (Codec[i] == NULL) - throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_UNSUPPORTED, - "Audio codec not found"); - - AVCodecContext *CodecContext = avcodec_alloc_context(); - CodecContext->extradata = FFMS_GET_VECTOR_PTR(CodecPrivate[i]); - CodecContext->extradata_size = CodecPrivateSize[i]; - AudioContexts[i].CodecContext = CodecContext; - - if (avcodec_open(CodecContext, Codec[i]) < 0) { - av_freep(&CodecContext); - AudioContexts[i].CodecContext = NULL; - throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_DECODING, - "Could not open audio codec"); - } - } else { - IndexMask &= ~(1 << i); - } - } -// - - AVPacket TempPacket; - InitNullPacket(TempPacket); - - for (;;) { - CComPtr pMMF; - if (pMMC->ReadFrame(NULL, &pMMF) != S_OK) - break; - - REFERENCE_TIME Ts, Te; - HRESULT hr = pMMF->GetTime(&Ts, &Te); - - if (IC) { - if (Duration > 0) { - if (SUCCEEDED(hr)) { - if ((*IC)(Ts, Duration, ICPrivate)) - throw FFMS_Exception(FFMS_ERROR_CANCELLED, FFMS_ERROR_USER, - "Cancelled by user"); - } - } else { - if ((*IC)(0, 1, ICPrivate)) - throw FFMS_Exception(FFMS_ERROR_CANCELLED, FFMS_ERROR_USER, - "Cancelled by user"); - } - } - - unsigned int Track = pMMF->GetTrack(); - pMMF->GetPointer(&TempPacket.data); - TempPacket.size = pMMF->GetActualDataLength(); - - // Only create index entries for video for now to save space - if (TrackType[Track] == FFMS_TYPE_VIDEO) { - uint8_t *OB; - int OBSize; - int RepeatPict = -1; - - if (VideoContexts[Track].Parser) { - av_parser_parse2(VideoContexts[Track].Parser, VideoContexts[Track].CodecContext, &OB, &OBSize, TempPacket.data, TempPacket.size, ffms_av_nopts_value, ffms_av_nopts_value, ffms_av_nopts_value); - RepeatPict = VideoContexts[Track].Parser->repeat_pict; - } - - (*TrackIndices)[Track].push_back(TFrameInfo::VideoFrameInfo(Ts, RepeatPict, pMMF->IsSyncPoint() == S_OK)); - } else if (TrackType[Track] == FFMS_TYPE_AUDIO && (IndexMask & (1 << Track))) { - int64_t StartSample = AudioContexts[Track].CurrentSample; - AVCodecContext *AudioCodecContext = AudioContexts[Track].CodecContext; - - if (pMMF->IsSyncPoint() == S_OK) - TempPacket.flags = AV_PKT_FLAG_KEY; - else - TempPacket.flags = 0; - - while (TempPacket.size > 0) { - int dbsize = AVCODEC_MAX_AUDIO_FRAME_SIZE*10; - int Ret = avcodec_decode_audio3(AudioCodecContext, &DecodingBuffer[0], &dbsize, &TempPacket); - if (Ret < 0) { - if (ErrorHandling == FFMS_IEH_ABORT) { - throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_DECODING, - "Audio decoding error"); - } else if (ErrorHandling == FFMS_IEH_CLEAR_TRACK) { - (*TrackIndices)[Track].clear(); - IndexMask &= ~(1 << Track); - break; - } else if (ErrorHandling == FFMS_IEH_STOP_TRACK) { - IndexMask &= ~(1 << Track); - break; - } else if (ErrorHandling == FFMS_IEH_IGNORE) { - break; - } - } - - if (Ret > 0) { - TempPacket.size -= Ret; - TempPacket.data += Ret; - } - - if (dbsize > 0) - AudioContexts[Track].CurrentSample += (dbsize * 8) / (av_get_bits_per_sample_format(AudioCodecContext->sample_fmt) * AudioCodecContext->channels); - - if (DumpMask & (1 << Track)) - WriteAudio(AudioContexts[Track], TrackIndices.get(), Track, dbsize); - } - - (*TrackIndices)[Track].push_back(TFrameInfo::AudioFrameInfo(Ts, StartSample, - static_cast(AudioContexts[Track].CurrentSample - StartSample), pMMF->IsSyncPoint() == S_OK)); - } - } - - TrackIndices->Sort(); - return TrackIndices.release(); -} - -int FFHaaliIndexer::GetNumberOfTracks() { - return NumTracks; -} - -FFMS_TrackType FFHaaliIndexer::GetTrackType(int Track) { - return TrackType[Track]; -} - -const char *FFHaaliIndexer::GetTrackCodec(int Track) { - if (Codec[Track]) - return Codec[Track]->name; - else - return "Unsupported codec/Unknown codec name"; -} - -#endif diff --git a/aegisub/libffms/src/core/haalivideo.cpp b/aegisub/libffms/src/core/haalivideo.cpp deleted file mode 100644 index 375ef2eb8..000000000 --- a/aegisub/libffms/src/core/haalivideo.cpp +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright (c) 2007-2009 Fredrik Mellbin -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#ifdef HAALISOURCE - -#include "videosource.h" - - - -void FFHaaliVideo::Free(bool CloseCodec) { - if (CloseCodec) - avcodec_close(CodecContext); - av_freep(&CodecContext); - if (BitStreamFilter) - av_bitstream_filter_close(BitStreamFilter); -} - -FFHaaliVideo::FFHaaliVideo(const char *SourceFile, int Track, - FFMS_Index *Index, int Threads, enum FFMS_Sources SourceMode) - : Res(FFSourceResources(this)), FFMS_VideoSource(SourceFile, Index, Track) { - - BitStreamFilter = NULL; - AVCodec *Codec = NULL; - CodecContext = NULL; - VideoTrack = Track; - Frames = (*Index)[VideoTrack]; - - pMMC = HaaliOpenFile(SourceFile, SourceMode); - - int CodecPrivateSize = 0; - int CurrentTrack = 0; - CComPtr pEU; - CComQIPtr pBag; - if (SUCCEEDED(pMMC->EnumTracks(&pEU))) { - CComPtr pU; - while (pEU->Next(1, &pU, NULL) == S_OK) { - if (CurrentTrack++ == Track) { - pBag = pU; - - if (pBag) { - CComVariant pV; - unsigned int FourCC = 0; - - pV.Clear(); - if (SUCCEEDED(pBag->Read(L"CodecPrivate", &pV, NULL))) { - CodecPrivateSize = vtSize(pV); - CodecPrivate.resize(CodecPrivateSize); - vtCopy(pV, FFMS_GET_VECTOR_PTR(CodecPrivate)); - } - - pV.Clear(); - if (SUCCEEDED(pBag->Read(L"FOURCC", &pV, NULL)) && SUCCEEDED(pV.ChangeType(VT_UI4))) { - FourCC = pV.uintVal; - - // Reconstruct the missing codec private part for VC1 - std::vector bihvect; - bihvect.resize(sizeof(FFMS_BITMAPINFOHEADER)); - FFMS_BITMAPINFOHEADER *bih = reinterpret_cast(FFMS_GET_VECTOR_PTR(bihvect)); - memset(bih, 0, sizeof(FFMS_BITMAPINFOHEADER)); - bih->biSize = sizeof(FFMS_BITMAPINFOHEADER) + CodecPrivateSize; - bih->biCompression = FourCC; - bih->biBitCount = 24; - bih->biPlanes = 1; - - pV.Clear(); - if (SUCCEEDED(pBag->Read(L"Video.PixelWidth", &pV, NULL)) && SUCCEEDED(pV.ChangeType(VT_UI4))) - bih->biWidth = pV.uintVal; - - pV.Clear(); - if (SUCCEEDED(pBag->Read(L"Video.PixelHeight", &pV, NULL)) && SUCCEEDED(pV.ChangeType(VT_UI4))) - bih->biHeight = pV.uintVal; - - CodecPrivate.insert(CodecPrivate.begin(), bihvect.begin(), bihvect.end()); - CodecPrivateSize += sizeof(FFMS_BITMAPINFOHEADER); - } - - pV.Clear(); - if (SUCCEEDED(pBag->Read(L"CodecID", &pV, NULL)) && SUCCEEDED(pV.ChangeType(VT_BSTR))) { - char ACodecID[2048]; - wcstombs(ACodecID, pV.bstrVal, 2000); - Codec = avcodec_find_decoder(MatroskaToFFCodecID(ACodecID, FFMS_GET_VECTOR_PTR(CodecPrivate), FourCC)); - } - } - } - pU = NULL; - } - } - - CodecContext = avcodec_alloc_context(); - CodecContext->extradata = FFMS_GET_VECTOR_PTR(CodecPrivate); - CodecContext->extradata_size = CodecPrivateSize; - CodecContext->thread_count = Threads; - - if (Codec == NULL) - throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC, - "Video codec not found"); - - InitializeCodecContextFromHaaliInfo(pBag, CodecContext); - - if (avcodec_open(CodecContext, Codec) < 0) - throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC, - "Could not open video codec"); - - if (Codec->id == CODEC_ID_H264 && SourceMode == FFMS_SOURCE_HAALIMPEG) - BitStreamFilter = av_bitstream_filter_init("h264_mp4toannexb"); - - Res.CloseCodec(true); - - // Always try to decode a frame to make sure all required parameters are known - int64_t Dummy; - DecodeNextFrame(&Dummy); - - VP.FPSDenominator = 1; - VP.FPSNumerator = 30; - VP.RFFDenominator = CodecContext->time_base.num; - VP.RFFNumerator = CodecContext->time_base.den; - VP.NumFrames = Frames.size(); - VP.TopFieldFirst = DecodeFrame->top_field_first; -#ifdef FFMS_HAVE_FFMPEG_COLORSPACE_INFO - VP.ColorSpace = CodecContext->colorspace; - VP.ColorRange = CodecContext->color_range; -#else - VP.ColorSpace = 0; - VP.ColorRange = 0; -#endif - VP.FirstTime = ((Frames.front().DTS * Frames.TB.Num) / (double)Frames.TB.Den) / 1000; - VP.LastTime = ((Frames.back().DTS * Frames.TB.Num) / (double)Frames.TB.Den) / 1000; - - if (CodecContext->width <= 0 || CodecContext->height <= 0) - throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC, - "Codec returned zero size video"); - - // Calculate the average framerate - if (Frames.size() >= 2) { - double DTSDiff = (double)(Frames.back().DTS - Frames.front().DTS); - VP.FPSDenominator = (unsigned int)(DTSDiff / (double)1000 / (double)(VP.NumFrames - 1) + 0.5); - VP.FPSNumerator = 1000000; - } - - // Output the already decoded frame so it isn't wasted - OutputFrame(DecodeFrame); - - // Set AR variables - CComVariant pV; - - pV.Clear(); - if (SUCCEEDED(pBag->Read(L"Video.DisplayWidth", &pV, NULL)) && SUCCEEDED(pV.ChangeType(VT_UI4))) - VP.SARNum = pV.uiVal; - pV.Clear(); - if (SUCCEEDED(pBag->Read(L"Video.DisplayHeight", &pV, NULL)) && SUCCEEDED(pV.ChangeType(VT_UI4))) - VP.SARDen = pV.uiVal; -} - -void FFHaaliVideo::DecodeNextFrame(int64_t *AFirstStartTime) { - int FrameFinished = 0; - *AFirstStartTime = -1; - AVPacket Packet; - InitNullPacket(Packet); - - for (;;) { - CComPtr pMMF; - if (pMMC->ReadFrame(NULL, &pMMF) != S_OK) - break; - - REFERENCE_TIME Ts, Te; - if (*AFirstStartTime < 0 && SUCCEEDED(pMMF->GetTime(&Ts, &Te))) - *AFirstStartTime = Ts; - - if (pMMF->GetTrack() == VideoTrack) { - BYTE *Data = NULL; - if (FAILED(pMMF->GetPointer(&Data))) - goto Error; - - Packet.data = Data; - Packet.size = pMMF->GetActualDataLength(); - if (pMMF->IsSyncPoint() == S_OK) - Packet.flags = AV_PKT_FLAG_KEY; - else - Packet.flags = 0; - - if (BitStreamFilter) - av_bitstream_filter_filter(BitStreamFilter, CodecContext, NULL, - &Packet.data, &Packet.size, Data, pMMF->GetActualDataLength(), !!Packet.flags); - - if (CodecContext->codec_id == CODEC_ID_MPEG4 && IsNVOP(Packet)) - goto Done; - - avcodec_decode_video2(CodecContext, DecodeFrame, &FrameFinished, &Packet); - - if (FrameFinished) - goto Done; - } - } - - // Flush the last frames - if (CodecContext->has_b_frames) { - AVPacket NullPacket; - InitNullPacket(NullPacket); - avcodec_decode_video2(CodecContext, DecodeFrame, &FrameFinished, &NullPacket); - } - - if (!FrameFinished) - goto Error; - -Error: -Done:; -} - -FFMS_Frame *FFHaaliVideo::GetFrame(int n) { - GetFrameCheck(n); - - if (LastFrameNum == n) - return &LocalFrame; - - bool HasSeeked = false; - int SeekOffset = 0; - - if (n < CurrentFrame || Frames.FindClosestVideoKeyFrame(n) > CurrentFrame + 10) { -ReSeek: - pMMC->Seek(Frames[n + SeekOffset].DTS, MMSF_PREV_KF); - avcodec_flush_buffers(CodecContext); - HasSeeked = true; - } - - do { - int64_t StartTime; - DecodeNextFrame(&StartTime); - - if (HasSeeked) { - HasSeeked = false; - - if (StartTime < 0 || (CurrentFrame = Frames.FrameFromDTS(StartTime)) < 0) { - // No idea where we are so go back a bit further - if (n + SeekOffset == 0) - throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC, - "Frame accurate seeking is not possible in this file"); - - SeekOffset -= FFMIN(20, n + SeekOffset); - goto ReSeek; - } - } - - CurrentFrame++; - } while (CurrentFrame <= n); - - LastFrameNum = n; - return OutputFrame(DecodeFrame); -} - -#endif // HAALISOURCE