@@ -20,6 +20,7 @@ extern "C" {
2020#include < libavfilter/buffersrc.h>
2121#include < libavformat/avformat.h>
2222#include < libavutil/imgutils.h>
23+ #include < libavutil/log.h>
2324#include < libavutil/pixdesc.h>
2425#include < libswscale/swscale.h>
2526}
@@ -69,6 +70,8 @@ std::vector<std::string> splitStringWithDelimiters(
6970
7071VideoDecoder::VideoDecoder (const std::string& videoFilePath, SeekMode seekMode)
7172 : seekMode_(seekMode) {
73+ av_log_set_level (AV_LOG_QUIET);
74+
7275 AVFormatContext* formatContext = nullptr ;
7376 int open_ret = avformat_open_input (
7477 &formatContext, videoFilePath.c_str (), nullptr , nullptr );
@@ -89,6 +92,8 @@ VideoDecoder::VideoDecoder(const void* buffer, size_t length, SeekMode seekMode)
8992 : seekMode_(seekMode) {
9093 TORCH_CHECK (buffer != nullptr , " Video buffer cannot be nullptr!" );
9194
95+ av_log_set_level (AV_LOG_QUIET);
96+
9297 AVInput input;
9398 input.formatContext .reset (avformat_alloc_context ());
9499 TORCH_CHECK (
@@ -222,6 +227,13 @@ void VideoDecoder::scanFileAndUpdateMetadataAndIndex() {
222227 return ;
223228 }
224229
230+ for (unsigned int i = 0 ; i < formatContext_->nb_streams ; ++i) {
231+ // We want to scan and update the metadata of all streams.
232+ TORCH_CHECK (
233+ formatContext_->streams [i]->discard != AVDISCARD_ALL,
234+ " Did you add a stream before you called for a scan?" );
235+ }
236+
225237 AutoAVPacket autoAVPacket;
226238 while (true ) {
227239 ReferenceAVPacket packet (autoAVPacket);
@@ -481,6 +493,16 @@ void VideoDecoder::addVideoStreamDecoder(
481493 updateMetadataWithCodecContext (streamInfo.streamIndex , codecContext);
482494 streamInfo.videoStreamOptions = videoStreamOptions;
483495
496+ // We will only need packets from the active stream, so we tell FFmpeg to
497+ // discard packets from the other streams. Note that av_read_frame() may still
498+ // return some of those un-desired packet under some conditions, so it's still
499+ // important to discard/demux correctly in the inner decoding loop.
500+ for (unsigned int i = 0 ; i < formatContext_->nb_streams ; ++i) {
501+ if (i != static_cast <unsigned int >(activeStreamIndex_)) {
502+ formatContext_->streams [i]->discard = AVDISCARD_ALL;
503+ }
504+ }
505+
484506 // By default, we want to use swscale for color conversion because it is
485507 // faster. However, it has width requirements, so we may need to fall back
486508 // to filtergraph. We also need to respect what was requested from the
@@ -971,43 +993,44 @@ VideoDecoder::AVFrameStream VideoDecoder::decodeAVFrame(
971993 }
972994
973995 if (reachedEOF) {
974- // We don't have any more packets to send to the decoder . So keep on
975- // pulling frames from its internal buffers.
996+ // We don't have any more packets to receive . So keep on pulling frames
997+ // from its internal buffers.
976998 continue ;
977999 }
9781000
9791001 // We still haven't found the frame we're looking for. So let's read more
9801002 // packets and send them to the decoder.
9811003 ReferenceAVPacket packet (autoAVPacket);
982- ffmpegStatus = av_read_frame (formatContext_.get (), packet.get ());
983- decodeStats_.numPacketsRead ++;
1004+ do {
1005+ ffmpegStatus = av_read_frame (formatContext_.get (), packet.get ());
1006+ decodeStats_.numPacketsRead ++;
1007+
1008+ if (ffmpegStatus == AVERROR_EOF) {
1009+ // End of file reached. We must drain the codec by sending a nullptr
1010+ // packet.
1011+ ffmpegStatus = avcodec_send_packet (
1012+ streamInfo.codecContext .get (),
1013+ /* avpkt=*/ nullptr );
1014+ if (ffmpegStatus < AVSUCCESS) {
1015+ throw std::runtime_error (
1016+ " Could not flush decoder: " +
1017+ getFFMPEGErrorStringFromErrorCode (ffmpegStatus));
1018+ }
1019+
1020+ reachedEOF = true ;
1021+ break ;
1022+ }
9841023
985- if (ffmpegStatus == AVERROR_EOF) {
986- // End of file reached. We must drain the codec by sending a nullptr
987- // packet.
988- ffmpegStatus = avcodec_send_packet (
989- streamInfo.codecContext .get (),
990- /* avpkt=*/ nullptr );
9911024 if (ffmpegStatus < AVSUCCESS) {
9921025 throw std::runtime_error (
993- " Could not flush decoder : " +
1026+ " Could not read frame from input file : " +
9941027 getFFMPEGErrorStringFromErrorCode (ffmpegStatus));
9951028 }
1029+ } while (packet->stream_index != activeStreamIndex_);
9961030
997- // We've reached the end of file so we can't read any more packets from
998- // it, but the decoder may still have frames to read in its buffer.
999- // Continue iterating to try reading frames.
1000- reachedEOF = true ;
1001- continue ;
1002- }
1003-
1004- if (ffmpegStatus < AVSUCCESS) {
1005- throw std::runtime_error (
1006- " Could not read frame from input file: " +
1007- getFFMPEGErrorStringFromErrorCode (ffmpegStatus));
1008- }
1009-
1010- if (packet->stream_index != activeStreamIndex_) {
1031+ if (reachedEOF) {
1032+ // We don't have any more packets to send to the decoder. So keep on
1033+ // pulling frames from its internal buffers.
10111034 continue ;
10121035 }
10131036
0 commit comments