summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: cab5d92)
raw | patch | inline | side by side (parent: cab5d92)
author | Alessandro Decina <alessandro.decina@collabora.co.uk> | |
Thu, 19 Jan 2012 16:07:31 +0000 (17:07 +0100) | ||
committer | Alessandro Decina <alessandro.decina@collabora.co.uk> | |
Thu, 19 Jan 2012 16:19:42 +0000 (17:19 +0100) |
Sometimes upstream thinks that some input is progressive (usually if interlaced
isn't marked correctly at the container level) when it's actually interlaced.
Detect such cases with help from the codec and adjust caps (and buffers)
accordingly.
isn't marked correctly at the container level) when it's actually interlaced.
Detect such cases with help from the codec and adjust caps (and buffers)
accordingly.
src/gstducatividdec.c | patch | blob | history | |
src/gstducatividdec.h | patch | blob | history |
diff --git a/src/gstducatividdec.c b/src/gstducatividdec.c
index a25c52033afba3addc394fad1837f3eb5d760648..7d98d402a83ca8d0c035bdded3bfd3ab6d999fe2 100644 (file)
--- a/src/gstducatividdec.c
+++ b/src/gstducatividdec.c
}
static XDAS_Int32
-codec_prepare_outbuf (GstDucatiVidDec * self, GstBuffer ** buf)
+codec_prepare_outbuf (GstDucatiVidDec * self, GstBuffer ** buf,
+ gboolean force_internal)
{
XDAS_Int16 y_type, uv_type;
guint8 *y_vaddr, *uv_vaddr;
SSPtr y_paddr, uv_paddr;
+ if (force_internal) {
+ GST_DEBUG_OBJECT (self, "internal bufferpool forced");
+ gst_buffer_unref (*buf);
+ *buf = codec_bufferpool_get (self, NULL);
+ return codec_prepare_outbuf (self, buf, FALSE);
+ }
+
y_vaddr = GST_BUFFER_DATA (*buf);
uv_vaddr = y_vaddr + self->stride * self->padded_height;
if (y_type < 0 || uv_type < 0) {
GST_DEBUG_OBJECT (self, "non TILER buffer, fallback to bufferpool");
*buf = codec_bufferpool_get (self, *buf);
- return codec_prepare_outbuf (self, buf);
+ return codec_prepare_outbuf (self, buf, FALSE);
}
if (!self->outBufs->numBufs) {
(self->outBufs->descs[1].memType != uv_type)) {
GST_DEBUG_OBJECT (self, "buffer mismatch, fallback to bufferpool");
*buf = codec_bufferpool_get (self, *buf);
- return codec_prepare_outbuf (self, buf);
+ return codec_prepare_outbuf (self, buf, FALSE);
}
}
}
for (i = 0; self->outArgs->outputID[i]; i++) {
+ gboolean interlaced;
+
+ outbuf = codec_get_outbuf (self, self->outArgs->outputID[i]);
+
+ interlaced = self->outArgs->decodedBufs.contentType == IVIDEO_PROGRESSIVE ? FALSE : TRUE;
+
+ if (interlaced != self->interlaced) {
+ GstCaps *caps;
+
+ GST_WARNING_OBJECT (self, "upstream set interlaced=%d but codec "
+ "thinks interlaced=%d... trusting codec", self->interlaced,
+ interlaced);
+
+ self->interlaced = interlaced;
+
+ caps = gst_caps_make_writable (gst_pad_get_negotiated_caps (self->srcpad));
+ GST_INFO_OBJECT (self, "changing interlace field in caps");
+ gst_caps_set_simple (caps, "interlaced", G_TYPE_BOOLEAN, interlaced, NULL);
+ if (!gst_pad_set_caps (self->srcpad, caps)) {
+ GST_ERROR_OBJECT (self, "downstream didn't want to change interlace mode");
+ err = XDM_EFAIL;
+ }
+ gst_caps_unref (caps);
+
+ /* this buffer still has the old caps so we skip it */
+ send = FALSE;
+ }
+
if (G_UNLIKELY (self->first_out_buffer) && send) {
gint crop_width, crop_height;
self->first_out_buffer = FALSE;
}
- outbuf = codec_get_outbuf (self, self->outArgs->outputID[i]);
if (send) {
GstClockTime ts;
i, outbuf, GST_TIME_ARGS (ts));
}
+
+ if (GST_BUFFER_CAPS (outbuf) &&
+ !gst_caps_is_equal (GST_BUFFER_CAPS (outbuf),
+ GST_PAD_CAPS (self->srcpad))) {
+ /* this looks a bit scary but it's really just to change the interlace=
+ * field in caps when we start as !interlaced and the codec detects
+ * otherwise */
+ GST_WARNING_OBJECT (self, "overriding buffer caps to fix "
+ "interlace mismatch");
+ outbuf = gst_buffer_make_metadata_writable (outbuf);
+ gst_buffer_set_caps (outbuf, GST_PAD_CAPS (self->srcpad));
+ }
+
gst_pad_push (self->srcpad, outbuf);
} else {
GST_DEBUG_OBJECT (self, "free buffer: %d %p", i, outbuf);
GstStructure *s;
GstCaps *outcaps = NULL;
GstStructure *out_s;
- gboolean interlaced = FALSE;
gint frn = 0, frd = 1;
gint par_width, par_height;
gboolean par_present;
klass->update_buffer_size (self);
gst_structure_get_fraction (s, "framerate", &frn, &frd);
- gst_structure_get_boolean (s, "interlaced", &interlaced);
+ gst_structure_get_boolean (s, "interlaced", &self->interlaced);
par_present = gst_structure_get_fraction (s, "pixel-aspect-ratio",
&par_width, &par_height);
gst_structure_set (out_s, "pixel-aspect-ratio", GST_TYPE_FRACTION,
par_width, par_height, NULL);
- if (interlaced)
+ if (self->interlaced)
gst_structure_set (out_s, "interlaced", G_TYPE_BOOLEAN, TRUE, NULL);
if (!strcmp (gst_structure_get_name (out_s), "video/x-raw-yuv-strided")) {
GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf);
/* pass new output buffer as to the decoder to decode into: */
- self->inArgs->inputID = codec_prepare_outbuf (self, &outbuf);
+ self->inArgs->inputID = codec_prepare_outbuf (self, &outbuf, self->first_out_buffer);
if (!self->inArgs->inputID) {
GST_ERROR_OBJECT (self, "could not prepare output buffer");
return GST_FLOW_ERROR;
@@ -974,6 +1021,9 @@ gst_ducati_viddec_change_state (GstElement * element, GstStateChange transition)
goto leave;
switch (transition) {
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ self->interlaced = FALSE;
+ break;
case GST_STATE_CHANGE_READY_TO_NULL:
codec_delete (self);
engine_close (self);
self->first_in_buffer = TRUE;
self->first_out_buffer = TRUE;
+ self->interlaced = FALSE;
self->dts_ridx = self->dts_widx = 0;
self->last_dts = self->last_pts = GST_CLOCK_TIME_NONE;
diff --git a/src/gstducatividdec.h b/src/gstducatividdec.h
index 3396e0d6928cf0a014126e192595bad460d679c3..10365e7e90d9802421821a8826837c1654d07eab 100644 (file)
--- a/src/gstducatividdec.h
+++ b/src/gstducatividdec.h
/* output stride (>= padded_width) */
gint stride;
+ gboolean interlaced;
+
/* input buffer, allocated when codec is created: */
guint8 *input;