aboutsummaryrefslogtreecommitdiff
path: root/ext/libav/gstavviddec.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/libav/gstavviddec.c')
-rw-r--r--ext/libav/gstavviddec.c85
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);