summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSreerenj Balachandran <sreerenj.balachandran@intel.com>2013-11-11 14:10:53 +0200
committerSebastian Dröge <sebastian@centricular.com>2013-11-11 13:28:11 +0100
commitcd52ff313e2c9eca0d20787f598b1d752da4c5f7 (patch)
tree391808d11018c1c56c297a152a3a5ff55d0f06d2
parent360ac34425539eaabfa6f6106ea1a820460f7101 (diff)
videodecoder: try to negotiate the buffer pool even though there is no o/p format
We could have allocation query before caps event and even without caps inside the query. In such cases , the downstream can return a bufferpool object with out actually configuring it. This feature is helpful to negotiate the bufferpool with out knowing the output video format. For eg: some hardware accelerated decoders can interpret the o/p video format only after it finishes the decoding of one buffer at least. https://bugzilla.gnome.org/show_bug.cgi?id=687183
-rw-r--r--gst-libs/gst/video/gstvideodecoder.c162
1 files changed, 95 insertions, 67 deletions
diff --git a/gst-libs/gst/video/gstvideodecoder.c b/gst-libs/gst/video/gstvideodecoder.c
index 77853a481..ef5baf7f7 100644
--- a/gst-libs/gst/video/gstvideodecoder.c
+++ b/gst-libs/gst/video/gstvideodecoder.c
@@ -2928,7 +2928,7 @@ static gboolean
gst_video_decoder_decide_allocation_default (GstVideoDecoder * decoder,
GstQuery * query)
{
- GstCaps *outcaps;
+ GstCaps *outcaps = NULL;
GstBufferPool *pool = NULL;
guint size, min, max;
GstAllocator *allocator = NULL;
@@ -2939,7 +2939,8 @@ gst_video_decoder_decide_allocation_default (GstVideoDecoder * decoder,
gst_query_parse_allocation (query, &outcaps, NULL);
gst_video_info_init (&vinfo);
- gst_video_info_from_caps (&vinfo, outcaps);
+ if (outcaps)
+ gst_video_info_from_caps (&vinfo, outcaps);
/* we got configuration from our peer or the decide_allocation method,
* parse them */
@@ -3003,73 +3004,18 @@ gst_video_decoder_propose_allocation_default (GstVideoDecoder * decoder,
}
static gboolean
-gst_video_decoder_negotiate_default (GstVideoDecoder * decoder)
+gst_video_decoder_negotiate_pool (GstVideoDecoder * decoder, GstCaps * caps)
{
- GstVideoCodecState *state = decoder->priv->output_state;
GstVideoDecoderClass *klass;
GstQuery *query = NULL;
GstBufferPool *pool = NULL;
GstAllocator *allocator;
GstAllocationParams params;
gboolean ret = TRUE;
- GstVideoCodecFrame *frame;
- GstCaps *prevcaps;
-
- g_return_val_if_fail (GST_VIDEO_INFO_WIDTH (&state->info) != 0, FALSE);
- g_return_val_if_fail (GST_VIDEO_INFO_HEIGHT (&state->info) != 0, FALSE);
klass = GST_VIDEO_DECODER_GET_CLASS (decoder);
- GST_DEBUG_OBJECT (decoder, "output_state par %d/%d fps %d/%d",
- state->info.par_n, state->info.par_d,
- state->info.fps_n, state->info.fps_d);
-
- if (state->caps == NULL)
- state->caps = gst_video_info_to_caps (&state->info);
-
- GST_DEBUG_OBJECT (decoder, "setting caps %" GST_PTR_FORMAT, state->caps);
-
- /* Push all pending pre-caps events of the oldest frame before
- * setting caps */
- frame = decoder->priv->frames ? decoder->priv->frames->data : NULL;
- if (frame || decoder->priv->current_frame_events) {
- GList **events, *l;
-
- if (frame) {
- events = &frame->events;
- } else {
- events = &decoder->priv->current_frame_events;
- }
-
- for (l = g_list_last (*events); l;) {
- GstEvent *event = GST_EVENT (l->data);
- GList *tmp;
-
- if (GST_EVENT_TYPE (event) < GST_EVENT_CAPS) {
- gst_video_decoder_push_event (decoder, event);
- tmp = l;
- l = l->prev;
- *events = g_list_delete_link (*events, tmp);
- } else {
- l = l->prev;
- }
- }
- }
-
- prevcaps = gst_pad_get_current_caps (decoder->srcpad);
- if (!prevcaps || !gst_caps_is_equal (prevcaps, state->caps))
- ret = gst_pad_set_caps (decoder->srcpad, state->caps);
- else
- ret = TRUE;
- if (prevcaps)
- gst_caps_unref (prevcaps);
-
- if (!ret)
- goto done;
- decoder->priv->output_state_changed = FALSE;
-
- /* Negotiate pool */
- query = gst_query_new_allocation (state->caps, TRUE);
+ query = gst_query_new_allocation (caps, TRUE);
if (!gst_pad_peer_query (decoder->srcpad, query)) {
GST_DEBUG_OBJECT (decoder, "didn't get downstream ALLOCATION hints");
@@ -3130,6 +3076,78 @@ no_decide_allocation:
}
}
+static gboolean
+gst_video_decoder_negotiate_default (GstVideoDecoder * decoder)
+{
+ GstVideoCodecState *state = decoder->priv->output_state;
+ gboolean ret = TRUE;
+ GstVideoCodecFrame *frame;
+ GstCaps *prevcaps;
+
+ if (!state) {
+ GST_DEBUG_OBJECT (decoder,
+ "Trying to negotiate the pool with out setting the o/p format");
+ ret = gst_video_decoder_negotiate_pool (decoder, NULL);
+ goto done;
+ }
+
+ g_return_val_if_fail (GST_VIDEO_INFO_WIDTH (&state->info) != 0, FALSE);
+ g_return_val_if_fail (GST_VIDEO_INFO_HEIGHT (&state->info) != 0, FALSE);
+
+ GST_DEBUG_OBJECT (decoder, "output_state par %d/%d fps %d/%d",
+ state->info.par_n, state->info.par_d,
+ state->info.fps_n, state->info.fps_d);
+
+ if (state->caps == NULL)
+ state->caps = gst_video_info_to_caps (&state->info);
+
+ GST_DEBUG_OBJECT (decoder, "setting caps %" GST_PTR_FORMAT, state->caps);
+
+ /* Push all pending pre-caps events of the oldest frame before
+ * setting caps */
+ frame = decoder->priv->frames ? decoder->priv->frames->data : NULL;
+ if (frame || decoder->priv->current_frame_events) {
+ GList **events, *l;
+
+ if (frame) {
+ events = &frame->events;
+ } else {
+ events = &decoder->priv->current_frame_events;
+ }
+
+ for (l = g_list_last (*events); l;) {
+ GstEvent *event = GST_EVENT (l->data);
+ GList *tmp;
+
+ if (GST_EVENT_TYPE (event) < GST_EVENT_CAPS) {
+ gst_video_decoder_push_event (decoder, event);
+ tmp = l;
+ l = l->prev;
+ *events = g_list_delete_link (*events, tmp);
+ } else {
+ l = l->prev;
+ }
+ }
+ }
+
+ prevcaps = gst_pad_get_current_caps (decoder->srcpad);
+ if (!prevcaps || !gst_caps_is_equal (prevcaps, state->caps))
+ ret = gst_pad_set_caps (decoder->srcpad, state->caps);
+ else
+ ret = TRUE;
+ if (prevcaps)
+ gst_caps_unref (prevcaps);
+
+ if (!ret)
+ goto done;
+ decoder->priv->output_state_changed = FALSE;
+ /* Negotiate pool */
+ ret = gst_video_decoder_negotiate_pool (decoder, state->caps);
+
+done:
+ return ret;
+}
+
/**
* gst_video_decoder_negotiate:
* @decoder: a #GstVideoDecoder
@@ -3145,7 +3163,6 @@ gst_video_decoder_negotiate (GstVideoDecoder * decoder)
gboolean ret = TRUE;
g_return_val_if_fail (GST_IS_VIDEO_DECODER (decoder), FALSE);
- g_return_val_if_fail (decoder->priv->output_state, FALSE);
klass = GST_VIDEO_DECODER_GET_CLASS (decoder);
@@ -3176,17 +3193,21 @@ gst_video_decoder_allocate_output_buffer (GstVideoDecoder * decoder)
GstFlowReturn flow;
GstBuffer *buffer = NULL;
- g_return_val_if_fail (decoder->priv->output_state, NULL);
-
GST_DEBUG ("alloc src buffer");
GST_VIDEO_DECODER_STREAM_LOCK (decoder);
- if (G_UNLIKELY (decoder->priv->output_state_changed
+ if (G_UNLIKELY (!decoder->priv->output_state
+ || decoder->priv->output_state_changed
|| gst_pad_check_reconfigure (decoder->srcpad))) {
if (!gst_video_decoder_negotiate (decoder)) {
- GST_DEBUG_OBJECT (decoder, "Failed to negotiate, fallback allocation");
- gst_pad_mark_reconfigure (decoder->srcpad);
- goto fallback;
+ if (decoder->priv->output_state) {
+ GST_DEBUG_OBJECT (decoder, "Failed to negotiate, fallback allocation");
+ gst_pad_mark_reconfigure (decoder->srcpad);
+ goto fallback;
+ } else {
+ GST_DEBUG_OBJECT (decoder, "Failed to negotiate, output_buffer=NULL");
+ goto failed_allocation;
+ }
}
}
@@ -3195,17 +3216,24 @@ gst_video_decoder_allocate_output_buffer (GstVideoDecoder * decoder)
if (flow != GST_FLOW_OK) {
GST_INFO_OBJECT (decoder, "couldn't allocate output buffer, flow %s",
gst_flow_get_name (flow));
- goto fallback;
+ if (decoder->priv->output_state && decoder->priv->output_state->info.size)
+ goto fallback;
+ else
+ goto failed_allocation;
}
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
return buffer;
fallback:
+ GST_INFO_OBJECT (decoder,
+ "Fallback allocation, creating new buffer which doesn't belongs to any buffer pool");
buffer =
gst_buffer_new_allocate (NULL, decoder->priv->output_state->info.size,
NULL);
+failed_allocation:
+ GST_ERROR_OBJECT (decoder, "Failed to allocate the buffer..");
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
return buffer;