summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlessandro Decina <alessandro.decina@collabora.co.uk>2011-11-14 17:08:00 +0100
committerAlessandro Decina <alessandro.decina@collabora.co.uk>2011-11-14 17:08:00 +0100
commit9cc7bfb81487fd8fcd4354e161484fbe26798e9f (patch)
tree7259e6dda7b51c17131d3063f16f7143718f4a00
parent6d55562e304a521f7707258d842edcf3d8cd0d19 (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.c6
-rw-r--r--src/gstducatibufferpool.h2
-rw-r--r--src/gstducatividdec.c141
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;
}