diff options
Diffstat (limited to 'ext/libav/gstavviddec.c')
-rw-r--r-- | ext/libav/gstavviddec.c | 85 |
1 files changed, 36 insertions, 49 deletions
diff --git a/ext/libav/gstavviddec.c b/ext/libav/gstavviddec.c index b3ba5c0..94dfa58 100644 --- a/ext/libav/gstavviddec.c +++ b/ext/libav/gstavviddec.c @@ -47,6 +47,7 @@ GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE); #define DEFAULT_DEBUG_MV FALSE #define DEFAULT_MAX_THREADS 0 #define DEFAULT_OUTPUT_CORRUPT TRUE +#define REQUIRED_POOL_MAX_BUFFERS 32 enum { @@ -1065,10 +1066,8 @@ negotiate_failed: * Sets the skip_frame flag and if things are really bad, skips to the next * keyframe. * - * Returns TRUE if the frame should be decoded, FALSE if the frame can be dropped - * entirely. */ -static gboolean +static void gst_ffmpegviddec_do_qos (GstFFMpegVidDec * ffmpegdec, GstVideoCodecFrame * frame, gboolean * mode_switch) { @@ -1077,47 +1076,29 @@ gst_ffmpegviddec_do_qos (GstFFMpegVidDec * ffmpegdec, *mode_switch = FALSE; if (frame == NULL) - goto no_qos; + return; diff = gst_video_decoder_get_max_decode_time (GST_VIDEO_DECODER (ffmpegdec), frame); /* if we don't have timing info, then we don't do QoS */ - if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (diff))) - goto no_qos; - - GST_DEBUG_OBJECT (ffmpegdec, "decoding time %" GST_TIME_FORMAT, - GST_TIME_ARGS (diff)); + if (G_UNLIKELY(diff == G_MAXINT64)) + return; - if (diff > 0) - goto normal_mode; + GST_DEBUG_OBJECT (ffmpegdec, "decoding time %" G_GINT64_FORMAT, diff); - if (diff <= 0) { - goto skip_frame; + if (diff > 0 && ffmpegdec->context->skip_frame != AVDISCARD_DEFAULT) { + ffmpegdec->context->skip_frame = AVDISCARD_DEFAULT; + *mode_switch = TRUE; + GST_DEBUG_OBJECT (ffmpegdec, "QOS: normal mode"); } -no_qos: - return TRUE; - -normal_mode: - { - if (ffmpegdec->context->skip_frame != AVDISCARD_DEFAULT) { - ffmpegdec->context->skip_frame = AVDISCARD_DEFAULT; - *mode_switch = TRUE; - GST_DEBUG_OBJECT (ffmpegdec, "QOS: normal mode"); - } - return TRUE; - } -skip_frame: - { - if (ffmpegdec->context->skip_frame != AVDISCARD_NONREF) { - ffmpegdec->context->skip_frame = AVDISCARD_NONREF; - *mode_switch = TRUE; - GST_DEBUG_OBJECT (ffmpegdec, - "QOS: hurry up, diff %" G_GINT64_FORMAT " >= 0", diff); - } - return FALSE; + else if (diff <= 0 && ffmpegdec->context->skip_frame != AVDISCARD_NONREF) { + ffmpegdec->context->skip_frame = AVDISCARD_NONREF; + *mode_switch = TRUE; + GST_DEBUG_OBJECT (ffmpegdec, + "QOS: hurry up, diff %" G_GINT64_FORMAT " >= 0", diff); } } @@ -1205,8 +1186,6 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec, gint len = -1; gint have_data; gboolean mode_switch; - gboolean decode; - gint skip_frame = AVDISCARD_DEFAULT; GstVideoCodecFrame *out_frame; GstFFMpegVidDecVideoFrame *out_dframe; AVPacket packet; @@ -1218,7 +1197,7 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec, /* run QoS code, we don't stop decoding the frame when we are late because * else we might skip a reference frame */ - decode = gst_ffmpegviddec_do_qos (ffmpegdec, frame, &mode_switch); + gst_ffmpegviddec_do_qos (ffmpegdec, frame, &mode_switch); if (ffmpegdec->is_realvideo && data != NULL) { gint slice_count; @@ -1238,13 +1217,6 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec, } } - if (!decode) { - /* no decoding needed, save previous skip_frame value and brutely skip - * decoding everything */ - skip_frame = ffmpegdec->context->skip_frame; - ffmpegdec->context->skip_frame = AVDISCARD_NONREF; - } - if (frame) { /* save reference to the timing info */ ffmpegdec->context->reordered_opaque = (gint64) frame->system_frame_number; @@ -1269,10 +1241,6 @@ gst_ffmpegviddec_video_frame (GstFFMpegVidDec * ffmpegdec, len = avcodec_decode_video2 (ffmpegdec->context, ffmpegdec->picture, &have_data, &packet); - /* restore previous state */ - if (!decode) - ffmpegdec->context->skip_frame = skip_frame; - GST_DEBUG_OBJECT (ffmpegdec, "after decode: len %d, have_data %d", len, have_data); @@ -1693,7 +1661,7 @@ gst_ffmpegviddec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query) GstBufferPool *pool; guint size, min, max; GstStructure *config; - gboolean have_videometa, have_alignment; + gboolean have_videometa, have_alignment, update_pool; GstAllocator *allocator = NULL; GstAllocationParams params = { 0, 15, 0, 0, }; @@ -1712,6 +1680,22 @@ gst_ffmpegviddec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query) gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); + /* Don't use pool that can't grow, as we don't know how many buffer we'll + * need, otherwise we may stall */ + if (max != 0 && max < REQUIRED_POOL_MAX_BUFFERS) { + gst_object_unref (pool); + pool = gst_video_buffer_pool_new (); + max = 0; + update_pool = TRUE; + + /* if there is an allocator, also drop it, as it might be the reason we + * have this limit. Default will be used */ + if (allocator) { + gst_object_unref (allocator); + allocator = NULL; + } + } + config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, state->caps, size, min, max); /* we are happy with the default allocator but we would like to have 16 bytes @@ -1799,6 +1783,9 @@ gst_ffmpegviddec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query) /* and store */ gst_buffer_pool_set_config (pool, config); + if (update_pool) + gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max); + gst_object_unref (pool); if (allocator) gst_object_unref (allocator); |