# source: https://github.com/FFMS/ffms2/pull/380 diff --git a/configure.ac b/configure.ac index b35ef80bcd..d19714d0f6 100644 --- a/configure.ac +++ b/configure.ac @@ -102,10 +102,10 @@ CFLAGS="$_CFLAGS $FFMPEG_CFLAGS" AC_DEFUN([TEST_FFMPEG], [AC_LINK_IFELSE([AC_LANG_PROGRAM([[ - #include + #include #include ]],[[ - avcodec_register_all(); + avformat_network_init(); swscale_version(); ]])], [eval $1=yes], [eval $1=no]) ]) diff --git a/src/core/audiosource.cpp b/src/core/audiosource.cpp index 37cf9aeefd..ac0966636f 100644 --- a/src/core/audiosource.cpp +++ b/src/core/audiosource.cpp @@ -285,10 +285,15 @@ FFMS_AudioSource::AudioBlock *FFMS_AudioSource::CacheBlock(CacheIterator &pos) { int FFMS_AudioSource::DecodeNextBlock(CacheIterator *pos) { CurrentFrame = &Frames[PacketNumber]; - AVPacket Packet; - if (!ReadPacket(&Packet)) + AVPacket *Packet = av_packet_alloc(); + if (!Packet) + throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_ALLOCATION_FAILED, + "Could not allocate packet."); + if (!ReadPacket(Packet)) { + av_packet_free(&Packet); throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_UNKNOWN, "ReadPacket unexpectedly failed to read a packet"); + } // ReadPacket may have changed the packet number CurrentFrame = &Frames[PacketNumber]; @@ -297,8 +302,9 @@ int FFMS_AudioSource::DecodeNextBlock(CacheIterator *pos) { int NumberOfSamples = 0; AudioBlock *CachedBlock = nullptr; - int Ret = avcodec_send_packet(CodecContext, &Packet); - av_packet_unref(&Packet); + int Ret = avcodec_send_packet(CodecContext, Packet); + av_packet_unref(Packet); + av_packet_free(&Packet); av_frame_unref(DecodeFrame); Ret = avcodec_receive_frame(CodecContext, DecodeFrame); @@ -463,7 +469,7 @@ void FFMS_AudioSource::OpenFile() { LAVFOpenFile(SourceFile.c_str(), FormatContext, TrackNumber); - AVCodec *Codec = avcodec_find_decoder(FormatContext->streams[TrackNumber]->codecpar->codec_id); + auto *Codec = avcodec_find_decoder(FormatContext->streams[TrackNumber]->codecpar->codec_id); if (Codec == nullptr) throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC, "Audio codec not found"); @@ -513,8 +519,6 @@ void FFMS_AudioSource::Seek() { } bool FFMS_AudioSource::ReadPacket(AVPacket *Packet) { - InitNullPacket(*Packet); - while (av_read_frame(FormatContext, Packet) >= 0) { if (Packet->stream_index == TrackNumber) { // Required because not all audio packets, especially in ogg, have a pts. Use the previous valid packet's pts instead. diff --git a/src/core/indexing.cpp b/src/core/indexing.cpp index 23fb95b128..59fb4e8ea8 100644 --- a/src/core/indexing.cpp +++ b/src/core/indexing.cpp @@ -320,7 +320,7 @@ void FFMS_Indexer::CheckAudioProperties(int Track, AVCodecContext *Context) { } } -void FFMS_Indexer::ParseVideoPacket(SharedAVContext &VideoContext, AVPacket &pkt, int *RepeatPict, +void FFMS_Indexer::ParseVideoPacket(SharedAVContext &VideoContext, AVPacket *pkt, int *RepeatPict, int *FrameType, bool *Invisible, enum AVPictureStructure *LastPicStruct) { if (VideoContext.Parser) { uint8_t *OB; @@ -330,8 +330,8 @@ void FFMS_Indexer::ParseVideoPacket(SharedAVContext &VideoContext, AVPacket &pkt av_parser_parse2(VideoContext.Parser, VideoContext.CodecContext, &OB, &OBSize, - pkt.data, pkt.size, - pkt.pts, pkt.dts, pkt.pos); + pkt->data, pkt->size, + pkt->pts, pkt->dts, pkt->pos); // H.264 (PAFF) and HEVC may have one field per packet, so we need to track // when we have a full or half frame available, and mark one of them as @@ -351,15 +351,15 @@ void FFMS_Indexer::ParseVideoPacket(SharedAVContext &VideoContext, AVPacket &pkt *RepeatPict = VideoContext.Parser->repeat_pict; *FrameType = VideoContext.Parser->pict_type; - *Invisible = (IncompleteFrame || VideoContext.Parser->repeat_pict < 0 || (pkt.flags & AV_PKT_FLAG_DISCARD)); + *Invisible = (IncompleteFrame || VideoContext.Parser->repeat_pict < 0 || (pkt->flags & AV_PKT_FLAG_DISCARD)); } else { - *Invisible = !!(pkt.flags & AV_PKT_FLAG_DISCARD); + *Invisible = !!(pkt->flags & AV_PKT_FLAG_DISCARD); } if (VideoContext.CodecContext->codec_id == AV_CODEC_ID_VP8) - ParseVP8(pkt.data[0], Invisible, FrameType); + ParseVP8(pkt->data[0], Invisible, FrameType); else if (VideoContext.CodecContext->codec_id == AV_CODEC_ID_VP9) - ParseVP9(pkt.data[0], Invisible, FrameType); + ParseVP9(pkt->data[0], Invisible, FrameType); } void FFMS_Indexer::Free() { @@ -384,7 +384,7 @@ FFMS_TrackType FFMS_Indexer::GetTrackType(int Track) { } const char *FFMS_Indexer::GetTrackCodec(int Track) { - AVCodec *codec = avcodec_find_decoder(FormatContext->streams[Track]->codecpar->codec_id); + auto *codec = avcodec_find_decoder(FormatContext->streams[Track]->codecpar->codec_id); return codec ? codec->name : nullptr; } @@ -402,7 +402,7 @@ FFMS_Index *FFMS_Indexer::DoIndexing() { UseDTS); if (IndexMask.count(i) && FormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { - AVCodec *VideoCodec = avcodec_find_decoder(FormatContext->streams[i]->codecpar->codec_id); + auto *VideoCodec = avcodec_find_decoder(FormatContext->streams[i]->codecpar->codec_id); if (!VideoCodec) { FormatContext->streams[i]->discard = AVDISCARD_ALL; IndexMask.erase(i); @@ -433,7 +433,7 @@ FFMS_Index *FFMS_Indexer::DoIndexing() { IndexMask.insert(i); } } else if (IndexMask.count(i) && FormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - AVCodec *AudioCodec = avcodec_find_decoder(FormatContext->streams[i]->codecpar->codec_id); + auto *AudioCodec = avcodec_find_decoder(FormatContext->streams[i]->codecpar->codec_id); if (AudioCodec == nullptr) throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_UNSUPPORTED, "Audio codec not found"); @@ -458,32 +458,36 @@ FFMS_Index *FFMS_Indexer::DoIndexing() { } } - AVPacket Packet; - InitNullPacket(Packet); + AVPacket *Packet = av_packet_alloc(); + if (!Packet) + throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_ALLOCATION_FAILED, + "Could not allocate packet."); std::vector LastValidTS(FormatContext->nb_streams, AV_NOPTS_VALUE); int64_t filesize = avio_size(FormatContext->pb); enum AVPictureStructure LastPicStruct = AV_PICTURE_STRUCTURE_UNKNOWN; - while (av_read_frame(FormatContext, &Packet) >= 0) { + while (av_read_frame(FormatContext, Packet) >= 0) { // Update progress // FormatContext->pb can apparently be NULL when opening images. if (IC && FormatContext->pb) { - if ((*IC)(FormatContext->pb->pos, filesize, ICPrivate)) + if ((*IC)(FormatContext->pb->pos, filesize, ICPrivate)) { + av_packet_free(&Packet); throw FFMS_Exception(FFMS_ERROR_CANCELLED, FFMS_ERROR_USER, "Cancelled by user"); + } } - if (!IndexMask.count(Packet.stream_index)) { - av_packet_unref(&Packet); + if (!IndexMask.count(Packet->stream_index)) { + av_packet_unref(Packet); continue; } - int Track = Packet.stream_index; + int Track = Packet->stream_index; FFMS_Track &TrackInfo = (*TrackIndices)[Track]; - bool KeyFrame = !!(Packet.flags & AV_PKT_FLAG_KEY); + bool KeyFrame = !!(Packet->flags & AV_PKT_FLAG_KEY); ReadTS(Packet, LastValidTS[Track], (*TrackIndices)[Track].UseDTS); if (FormatContext->streams[Track]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { - int64_t PTS = TrackInfo.UseDTS ? Packet.dts : Packet.pts; + int64_t PTS = TrackInfo.UseDTS ? Packet->dts : Packet->pts; if (PTS == AV_NOPTS_VALUE) { // VPx alt-refs are output as packets which lack timestmps or durations, since // they are invisible. Currently, the timestamp mangling code in libavformat @@ -495,9 +499,11 @@ FFMS_Index *FFMS_Indexer::DoIndexing() { // FFMS2 currently sorts packets by PTS, which will break decoding, otherwise. bool HasAltRefs = (FormatContext->streams[Track]->codecpar->codec_id == AV_CODEC_ID_VP8 || FormatContext->streams[Track]->codecpar->codec_id == AV_CODEC_ID_VP9); - if (Packet.duration == 0 && !HasAltRefs) + if (Packet->duration == 0 && !HasAltRefs) { + av_packet_free(&Packet); throw FFMS_Exception(FFMS_ERROR_INDEXING, FFMS_ERROR_PARSER, "Invalid packet pts, dts, and duration"); + } if (TrackInfo.empty()) PTS = 0; @@ -513,7 +519,7 @@ FFMS_Index *FFMS_Indexer::DoIndexing() { ParseVideoPacket(AVContexts[Track], Packet, &RepeatPict, &FrameType, &Invisible, &LastPicStruct); TrackInfo.AddVideoFrame(PTS, RepeatPict, KeyFrame, - FrameType, Packet.pos, Invisible); + FrameType, Packet->pos, Invisible); } else if (FormatContext->streams[Track]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { // For video seeking timestamps are used only if all packets have // timestamps, while for audio they're used if any have timestamps, @@ -522,28 +528,29 @@ FFMS_Index *FFMS_Indexer::DoIndexing() { TrackInfo.HasTS = true; int64_t StartSample = AVContexts[Track].CurrentSample; - uint32_t SampleCount = IndexAudioPacket(Track, &Packet, AVContexts[Track], *TrackIndices); + uint32_t SampleCount = IndexAudioPacket(Track, Packet, AVContexts[Track], *TrackIndices); TrackInfo.SampleRate = AVContexts[Track].CodecContext->sample_rate; TrackInfo.AddAudioFrame(LastValidTS[Track], - StartSample, SampleCount, KeyFrame, Packet.pos, Packet.flags & AV_PKT_FLAG_DISCARD); + StartSample, SampleCount, KeyFrame, Packet->pos, Packet->flags & AV_PKT_FLAG_DISCARD); } - if (!(Packet.flags & AV_PKT_FLAG_DISCARD)) - TrackInfo.LastDuration = Packet.duration; + if (!(Packet->flags & AV_PKT_FLAG_DISCARD)) + TrackInfo.LastDuration = Packet->duration; - av_packet_unref(&Packet); + av_packet_unref(Packet); } + av_packet_free(&Packet); TrackIndices->Finalize(AVContexts, FormatContext->iformat->name); return TrackIndices.release(); } -void FFMS_Indexer::ReadTS(const AVPacket &Packet, int64_t &TS, bool &UseDTS) { - if (!UseDTS && Packet.pts != AV_NOPTS_VALUE) - TS = Packet.pts; +void FFMS_Indexer::ReadTS(const AVPacket *Packet, int64_t &TS, bool &UseDTS) { + if (!UseDTS && Packet->pts != AV_NOPTS_VALUE) + TS = Packet->pts; if (TS == AV_NOPTS_VALUE) UseDTS = true; - if (UseDTS && Packet.dts != AV_NOPTS_VALUE) - TS = Packet.dts; + if (UseDTS && Packet->dts != AV_NOPTS_VALUE) + TS = Packet->dts; } diff --git a/src/core/indexing.h b/src/core/indexing.h index 3cfc3c30b3..5c06868890 100644 --- a/src/core/indexing.h +++ b/src/core/indexing.h @@ -80,10 +80,10 @@ struct FFMS_Indexer { int64_t Filesize; uint8_t Digest[20]; - void ReadTS(const AVPacket &Packet, int64_t &TS, bool &UseDTS); + void ReadTS(const AVPacket *Packet, int64_t &TS, bool &UseDTS); void CheckAudioProperties(int Track, AVCodecContext *Context); uint32_t IndexAudioPacket(int Track, AVPacket *Packet, SharedAVContext &Context, FFMS_Index &TrackIndices); - void ParseVideoPacket(SharedAVContext &VideoContext, AVPacket &pkt, int *RepeatPict, int *FrameType, bool *Invisible, enum AVPictureStructure *LastPicStruct); + void ParseVideoPacket(SharedAVContext &VideoContext, AVPacket *pkt, int *RepeatPict, int *FrameType, bool *Invisible, enum AVPictureStructure *LastPicStruct); void Free(); public: FFMS_Indexer(const char *Filename); diff --git a/src/core/utils.cpp b/src/core/utils.cpp index ce67533fd7..8a2e99710e 100644 --- a/src/core/utils.cpp +++ b/src/core/utils.cpp @@ -62,12 +62,6 @@ void ClearErrorInfo(FFMS_ErrorInfo *ErrorInfo) { } } -void InitNullPacket(AVPacket &pkt) { - av_init_packet(&pkt); - pkt.data = nullptr; - pkt.size = 0; -} - void FillAP(FFMS_AudioProperties &AP, AVCodecContext *CTX, FFMS_Track &Frames) { AP.SampleFormat = static_cast(av_get_packed_sample_fmt(CTX->sample_fmt)); AP.BitsPerSample = av_get_bytes_per_sample(CTX->sample_fmt) * 8; diff --git a/src/core/utils.h b/src/core/utils.h index 9819dc7c9e..003ab794e9 100644 --- a/src/core/utils.h +++ b/src/core/utils.h @@ -58,7 +58,6 @@ std::unique_ptr make_unique(Args&&... args) { } void ClearErrorInfo(FFMS_ErrorInfo *ErrorInfo); -void InitNullPacket(AVPacket &pkt); void FillAP(FFMS_AudioProperties &AP, AVCodecContext *CTX, FFMS_Track &Frames); void LAVFOpenFile(const char *SourceFile, AVFormatContext *&FormatContext, int Track); diff --git a/src/core/videosource.cpp b/src/core/videosource.cpp index 06bd1610e1..8956c22566 100644 --- a/src/core/videosource.cpp +++ b/src/core/videosource.cpp @@ -171,7 +171,7 @@ FFMS_VideoSource::FFMS_VideoSource(const char *SourceFile, FFMS_Index &Index, in LAVFOpenFile(SourceFile, FormatContext, VideoTrack); - AVCodec *Codec = avcodec_find_decoder(FormatContext->streams[VideoTrack]->codecpar->codec_id); + auto *Codec = avcodec_find_decoder(FormatContext->streams[VideoTrack]->codecpar->codec_id); if (Codec == nullptr) throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC, "Video codec not found"); @@ -673,30 +673,34 @@ void FFMS_VideoSource::DecodeNextFrame(int64_t &AStartTime, int64_t &Pos) { if (HasPendingDelayedFrames()) return; - AVPacket Packet; - InitNullPacket(Packet); + AVPacket *Packet = av_packet_alloc(); + if (!Packet) + throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_ALLOCATION_FAILED, + "Could not allocate packet."); - while (ReadFrame(&Packet) >= 0) { - if (Packet.stream_index != VideoTrack) { - av_packet_unref(&Packet); + while (ReadFrame(Packet) >= 0) { + if (Packet->stream_index != VideoTrack) { + av_packet_unref(Packet); continue; } if (AStartTime < 0) - AStartTime = Frames.UseDTS ? Packet.dts : Packet.pts; + AStartTime = Frames.UseDTS ? Packet->dts : Packet->pts; if (Pos < 0) - Pos = Packet.pos; + Pos = Packet->pos; - bool FrameFinished = DecodePacket(&Packet); - av_packet_unref(&Packet); - if (FrameFinished) + bool FrameFinished = DecodePacket(Packet); + av_packet_unref(Packet); + if (FrameFinished) { + av_packet_free(&Packet); return; + } } // Flush final frames - InitNullPacket(Packet); - DecodePacket(&Packet); + DecodePacket(Packet); + av_packet_free(&Packet); } bool FFMS_VideoSource::SeekTo(int n, int SeekOffset) {