diff --git a/src/gstducatividdec.c b/src/gstducatividdec.c
index b1622de462664c0c14ce32c2020a6ae7c1ddd669..4d43cd4946a97ba84ea5c8dc0e5b291f20d598dd 100644 (file)
--- a/src/gstducatividdec.c
+++ b/src/gstducatividdec.c
#endif
#include "gstducatividdec.h"
+#include "gstducatibufferpriv.h"
GST_BOILERPLATE (GstDucatiVidDec, gst_ducati_viddec, GstElement,
GST_TYPE_ELEMENT);
dce_free (self->outArgs);
self->outArgs = NULL;
}
+
+ if (self->device) {
+ dce_deinit (self->device);
+ self->device = NULL;
+ }
}
static gboolean
engine_open (GstDucatiVidDec * self)
{
gboolean ret;
+ int ec;
if (G_UNLIKELY (self->engine)) {
return TRUE;
}
+ if (self->device == NULL) {
+ self->device = dce_init ();
+ if (self->device == NULL) {
+ GST_ERROR_OBJECT (self, "dce_init() failed");
+ return FALSE;
+ }
+ }
+
GST_DEBUG_OBJECT (self, "opening engine");
- self->engine = Engine_open ((String) "ivahd_vidsvr", NULL, NULL);
+ self->engine = Engine_open ((String) "ivahd_vidsvr", NULL, &ec);
if (G_UNLIKELY (!self->engine)) {
GST_ERROR_OBJECT (self, "could not create engine");
return FALSE;
codec_delete (GstDucatiVidDec * self)
{
if (self->pool) {
- gst_ducati_bufferpool_destroy (self->pool);
+ gst_drm_buffer_pool_destroy (self->pool);
self->pool = NULL;
}
self->codec = NULL;
}
- if (self->input) {
- MemMgr_Free (self->input);
- self->input = NULL;
+ if (self->input_bo) {
+ omap_bo_del (self->input_bo);
+ self->input_bo = NULL;
}
}
self->first_out_buffer = TRUE;
/* allocate input buffer and initialize inBufs: */
+ self->input_bo = omap_bo_new (self->device,
+ self->width * self->height, OMAP_BO_WC);
+ self->input = omap_bo_map (self->input_bo);
self->inBufs->numBufs = 1;
- self->input = gst_ducati_alloc_1d (self->width * self->height);
- self->inBufs->descs[0].buf = (XDAS_Int8 *) TilerMem_VirtToPhys (self->input);
- self->inBufs->descs[0].memType = XDM_MEMTYPE_RAW;
+ self->inBufs->descs[0].buf = (XDAS_Int8 *) omap_bo_handle (self->input_bo);
return TRUE;
}
static inline GstBuffer *
-codec_bufferpool_get (GstDucatiVidDec * self, GstBuffer * buf)
+codec_buffer_pool_get (GstDucatiVidDec * self, GstBuffer * buf)
{
if (G_UNLIKELY (!self->pool)) {
- guint size;
-
- size = gst_video_format_get_size (GST_VIDEO_FORMAT_NV12,
+ guint size = gst_video_format_get_size (GST_VIDEO_FORMAT_NV12,
self->padded_width, self->padded_height);
+
GST_DEBUG_OBJECT (self, "creating bufferpool");
- self->pool = gst_ducati_bufferpool_new (GST_ELEMENT (self),
- GST_PAD_CAPS (self->srcpad), size);
+ self->pool = gst_drm_buffer_pool_new (GST_ELEMENT (self),
+ dce_get_fd (), GST_PAD_CAPS (self->srcpad), size);
+ }
+ return GST_BUFFER (gst_drm_buffer_pool_get (self->pool, FALSE));
+}
+
+static GstDucatiBufferPriv *
+get_buffer_priv (GstDucatiVidDec * self, GstBuffer * buf)
+{
+ GstDucatiBufferPriv *priv = gst_ducati_buffer_priv_get (buf);
+ if (!priv) {
+ GstVideoFormat format = GST_VIDEO_FORMAT_NV12;
+ GstDmaBuf *dmabuf = gst_buffer_get_dma_buf (buf);
+
+ /* if it isn't a dmabuf buffer that we can import, then there
+ * is nothing we can do with it:
+ */
+ if (!dmabuf) {
+ GST_DEBUG_OBJECT (self, "not importing non dmabuf buffer");
+ return NULL;
+ }
+
+ priv = gst_ducati_buffer_priv_new ();
+
+ priv->bo = omap_bo_from_dmabuf (self->device, gst_dma_buf_get_fd (dmabuf));
+
+ priv->uv_offset = gst_video_format_get_component_offset (format,
+ 1, self->stride, self->padded_height);
+ priv->size = gst_video_format_get_size (format,
+ self->stride, self->padded_height);
+
+ gst_ducati_buffer_priv_set (buf, priv);
}
- return GST_BUFFER (gst_ducati_bufferpool_get (self->pool, buf));
+ return priv;
}
static XDAS_Int32
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;
+ GstDucatiBufferPriv *priv = NULL;
+
+ if (!force_internal)
+ priv = get_buffer_priv (self, *buf);
- if (force_internal) {
+ if (!priv) {
GstBuffer *orig = *buf;
GST_DEBUG_OBJECT (self, "internal bufferpool forced");
- *buf = codec_bufferpool_get (self, NULL);
+ *buf = codec_buffer_pool_get (self, NULL);
GST_BUFFER_TIMESTAMP (*buf) = GST_BUFFER_TIMESTAMP (orig);
GST_BUFFER_DURATION (*buf) = GST_BUFFER_DURATION (orig);
gst_buffer_unref (orig);
return codec_prepare_outbuf (self, buf, FALSE);
}
- y_vaddr = GST_BUFFER_DATA (*buf);
- uv_vaddr = y_vaddr + self->stride * self->padded_height;
+ self->outBufs->numBufs = 2;
+ self->outBufs->descs[0].memType = XDM_MEMTYPE_BO;
+ self->outBufs->descs[0].buf = (XDAS_Int8 *) omap_bo_handle (priv->bo);
+ self->outBufs->descs[0].bufSize.bytes = priv->uv_offset;
+ self->outBufs->descs[1].memType = XDM_MEMTYPE_BO_OFFSET;
+ self->outBufs->descs[1].buf = (XDAS_Int8 *) priv->uv_offset;
+ self->outBufs->descs[1].bufSize.bytes = priv->size - priv->uv_offset;
- y_paddr = TilerMem_VirtToPhys (y_vaddr);
- uv_paddr = TilerMem_VirtToPhys (uv_vaddr);
-
- y_type = gst_ducati_get_mem_type (y_paddr);
- uv_type = gst_ducati_get_mem_type (uv_paddr);
- /* FIXME: workaround for the vc1 codec expecting _RAW when it's actually
- * _TILEDPAGE... should be removed once the codec is fixed */
- if (y_type == XDM_MEMTYPE_TILEDPAGE && self->pageMemType != y_type)
- y_type = self->pageMemType;
- if (uv_type == XDM_MEMTYPE_TILEDPAGE && self->pageMemType != uv_type)
- uv_type = self->pageMemType;
-
- 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, FALSE);
- }
-
- if (!self->outBufs->numBufs) {
- /* initialize output buffer type */
- self->outBufs->numBufs = 2;
- self->outBufs->descs[0].memType = y_type;
- self->outBufs->descs[1].memType = uv_type;
- if (y_type == XDM_MEMTYPE_RAW || y_type == XDM_MEMTYPE_TILEDPAGE) {
- self->outBufs->descs[0].bufSize.bytes =
- self->stride * self->padded_height;
- self->outBufs->descs[1].bufSize.bytes =
- self->stride * self->padded_height / 2;
- } else {
- self->outBufs->descs[0].bufSize.tileMem.width = self->padded_width;
- self->outBufs->descs[0].bufSize.tileMem.height = self->padded_height;
- /* note that UV interleaved width is same a Y: */
- self->outBufs->descs[1].bufSize.tileMem.width = self->padded_width;
- self->outBufs->descs[1].bufSize.tileMem.height = self->padded_height / 2;
- }
- } else {
- /* verify output buffer type matches what we've already given
- * to the codec
- */
- if ((self->outBufs->descs[0].memType != y_type) ||
- (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, FALSE);
- }
- }
-
- self->outBufs->descs[0].buf = (XDAS_Int8 *) y_paddr;
- self->outBufs->descs[1].buf = (XDAS_Int8 *) uv_paddr;
-
- return (XDAS_Int32) *buf; // XXX use lookup table
+ return (XDAS_Int32) * buf; // XXX use lookup table
}
static GstBuffer *
}
static gint
-codec_process (GstDucatiVidDec * self, gboolean send, gboolean flush)
+codec_process (GstDucatiVidDec * self, gboolean send, gboolean flush,
+ GstFlowReturn * flow_ret)
{
gint err;
GstClockTime t;
GstBuffer *outbuf = NULL;
gint i;
GstDucatiVidDecClass *klass = GST_DUCATIVIDDEC_GET_CLASS (self);
+ GstFlowReturn ret = GST_FLOW_OK;
+ if (flow_ret)
+ /* never leave flow_ret uninitialized */
+ *flow_ret = GST_FLOW_OK;
memset (&self->outArgs->outputID, 0, sizeof (self->outArgs->outputID));
memset (&self->outArgs->freeBufID, 0, sizeof (self->outArgs->freeBufID));
self->outArgs->extendedError, self->status->extendedError);
}
- for (i = 0; self->outArgs->outputID[i]; i++) {
+ for (i = 0; i < IVIDEO2_MAX_IO_BUFFERS && 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;
+ interlaced =
+ self->outArgs->decodedBufs.contentType ==
+ IVIDEO_PROGRESSIVE ? FALSE : TRUE;
/* if send is FALSE, don't try to renegotiate as we could be flushing during
* a PAUSED->READY state change
self->interlaced = interlaced;
- caps = gst_caps_make_writable (gst_pad_get_negotiated_caps (self->srcpad));
+ 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);
- gst_ducati_bufferpool_set_caps (self->pool, caps);
+ gst_caps_set_simple (caps, "interlaced", G_TYPE_BOOLEAN, interlaced,
+ NULL);
+ gst_drm_buffer_pool_set_caps (self->pool, caps);
if (!gst_pad_set_caps (self->srcpad, caps)) {
- GST_ERROR_OBJECT (self, "downstream didn't want to change interlace mode");
+ GST_ERROR_OBJECT (self,
+ "downstream didn't want to change interlace mode");
err = XDM_EFAIL;
}
gst_caps_unref (caps);
send = FALSE;
}
- if (G_UNLIKELY (self->first_out_buffer) && send) {
+ if (G_UNLIKELY (self->send_crop_event) && send) {
gint crop_width, crop_height;
- GstDucatiBufferPool *pool;
GstDucatiVidDecClass *klass = GST_DUCATIVIDDEC_GET_CLASS (self);
/* send region of interest to sink on first buffer: */
gst_event_new_crop (r->topLeft.y, r->topLeft.x,
crop_width, crop_height));
+ if (self->crop)
+ gst_video_crop_unref (self->crop);
+
+ self->crop = gst_video_crop_new (r->topLeft.y, r->topLeft.x,
+ crop_width, crop_height);
+
+ self->send_crop_event = FALSE;
+ }
+
+ if (G_UNLIKELY (self->first_out_buffer) && send) {
+ GstDRMBufferPool *pool;
self->first_out_buffer = FALSE;
/* Destroy the pool so the buffers we used so far are eventually released.
*/
pool = self->pool;
self->pool = NULL;
- gst_ducati_bufferpool_destroy (pool);
+ gst_drm_buffer_pool_destroy (pool);
}
if (send) {
GstClockTime ts;
- if (GST_IS_DUCATIBUFFER (outbuf)) {
- outbuf = gst_ducati_buffer_get (GST_DUCATIBUFFER (outbuf));
- }
-
ts = GST_BUFFER_TIMESTAMP (outbuf);
GST_DEBUG_OBJECT (self, "got buffer: %d %p (%" GST_TIME_FORMAT ")",
i, outbuf, GST_TIME_ARGS (ts));
if (self->ts_may_be_pts) {
- if ((self->last_pts != GST_CLOCK_TIME_NONE) &&
- (self->last_pts > ts)) {
+ if ((self->last_pts != GST_CLOCK_TIME_NONE) && (self->last_pts > ts)) {
GST_DEBUG_OBJECT (self, "detected PTS going backwards, "
"enabling ts_is_pts");
self->ts_is_pts = TRUE;
i, outbuf, GST_TIME_ARGS (ts));
}
-
if (GST_BUFFER_CAPS (outbuf) &&
!gst_caps_is_equal (GST_BUFFER_CAPS (outbuf),
GST_PAD_CAPS (self->srcpad))) {
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (self->srcpad));
}
- gst_pad_push (self->srcpad, outbuf);
+ if (self->crop)
+ gst_buffer_set_video_crop (outbuf, self->crop);
+
+ ret = gst_pad_push (self->srcpad, outbuf);
+ if (flow_ret)
+ *flow_ret = ret;
+ if (ret != GST_FLOW_OK) {
+ GST_WARNING_OBJECT (self, "push failed %s", gst_flow_get_name (ret));
+ /* just unref the remaining buffers (if any) */
+ send = FALSE;
+ }
} else {
GST_DEBUG_OBJECT (self, "free buffer: %d %p", i, outbuf);
gst_buffer_unref (outbuf);
}
}
- for (i = 0; self->outArgs->freeBufID[i]; i++) {
+ for (i = 0; i < IVIDEO2_MAX_IO_BUFFERS && self->outArgs->freeBufID[i]; i++) {
codec_unlock_outbuf (self, self->outArgs->freeBufID[i]);
}
}
/** call control(FLUSH), and then process() to pop out all buffers */
-static gboolean
-codec_flush (GstDucatiVidDec * self, gboolean eos)
+gboolean
+gst_ducati_viddec_codec_flush (GstDucatiVidDec * self, gboolean eos)
{
- gint err;
+ gint err = FALSE;
GST_DEBUG_OBJECT (self, "flush: eos=%d", eos);
self->dts_ridx = self->dts_widx = 0;
self->last_dts = self->last_pts = GST_CLOCK_TIME_NONE;
self->ts_may_be_pts = TRUE;
+ self->ts_is_pts = FALSE;
+ self->wait_keyframe = TRUE;
if (G_UNLIKELY (self->first_in_buffer)) {
- return TRUE;
+ goto out;
}
if (G_UNLIKELY (!self->codec)) {
GST_WARNING_OBJECT (self, "no codec");
- return TRUE;
+ goto out;
}
err = VIDDEC3_control (self->codec, XDM_FLUSH, self->dynParams, self->status);
self->inArgs->inputID = 0;
do {
- err = codec_process (self, eos, TRUE);
+ err = codec_process (self, eos, TRUE, NULL);
} while (err != XDM_EFAIL);
+ /* reset outArgs in case we're flushing in codec_process trying to do error
+ * recovery */
+ memset (&self->outArgs->outputID, 0, sizeof (self->outArgs->outputID));
+ memset (&self->outArgs->freeBufID, 0, sizeof (self->outArgs->freeBufID));
+
/* on a flush, it is normal (and not an error) for the last _process() call
* to return an error..
*/
GstStructure *s;
GstCaps *outcaps = NULL;
GstStructure *out_s;
- gint frn = 0, frd = 1;
gint par_width, par_height;
gboolean par_present;
/* update output/padded sizes */
klass->update_buffer_size (self);
- gst_structure_get_fraction (s, "framerate", &frn, &frd);
+ if (!gst_structure_get_fraction (s, "framerate", &self->fps_n, &self->fps_d)) {
+ self->fps_n = 0;
+ self->fps_d = 1;
+ }
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,
"width", G_TYPE_INT, self->padded_width,
"height", G_TYPE_INT, self->padded_height,
- "framerate", GST_TYPE_FRACTION, frn, frd, NULL);
+ "framerate", GST_TYPE_FRACTION, self->fps_n, self->fps_d, NULL);
if (par_present)
gst_structure_set (out_s, "pixel-aspect-ratio", GST_TYPE_FRACTION,
par_width, par_height, NULL);
GST_INFO_OBJECT (self, "outsize %d stride %d outcaps: %" GST_PTR_FORMAT,
self->outsize, self->stride, outcaps);
+ if (!self->first_in_buffer) {
+ /* Caps changed mid stream. We flush the codec to unlock all the potentially
+ * locked buffers. This is needed for downstream sinks that provide a
+ * buffer pool and need to destroy all the outstanding buffers before they
+ * can negotiate new caps (hello v4l2sink).
+ */
+ gst_ducati_viddec_codec_flush (self, FALSE);
+ }
+
+ /* (re)send a crop event when caps change */
+ self->send_crop_event = TRUE;
+
ret = gst_pad_set_caps (self->srcpad, outcaps);
+ GST_INFO_OBJECT (self, "set caps done %d, %" GST_PTR_FORMAT, ret, outcaps);
+
out:
if (outcaps)
gst_caps_unref (outcaps);
return ret;
}
-static gboolean
-gst_ducati_viddec_query (GstPad * pad, GstQuery * query)
+static GstCaps *
+gst_ducati_viddec_src_getcaps (GstPad * pad)
{
- gboolean res = TRUE, forward = TRUE;
- GstDucatiVidDec *self = GST_DUCATIVIDDEC (GST_OBJECT_PARENT (pad));
+ GstCaps *caps = NULL;
+ GstCaps *outcaps = NULL;
+ int i;
- GST_DEBUG_OBJECT (self, "query: %" GST_PTR_FORMAT, query);
+ caps = GST_PAD_CAPS (pad);
+ if (caps == NULL) {
+ outcaps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
+ return outcaps;
+ }
+
+ outcaps = gst_caps_new_empty ();
+
+ /* allow -rowstrided and regular yuv */
+ for (i = 0; i < gst_caps_get_size (caps); i++) {
+ GstStructure *structure;
+ GstStructure *modified_structure;
+ GValue value = { 0 };
+
+ structure = gst_caps_get_structure (caps, i);
+ gst_caps_append_structure (outcaps, gst_structure_copy (structure));
+ modified_structure = gst_structure_copy (structure);
+
+ if (gst_structure_has_name (structure, "video/x-raw-yuv")) {
+ gst_structure_set_name (modified_structure, "video/x-raw-yuv-strided");
+ g_value_init (&value, GST_TYPE_INT_RANGE);
+ gst_value_set_int_range (&value, 0, G_MAXINT);
+ gst_structure_set_value (modified_structure, "rowstride", &value);
+ gst_caps_append_structure (outcaps, modified_structure);
+ g_value_unset (&value);
+ } else {
+ gst_structure_set_name (modified_structure, "video/x-raw-yuv");
+ gst_structure_remove_field (modified_structure, "rowstride");
+ gst_caps_append_structure (outcaps, modified_structure);
+ }
+ }
+ return outcaps;
+}
+
+static gboolean
+gst_ducati_viddec_query (GstDucatiVidDec * self, GstPad * pad,
+ GstQuery * query, gboolean * forward)
+{
+ gboolean res = TRUE;
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_BUFFERS:
self->padded_width, self->padded_height);
gst_query_set_buffers_dimensions (query,
self->padded_width, self->padded_height);
- forward = FALSE;
+ *forward = FALSE;
break;
default:
break;
}
- if (forward)
+
+ return res;
+}
+
+static gboolean
+gst_ducati_viddec_src_query (GstPad * pad, GstQuery * query)
+{
+ gboolean res = TRUE, forward = TRUE;
+ GstDucatiVidDec *self = GST_DUCATIVIDDEC (GST_OBJECT_PARENT (pad));
+ GstDucatiVidDecClass *klass = GST_DUCATIVIDDEC_GET_CLASS (self);
+
+ GST_DEBUG_OBJECT (self, "query: %" GST_PTR_FORMAT, query);
+ res = klass->query (self, pad, query, &forward);
+ if (res && forward)
res = gst_pad_query_default (pad, query);
return res;
GstDucatiVidDecClass *klass = GST_DUCATIVIDDEC_GET_CLASS (self);
gint64 diff;
+ if (self->wait_keyframe) {
+ if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) {
+ GST_INFO_OBJECT (self, "skipping until the next keyframe");
+ return FALSE;
+ }
+
+ self->wait_keyframe = FALSE;
+ }
+
timestamp = GST_BUFFER_TIMESTAMP (buf);
if (self->segment.format != GST_FORMAT_TIME ||
self->qos_earliest_time == GST_CLOCK_TIME_NONE)
{
GstDucatiVidDec *self = GST_DUCATIVIDDEC (GST_OBJECT_PARENT (pad));
GstClockTime ts = GST_BUFFER_TIMESTAMP (buf);
- GstFlowReturn ret;
+ GstFlowReturn ret = GST_FLOW_OK;
Int32 err;
GstBuffer *outbuf = NULL;
GstCaps *outcaps = NULL;
if (G_UNLIKELY (!self->engine)) {
GST_ERROR_OBJECT (self, "no engine");
+ gst_buffer_unref (buf);
return GST_FLOW_ERROR;
}
ret = gst_pad_alloc_buffer (self->srcpad, 0, self->outsize,
GST_PAD_CAPS (self->srcpad), &outbuf);
if (ret != GST_FLOW_OK) {
- GST_ERROR_OBJECT (self, "alloc_buffer failed %s", gst_flow_get_name (ret));
+ GST_WARNING_OBJECT (self, "alloc_buffer failed %s",
+ gst_flow_get_name (ret));
+ gst_buffer_unref (buf);
return ret;
}
if (G_UNLIKELY (!self->codec)) {
if (!codec_create (self)) {
GST_ERROR_OBJECT (self, "could not create codec");
+ gst_buffer_unref (buf);
+ gst_buffer_unref (outbuf);
return GST_FLOW_ERROR;
}
}
/* Pass new output buffer to the decoder to decode into. Use buffers from the
* internal pool while self->first_out_buffer == TRUE in order to simplify
* things in case we need to renegotiate */
- self->inArgs->inputID = codec_prepare_outbuf (self, &outbuf, self->first_out_buffer);
+ 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");
+ gst_buffer_unref (buf);
return GST_FLOW_ERROR;
}
/* if next buffer has earlier ts than previous, then the ts
* we are getting are definitely decode order (DTS):
*/
- if ((self->last_dts != GST_CLOCK_TIME_NONE) &&
- (self->last_dts > ts)) {
+ if ((self->last_dts != GST_CLOCK_TIME_NONE) && (self->last_dts > ts)) {
GST_DEBUG_OBJECT (self, "input timestamp definitely DTS");
self->ts_may_be_pts = FALSE;
}
self->inArgs->numBytes = self->in_size;
self->inBufs->descs[0].bufSize.bytes = self->in_size;
+ self->inBufs->descs[0].memType = XDM_MEMTYPE_BO;
- err = codec_process (self, TRUE, FALSE);
+ err = codec_process (self, TRUE, FALSE, &ret);
if (err) {
GST_ELEMENT_ERROR (self, STREAM, DECODE, (NULL),
("process returned error: %d %08x", err, self->outArgs->extendedError));
return GST_FLOW_ERROR;
}
+ if (ret != GST_FLOW_OK) {
+ GST_WARNING_OBJECT (self, "push from codec_process failed %s",
+ gst_flow_get_name (ret));
+ return ret;
+ }
self->first_in_buffer = FALSE;
break;
}
case GST_EVENT_EOS:
- if (!codec_flush (self, TRUE)) {
+ if (!gst_ducati_viddec_codec_flush (self, TRUE)) {
GST_ERROR_OBJECT (self, "could not flush on eos");
ret = FALSE;
}
break;
case GST_EVENT_FLUSH_STOP:
- if (!codec_flush (self, FALSE)) {
+ if (!gst_ducati_viddec_codec_flush (self, FALSE)) {
GST_ERROR_OBJECT (self, "could not flush");
+ gst_event_unref (event);
ret = FALSE;
}
gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
@@ -1034,6 +1156,7 @@ gst_ducati_viddec_change_state (GstElement * element, GstStateChange transition)
{
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
GstDucatiVidDec *self = GST_DUCATIVIDDEC (element);
+ gboolean supported;
GST_DEBUG_OBJECT (self, "begin: changing state %s -> %s",
gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
@@ -1045,6 +1168,16 @@ gst_ducati_viddec_change_state (GstElement * element, GstStateChange transition)
GST_ERROR_OBJECT (self, "could not open");
return GST_STATE_CHANGE_FAILURE;
}
+ /* try to create/destroy the codec here, it may not be supported */
+ supported = codec_create (self);
+ codec_delete (self);
+ self->codec = NULL;
+ if (!supported) {
+ GST_ERROR_OBJECT (element, "Failed to create codec %s, not supported",
+ GST_DUCATIVIDDEC_GET_CLASS (self)->codec_name);
+ engine_close (self);
+ return GST_STATE_CHANGE_FAILURE;
+ }
break;
default:
break;
@@ -1058,7 +1191,8 @@ gst_ducati_viddec_change_state (GstElement * element, GstStateChange transition)
switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_READY:
self->interlaced = FALSE;
- codec_flush (self, FALSE);
+ self->send_crop_event = TRUE;
+ gst_ducati_viddec_codec_flush (self, FALSE);
break;
case GST_STATE_CHANGE_READY_TO_NULL:
codec_delete (self);
{
GstDucatiVidDec *self = GST_DUCATIVIDDEC (obj);
+
switch (prop_id) {
case PROP_VERSION:{
int err;
- char *version = gst_ducati_alloc_1d (VERSION_LENGTH);
-
- /* in case something fails: */
- snprintf (version, VERSION_LENGTH, "unsupported");
+ char *version = NULL;
if (!self->engine)
engine_open (self);
codec_create (self);
if (self->codec) {
- self->status->data.buf = (XDAS_Int8 *) TilerMem_VirtToPhys (version);
+ version = dce_alloc (VERSION_LENGTH);
+ self->status->data.buf = (XDAS_Int8 *) version;
self->status->data.bufSize = VERSION_LENGTH;
err = VIDDEC3_control (self->codec, XDM_GETVERSION,
}
g_value_set_string (value, version);
-
- MemMgr_Free (version);
+ if (version)
+ dce_free (version);
break;
}
klass->push_input = GST_DEBUG_FUNCPTR (gst_ducati_viddec_push_input);
klass->handle_error = GST_DEBUG_FUNCPTR (gst_ducati_viddec_handle_error);
klass->drop_frame = GST_DEBUG_FUNCPTR (gst_ducati_viddec_drop_frame);
+ klass->query = GST_DEBUG_FUNCPTR (gst_ducati_viddec_query);
g_object_class_install_property (gobject_class, PROP_VERSION,
g_param_spec_string ("version", "Version",
gst_pad_set_event_function (self->srcpad,
GST_DEBUG_FUNCPTR (gst_ducati_viddec_src_event));
gst_pad_set_query_function (self->srcpad,
- GST_DEBUG_FUNCPTR (gst_ducati_viddec_query));
+ GST_DEBUG_FUNCPTR (gst_ducati_viddec_src_query));
+ gst_pad_set_getcaps_function (self->srcpad,
+ GST_DEBUG_FUNCPTR (gst_ducati_viddec_src_getcaps));
gst_element_add_pad (GST_ELEMENT (self), self->sinkpad);
gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
@@ -1206,10 +1342,13 @@ gst_ducati_viddec_init (GstDucatiVidDec * self, GstDucatiVidDecClass * klass)
*/
self->width = 128;
self->height = 128;
+ self->fps_n = -1;
+ self->fps_d = -1;
self->first_in_buffer = TRUE;
self->first_out_buffer = TRUE;
self->interlaced = FALSE;
+ self->send_crop_event = TRUE;
self->dts_ridx = self->dts_widx = 0;
self->last_dts = self->last_pts = GST_CLOCK_TIME_NONE;
self->qos_proportion = 1;
self->qos_earliest_time = GST_CLOCK_TIME_NONE;
+ self->wait_keyframe = TRUE;
self->need_out_buf = TRUE;
+ self->device = NULL;
+ self->input_bo = NULL;
}