diff options
author | Alessandro Decina <alessandro.decina@collabora.co.uk> | 2011-11-14 17:08:00 +0100 |
---|---|---|
committer | Alessandro Decina <alessandro.decina@collabora.co.uk> | 2011-11-14 17:08:00 +0100 |
commit | 9cc7bfb81487fd8fcd4354e161484fbe26798e9f (patch) | |
tree | 7259e6dda7b51c17131d3063f16f7143718f4a00 | |
parent | 6d55562e304a521f7707258d842edcf3d8cd0d19 (diff) |
ducatividdec: add support for video/x-raw-yuv-strided
Add support video/x-raw-yuv-strided and rework negotiation a bit so that we can
support upstream negotiation for the rowstride field (v4l2sink likes to do
that).
-rw-r--r-- | src/gstducatibufferpool.c | 6 | ||||
-rw-r--r-- | src/gstducatibufferpool.h | 2 | ||||
-rw-r--r-- | src/gstducatividdec.c | 141 |
3 files changed, 90 insertions, 59 deletions
diff --git a/src/gstducatibufferpool.c b/src/gstducatibufferpool.c index 3f91c8c..6e7d6b8 100644 --- a/src/gstducatibufferpool.c +++ b/src/gstducatibufferpool.c @@ -44,14 +44,16 @@ gst_ducati_buffer_new (GstDucatiBufferPool * pool) { GstDucatiBuffer *self = (GstDucatiBuffer *) gst_mini_object_new (GST_TYPE_DUCATIBUFFER); + guint sz; GST_LOG_OBJECT (pool->element, "creating buffer %p in pool %p", self, pool); self->pool = (GstDucatiBufferPool *) gst_mini_object_ref (GST_MINI_OBJECT (pool)); - GST_BUFFER_DATA (self) = gst_ducati_alloc_1d (pool->size); - GST_BUFFER_SIZE (self) = pool->size; + GST_BUFFER_DATA (self) = + gst_ducati_alloc_2d (pool->padded_width, pool->padded_height, &sz); + GST_BUFFER_SIZE (self) = sz; gst_buffer_set_caps (GST_BUFFER (self), pool->caps); diff --git a/src/gstducatibufferpool.h b/src/gstducatibufferpool.h index a8588c8..c38f49a 100644 --- a/src/gstducatibufferpool.h +++ b/src/gstducatibufferpool.h @@ -43,13 +43,13 @@ struct _GstDucatiBufferPool /* output (padded) size including any codec padding: */ gint padded_width, padded_height; - guint size; GstCaps *caps; GMutex *lock; gboolean running; /* with lock */ GstElement *element; /* the element that owns us.. */ GstDucatiBuffer *freelist; /* list of available buffers */ + guint size; }; GstDucatiBufferPool * gst_ducati_bufferpool_new (GstElement * element, GstCaps * caps, guint size); diff --git a/src/gstducatividdec.c b/src/gstducatividdec.c index ad45c51..336a772 100644 --- a/src/gstducatividdec.c +++ b/src/gstducatividdec.c @@ -29,7 +29,7 @@ GST_BOILERPLATE (GstDucatiVidDec, gst_ducati_viddec, GstElement, static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("NV12")) + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV_STRIDED ("NV12", "[ 0, max ]")) ); enum @@ -281,7 +281,7 @@ codec_process (GstDucatiVidDec * self, gboolean send, gboolean flush) t = gst_util_get_timestamp (); err = VIDDEC3_process (self->codec, self->inBufs, self->outBufs, self->inArgs, self->outArgs); - GST_INFO_OBJECT (self, "%10dns", (gint) (gst_util_get_timestamp () - t)); + GST_DEBUG_OBJECT (self, "%10dns", (gint) (gst_util_get_timestamp () - t)); if (err) { GST_WARNING_OBJECT (self, "err=%d, extendedError=%08x", @@ -511,73 +511,75 @@ gst_ducati_viddec_push_input (GstDucatiVidDec * self, GstBuffer * buf) /* GstElement vmethod implementations */ static gboolean -gst_ducati_viddec_set_caps (GstPad * pad, GstCaps * caps) +gst_ducati_viddec_sink_setcaps (GstPad * pad, GstCaps * caps) { gboolean ret = TRUE; GstDucatiVidDec *self = GST_DUCATIVIDDEC (gst_pad_get_parent (pad)); GstDucatiVidDecClass *klass = GST_DUCATIVIDDEC_GET_CLASS (self); GstStructure *s; - - g_return_val_if_fail (caps, FALSE); - g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE); + GstCaps *outcaps = NULL; + GstStructure *out_s; + gboolean interlaced = FALSE; + gint frn = 0, frd = 1; s = gst_caps_get_structure (caps, 0); + if (!klass->parse_caps (self, s)) { + GST_WARNING_OBJECT (self, "missing required fields"); + ret = FALSE; + goto out; + } - if (pad == self->sinkpad) { - gint frn = 0, frd = 1; - GST_INFO_OBJECT (self, "setcaps (sink): %" GST_PTR_FORMAT, caps); - - if (klass->parse_caps (self, s)) { - GstCaps *outcaps; - gboolean interlaced = FALSE; - - gst_structure_get_fraction (s, "framerate", &frn, &frd); - - - gst_structure_get_boolean (s, "interlaced", &interlaced); - - /* update output/padded sizes: - */ - klass->update_buffer_size (self); + /* update output/padded sizes */ + klass->update_buffer_size (self); - self->stride = self->padded_width; - self->outsize = - GST_ROUND_UP_2 (self->stride * self->padded_height * 3) / 2; + GST_INFO_OBJECT (self, "setcaps (sink): %" GST_PTR_FORMAT, caps); - outcaps = gst_caps_new_simple ("video/x-raw-yuv", - "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('N','V','1','2'), - "width", G_TYPE_INT, self->padded_width, - "height", G_TYPE_INT, self->padded_height, - "framerate", GST_TYPE_FRACTION, frn, frd, - NULL); + gst_structure_get_fraction (s, "framerate", &frn, &frd); + gst_structure_get_boolean (s, "interlaced", &interlaced); - if (interlaced) { - gst_caps_set_simple (outcaps, "interlaced", G_TYPE_BOOLEAN, TRUE, NULL); - } + outcaps = gst_pad_get_allowed_caps (self->srcpad); + if (outcaps) { + outcaps = gst_caps_make_writable (outcaps); + gst_caps_truncate (outcaps); + } else { + outcaps = gst_caps_new_simple ("video/x-raw-yuv-strided", + "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('N', 'V', '1', '2'), + NULL); + } - GST_DEBUG_OBJECT (self, "outcaps: %" GST_PTR_FORMAT, outcaps); + out_s = gst_caps_get_structure (outcaps, 0); + gst_structure_set (out_s, + "width", G_TYPE_INT, self->padded_width, + "height", G_TYPE_INT, self->padded_height, + "framerate", GST_TYPE_FRACTION, frn, frd, NULL); - ret = gst_pad_set_caps (self->srcpad, outcaps); - gst_caps_unref (outcaps); + if (interlaced) + gst_structure_set (out_s, "interlaced", G_TYPE_BOOLEAN, TRUE, NULL); - if (!ret) { - GST_WARNING_OBJECT (self, "failed to set caps"); - return FALSE; - } - } else { - GST_WARNING_OBJECT (self, "missing required fields"); - return FALSE; + if (!strcmp (gst_structure_get_name (out_s), "video/x-raw-yuv-strided")) { + if (!gst_structure_get_int (out_s, "rowstride", &self->stride)) { + self->stride = 4096; + gst_structure_set (out_s, "rowstride", G_TYPE_INT, self->stride, NULL); } } else { - GST_INFO_OBJECT (self, "setcaps (src): %" GST_PTR_FORMAT, caps); - // XXX check to make sure caps are ok.. keep track if we - // XXX need to handle unstrided buffers.. - GST_WARNING_OBJECT (self, "TODO"); + self->stride = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_NV12, + 0, self->padded_width); } + self->outsize = gst_video_format_get_size (GST_VIDEO_FORMAT_NV12, + self->stride, self->padded_height); + + GST_INFO_OBJECT (self, "outsize %d stride %d outcaps: %" GST_PTR_FORMAT, + self->outsize, self->stride, outcaps); + + ret = gst_pad_set_caps (self->srcpad, outcaps); + +out: + if (outcaps) + gst_caps_unref (outcaps); gst_object_unref (self); - return gst_pad_set_caps (pad, caps); + return ret; } static gboolean @@ -616,6 +618,7 @@ gst_ducati_viddec_chain (GstPad * pad, GstBuffer * buf) GstFlowReturn ret; Int32 err; GstBuffer *outbuf = NULL; + GstCaps *outcaps = NULL; if (G_UNLIKELY (!self->engine)) { GST_ERROR_OBJECT (self, "no engine"); @@ -625,12 +628,37 @@ gst_ducati_viddec_chain (GstPad * pad, GstBuffer * buf) /* do this before creating codec to ensure reverse caps negotiation * happens first: */ - ret = gst_pad_alloc_buffer_and_set_caps (self->srcpad, 0, self->outsize, +allocate_buffer: + ret = gst_pad_alloc_buffer (self->srcpad, 0, self->outsize, GST_PAD_CAPS (self->srcpad), &outbuf); - if (ret != GST_FLOW_OK) { - outbuf = codec_bufferpool_get (self, NULL); - ret = GST_FLOW_OK; + GST_ERROR_OBJECT (self, "alloc_buffer failed %s", gst_flow_get_name (ret)); + return ret; + } + + outcaps = GST_BUFFER_CAPS (outbuf); + if (outcaps && !gst_caps_is_equal (outcaps, GST_PAD_CAPS (self->srcpad))) { + GstStructure *s; + + GST_INFO_OBJECT (self, "doing upstream negotiation bufsize %d", + GST_BUFFER_SIZE (outbuf)); + + s = gst_caps_get_structure (outcaps, 0); + gst_structure_get_int (s, "rowstride", &self->stride); + self->outsize = gst_video_format_get_size (GST_VIDEO_FORMAT_NV12, + self->stride, self->padded_height); + + GST_INFO_OBJECT (self, "outsize %d stride %d outcaps: %" GST_PTR_FORMAT, + self->outsize, self->stride, outcaps); + + gst_pad_set_caps (self->srcpad, outcaps); + + if (GST_BUFFER_SIZE (outbuf) != self->outsize) { + GST_INFO_OBJECT (self, "dropping buffer (bufsize %d != outsize %d)", + GST_BUFFER_SIZE (outbuf), self->outsize); + gst_buffer_unref (outbuf); + goto allocate_buffer; + } } if (G_UNLIKELY (!self->codec)) { @@ -866,15 +894,13 @@ gst_ducati_viddec_init (GstDucatiVidDec * self, GstDucatiVidDecClass * klass) self->sinkpad = gst_pad_new_from_template ( gst_element_class_get_pad_template (gstelement_class, "sink"), "sink"); gst_pad_set_setcaps_function (self->sinkpad, - GST_DEBUG_FUNCPTR (gst_ducati_viddec_set_caps)); + GST_DEBUG_FUNCPTR (gst_ducati_viddec_sink_setcaps)); gst_pad_set_chain_function (self->sinkpad, GST_DEBUG_FUNCPTR (gst_ducati_viddec_chain)); gst_pad_set_event_function (self->sinkpad, GST_DEBUG_FUNCPTR (gst_ducati_viddec_event)); self->srcpad = gst_pad_new_from_static_template (&src_factory, "src"); - gst_pad_set_setcaps_function (self->srcpad, - GST_DEBUG_FUNCPTR (gst_ducati_viddec_set_caps)); gst_pad_set_query_function (self->srcpad, GST_DEBUG_FUNCPTR (gst_ducati_viddec_query)); @@ -887,5 +913,8 @@ gst_ducati_viddec_init (GstDucatiVidDec * self, GstDucatiVidDecClass * klass) self->width = 128; self->height = 128; + self->first_in_buffer = TRUE; + self->first_out_buffer = TRUE; + self->pageMemType = XDM_MEMTYPE_TILEDPAGE; } |