@@ -285,6 +285,8 @@ bool Decoder::init(
285285 return false ;
286286 }
287287
288+ avioCtx_->max_packet_size = params.maxEncodedBufferSize ;
289+
288290 inputCtx_->pb = avioCtx_;
289291 inputCtx_->flags |= AVFMT_FLAG_CUSTOM_IO;
290292 }
@@ -382,7 +384,30 @@ bool Decoder::init(
382384 av_seek_frame (inputCtx_, -1 , offset, AVSEEK_FLAG_BACKWARD);
383385 }
384386
387+ for (unsigned int i = 0 ; i < inputCtx_->nb_streams ; i++) {
388+ if (
389+ #if LIBAVUTIL_VERSION_MAJOR < 56 // Before FFMPEG 4.0
390+ inputCtx_->streams [i]->codec ->codec_type == AVMEDIA_TYPE_VIDEO
391+ #else // FFMPEG 4.0+
392+ inputCtx_->streams [i]->codecpar ->codec_type == AVMEDIA_TYPE_VIDEO
393+ #endif
394+ && inputCtx_->streams [i]->duration > 0 ) {
395+ // There is at least two 1/r_frame_rates from the frame before the last
396+ // one until the video duration, let's prefer to set duration after the
397+ // frame before the last one, but as early as possible
398+ double correction = 2 * inputCtx_->streams [i]->r_frame_rate .den /
399+ (double )inputCtx_->streams [i]->r_frame_rate .num -
400+ 1 / (double )AV_TIME_BASE;
401+ videoDurationMs_ = 1000 * inputCtx_->streams [i]->duration *
402+ inputCtx_->streams [i]->time_base .num /
403+ (double )inputCtx_->streams [i]->time_base .den -
404+ 1000 * correction;
405+ break ;
406+ }
407+ }
408+
385409 VLOG (1 ) << " Decoder initialized, log level: " << params_.logLevel ;
410+ VLOG (1 ) << " Video duration: " << videoDurationMs_;
386411 return true ;
387412}
388413
@@ -590,13 +615,30 @@ int Decoder::getFrame(size_t workingTimeInMs) {
590615 result = 0 ;
591616
592617 av_packet_unref (avPacket);
618+
619+ if (params_.uniformSampling > 1 ) {
620+ if (doSeek_) {
621+ double duration =
622+ videoDurationMs_ > 0 ? videoDurationMs_ : params_.expectedDuration ;
623+ double step =
624+ (duration * AV_TIME_BASE) / (1000 * (params_.uniformSampling - 1 ));
625+ avformat_seek_file (
626+ inputCtx_,
627+ -1 ,
628+ static_cast <int64_t >(step * kFramesDecoded_ ) + 1 ,
629+ static_cast <int64_t >(step * (kFramesDecoded_ + 1 )),
630+ static_cast <int64_t >(step * (kFramesDecoded_ + 1 )),
631+ 0 );
632+ ++kFramesDecoded_ ;
633+ doSeek_ = false ;
634+ }
635+ }
593636 }
594637
595638 av_packet_free (&avPacket);
596- VLOG (2 ) << " Interrupted loop"
597- << " , interrupted_ " << interrupted_ << " , inRange_.any() "
598- << inRange_.any () << " , decodedFrame " << decodedFrame << " , result "
599- << result;
639+ VLOG (2 ) << " Interrupted loop" << " , interrupted_ " << interrupted_
640+ << " , inRange_.any() " << inRange_.any () << " , decodedFrame "
641+ << decodedFrame << " , result " << result;
600642
601643 // loop can be terminated, either by:
602644 // 1. explicitly interrupted
@@ -660,13 +702,35 @@ int Decoder::processPacket(
660702 startCondition = msg.header .pts >= params_.startOffset ;
661703 }
662704 if (endInRange && startCondition) {
663- *hasMsg = true ;
664- push (std::move (msg));
705+ *hasMsg = pushMsg (std::move (msg));
665706 }
666707 }
667708 return result;
668709}
669710
711+ bool Decoder::pushMsg (DecoderOutputMessage&& msg) {
712+ pastDecodedPTS_ = currentDecodedPTS_;
713+ currentDecodedPTS_ = msg.header .pts ;
714+
715+ if (params_.uniformSampling <= 1 ) {
716+ push (std::move (msg));
717+ return true ;
718+ }
719+
720+ double duration =
721+ videoDurationMs_ > 0 ? videoDurationMs_ : params_.expectedDuration ;
722+ double step =
723+ (duration * AV_TIME_BASE) / (1000 * (params_.uniformSampling - 1 ));
724+ if (pastDecodedPTS_ < step * kFramesDecoded_ &&
725+ step * kFramesDecoded_ <= currentDecodedPTS_) {
726+ push (std::move (msg));
727+ doSeek_ = true ;
728+ return true ;
729+ }
730+
731+ return false ;
732+ }
733+
670734void Decoder::flushStreams () {
671735 VLOG (1 ) << " Flushing streams..." ;
672736 for (auto & stream : streams_) {
@@ -678,7 +742,7 @@ void Decoder::flushStreams() {
678742 params_.endOffset <= 0 || msg.header .pts <= params_.endOffset ;
679743 inRange_.set (stream.second ->getIndex (), endInRange);
680744 if (endInRange && msg.header .pts >= params_.startOffset ) {
681- push (std::move (msg));
745+ pushMsg (std::move (msg));
682746 } else {
683747 msg.payload .reset ();
684748 }
0 commit comments