diff --git a/deps/libff/libff/ff-audio-decoder.c b/deps/libff/libff/ff-audio-decoder.c index ebf8caed1..f951fdd18 100644 --- a/deps/libff/libff/ff-audio-decoder.c +++ b/deps/libff/libff/ff-audio-decoder.c @@ -55,6 +55,17 @@ static bool handle_reset_packet(struct ff_decoder *decoder, return true; } +static void drop_late_packets(struct ff_decoder *decoder, + struct ff_packet *packet) +{ + int64_t start_time = ff_clock_start_time(decoder->clock); + if (start_time != AV_NOPTS_VALUE) { + if (ff_decoder_set_frame_drop_state(decoder, start_time, + packet->base.pts)) + shrink_packet(packet, packet->base.size); + } +} + static int decode_frame(struct ff_decoder *decoder, struct ff_packet *packet, AVFrame *frame, bool *frame_complete) { @@ -65,6 +76,8 @@ static int decode_frame(struct ff_decoder *decoder, while (packet->base.size > 0) { int complete; + drop_late_packets(decoder, packet); + packet_length = avcodec_decode_audio4(decoder->codec, frame, &complete, &packet->base); diff --git a/deps/libff/libff/ff-decoder.c b/deps/libff/libff/ff-decoder.c index b51d6a81d..fb3d9fe39 100644 --- a/deps/libff/libff/ff-decoder.c +++ b/deps/libff/libff/ff-decoder.c @@ -320,3 +320,30 @@ double ff_decoder_get_best_effort_pts(struct ff_decoder *decoder, return d_pts; } + +bool ff_decoder_set_frame_drop_state(struct ff_decoder *decoder, + int64_t start_time, int64_t pts) +{ + if (pts != AV_NOPTS_VALUE) { + int64_t rescaled_pts = av_rescale_q(pts, + decoder->stream->time_base, AV_TIME_BASE_Q); + int64_t master_clock = av_gettime() - + start_time; + + int64_t diff = master_clock - rescaled_pts; + + if (diff > (AV_TIME_BASE / 2)) { + decoder->codec->skip_frame = decoder->frame_drop; + decoder->codec->skip_idct = decoder->frame_drop; + decoder->codec->skip_loop_filter = decoder->frame_drop; + return true; + } else { + decoder->codec->skip_frame = AVDISCARD_DEFAULT; + decoder->codec->skip_idct = AVDISCARD_DEFAULT; + decoder->codec->skip_loop_filter = AVDISCARD_DEFAULT; + return false; + } + } + + return false; +} diff --git a/deps/libff/libff/ff-decoder.h b/deps/libff/libff/ff-decoder.h index 089e01d37..6fb2bf012 100644 --- a/deps/libff/libff/ff-decoder.h +++ b/deps/libff/libff/ff-decoder.h @@ -44,6 +44,7 @@ struct ff_decoder { int64_t current_pts_time; // clock time when current_pts was set bool hwaccel_decoder; + enum AVDiscard frame_drop; struct ff_clock *clock; enum ff_av_sync_type natural_sync_clock; @@ -69,3 +70,6 @@ void ff_decoder_refresh(void *opaque); double ff_decoder_get_best_effort_pts(struct ff_decoder *decoder, AVFrame *frame); + +bool ff_decoder_set_frame_drop_state(struct ff_decoder *decoder, + int64_t start_time, int64_t pts); diff --git a/deps/libff/libff/ff-demuxer.c b/deps/libff/libff/ff-demuxer.c index 8b725d22f..44847af81 100644 --- a/deps/libff/libff/ff-demuxer.c +++ b/deps/libff/libff/ff-demuxer.c @@ -194,6 +194,8 @@ static bool initialize_decoder(struct ff_demuxer *demuxer, demuxer->options.audio_frame_queue_size); demuxer->audio_decoder->hwaccel_decoder = hwaccel_decoder; + demuxer->audio_decoder->frame_drop = + demuxer->options.frame_drop; demuxer->audio_decoder->natural_sync_clock = AV_SYNC_AUDIO_MASTER; demuxer->audio_decoder->callbacks = &demuxer->audio_callbacks; @@ -215,6 +217,8 @@ static bool initialize_decoder(struct ff_demuxer *demuxer, demuxer->options.video_frame_queue_size); demuxer->video_decoder->hwaccel_decoder = hwaccel_decoder; + demuxer->video_decoder->frame_drop = + demuxer->options.frame_drop; demuxer->video_decoder->natural_sync_clock = AV_SYNC_VIDEO_MASTER; demuxer->video_decoder->callbacks = &demuxer->video_callbacks; diff --git a/deps/libff/libff/ff-demuxer.h b/deps/libff/libff/ff-demuxer.h index 938114f0a..d6b20703f 100644 --- a/deps/libff/libff/ff-demuxer.h +++ b/deps/libff/libff/ff-demuxer.h @@ -35,6 +35,7 @@ struct ff_demuxer_options int video_frame_queue_size; bool is_hw_decoding; bool is_looping; + enum AVDiscard frame_drop; }; typedef struct ff_demuxer_options ff_demuxer_options_t; diff --git a/deps/libff/libff/ff-video-decoder.c b/deps/libff/libff/ff-video-decoder.c index c22381ad0..0f1b35f76 100644 --- a/deps/libff/libff/ff-video-decoder.c +++ b/deps/libff/libff/ff-video-decoder.c @@ -73,6 +73,7 @@ void *ff_video_decoder_thread(void *opaque_video_decoder) int complete; AVFrame *frame = av_frame_alloc(); int ret; + bool key_frame; while (!decoder->abort) { ret = packet_queue_get(&decoder->packet_queue, &packet, 1); @@ -95,6 +96,20 @@ void *ff_video_decoder_thread(void *opaque_video_decoder) continue; } + int64_t start_time = ff_clock_start_time(decoder->clock); + key_frame = packet.base.flags & AV_PKT_FLAG_KEY; + + // We can only make decisions on keyframes for + // hw decoders (maybe just OSX?) + // For now, always make drop decisions on keyframes + bool frame_drop_check = key_frame; + // Must have a proper packet pts to drop frames here + frame_drop_check &= start_time != AV_NOPTS_VALUE; + + if (frame_drop_check) + ff_decoder_set_frame_drop_state(decoder, + start_time, packet.base.pts); + avcodec_decode_video2(decoder->codec, frame, &complete, &packet.base);