summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian@centricular.com>2014-06-24 14:52:58 +0200
committerSebastian Dröge <sebastian@centricular.com>2014-06-24 15:11:53 +0200
commit4593f434a06d8d3b46338e0762e93c558ea4e58d (patch)
tree832f7f79ceee8c55b763a759549557be3e9d0137
parentb9238195dd983ec2803073ab66167324de9afe01 (diff)
downloadgst-omx-4593f434a06d8d3b46338e0762e93c558ea4e58d.tar.gz
omxbufferpool: Copy buffers if the stride does not match and we can't use video meta
https://bugzilla.gnome.org/show_bug.cgi?id=731672
-rw-r--r--omx/gstomxbufferpool.c83
-rw-r--r--omx/gstomxbufferpool.h1
-rw-r--r--omx/gstomxvideodec.c40
3 files changed, 95 insertions, 29 deletions
diff --git a/omx/gstomxbufferpool.c b/omx/gstomxbufferpool.c
index 65f4a41..b57612d 100644
--- a/omx/gstomxbufferpool.c
+++ b/omx/gstomxbufferpool.c
@@ -380,46 +380,73 @@ gst_omx_buffer_pool_alloc_buffer (GstBufferPool * bpool,
GST_VIDEO_INFO_HEIGHT (&pool->video_info));
}
}
+
+ pool->need_copy = FALSE;
} else {
GstMemory *mem;
+ const guint nstride = pool->port->port_def.format.video.nStride;
+ const guint nslice = pool->port->port_def.format.video.nSliceHeight;
+ gsize offset[GST_VIDEO_MAX_PLANES] = { 0, };
+ gint stride[GST_VIDEO_MAX_PLANES] = { nstride, 0, };
mem = gst_omx_memory_allocator_alloc (pool->allocator, 0, omx_buf);
buf = gst_buffer_new ();
gst_buffer_append_memory (buf, mem);
g_ptr_array_add (pool->buffers, buf);
+ switch (GST_VIDEO_INFO_FORMAT (&pool->video_info)) {
+ case GST_VIDEO_FORMAT_ABGR:
+ case GST_VIDEO_FORMAT_ARGB:
+ case GST_VIDEO_FORMAT_RGB16:
+ case GST_VIDEO_FORMAT_BGR16:
+ case GST_VIDEO_FORMAT_YUY2:
+ case GST_VIDEO_FORMAT_UYVY:
+ case GST_VIDEO_FORMAT_YVYU:
+ case GST_VIDEO_FORMAT_GRAY8:
+ break;
+ case GST_VIDEO_FORMAT_I420:
+ stride[1] = nstride / 2;
+ offset[1] = offset[0] + stride[0] * nslice;
+ stride[2] = nstride / 2;
+ offset[2] = offset[1] + (stride[1] * nslice / 2);
+ break;
+ case GST_VIDEO_FORMAT_NV12:
+ case GST_VIDEO_FORMAT_NV16:
+ stride[1] = nstride;
+ offset[1] = offset[0] + stride[0] * nslice;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
if (pool->add_videometa) {
- const guint nstride = pool->port->port_def.format.video.nStride;
- const guint nslice = pool->port->port_def.format.video.nSliceHeight;
- gsize offset[GST_VIDEO_MAX_PLANES] = { 0, };
- gint stride[GST_VIDEO_MAX_PLANES] = { nstride, 0, };
-
- switch (GST_VIDEO_INFO_FORMAT (&pool->video_info)) {
- case GST_VIDEO_FORMAT_ABGR:
- case GST_VIDEO_FORMAT_ARGB:
- case GST_VIDEO_FORMAT_RGB16:
- case GST_VIDEO_FORMAT_BGR16:
- case GST_VIDEO_FORMAT_YUY2:
- case GST_VIDEO_FORMAT_UYVY:
- case GST_VIDEO_FORMAT_YVYU:
- case GST_VIDEO_FORMAT_GRAY8:
- break;
- case GST_VIDEO_FORMAT_I420:
- stride[1] = nstride / 2;
- offset[1] = offset[0] + stride[0] * nslice;
- stride[2] = nstride / 2;
- offset[2] = offset[1] + (stride[1] * nslice / 2);
- break;
- case GST_VIDEO_FORMAT_NV12:
- case GST_VIDEO_FORMAT_NV16:
- stride[1] = nstride;
- offset[1] = offset[0] + stride[0] * nslice;
- break;
- default:
- g_assert_not_reached ();
+ pool->need_copy = FALSE;
+ } else {
+ GstVideoInfo info;
+ gboolean need_copy = FALSE;
+ gint i;
+
+ gst_video_info_init (&info);
+ gst_video_info_set_format (&info,
+ GST_VIDEO_INFO_FORMAT (&pool->video_info),
+ GST_VIDEO_INFO_WIDTH (&pool->video_info),
+ GST_VIDEO_INFO_HEIGHT (&pool->video_info));
+
+ for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&pool->video_info); i++) {
+ if (info.stride[i] != stride[i] || info.offset[i] != offset[i]) {
+ need_copy = TRUE;
break;
+ }
}
+ pool->need_copy = need_copy;
+ }
+
+ if (pool->need_copy || pool->add_videometa) {
+ /* We always add the videometa. It's the job of the user
+ * to copy the buffer if pool->need_copy is TRUE
+ */
gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE,
GST_VIDEO_INFO_FORMAT (&pool->video_info),
GST_VIDEO_INFO_WIDTH (&pool->video_info),
diff --git a/omx/gstomxbufferpool.h b/omx/gstomxbufferpool.h
index f2c008d..76f9680 100644
--- a/omx/gstomxbufferpool.h
+++ b/omx/gstomxbufferpool.h
@@ -51,6 +51,7 @@ struct _GstOMXBufferPool
GstCaps *caps;
gboolean add_videometa;
+ gboolean need_copy;
GstVideoInfo video_info;
/* Owned by element, element has to stop this pool before
diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c
index eb52d13..8590301 100644
--- a/omx/gstomxvideodec.c
+++ b/omx/gstomxvideodec.c
@@ -1214,6 +1214,29 @@ gst_omx_video_dec_clean_older_frames (GstOMXVideoDec * self,
g_list_free (frames);
}
+static GstBuffer *
+copy_frame (const GstVideoInfo * info, GstBuffer * outbuf)
+{
+ GstVideoInfo out_info, tmp_info;
+ GstBuffer *tmpbuf;
+ GstVideoFrame out_frame, tmp_frame;
+
+ out_info = *info;
+ tmp_info = *info;
+
+ tmpbuf = gst_buffer_new_and_alloc (out_info.size);
+
+ gst_video_frame_map (&out_frame, &out_info, outbuf, GST_MAP_READ);
+ gst_video_frame_map (&tmp_frame, &tmp_info, tmpbuf, GST_MAP_WRITE);
+ gst_video_frame_copy (&tmp_frame, &out_frame);
+ gst_video_frame_unmap (&out_frame);
+ gst_video_frame_unmap (&tmp_frame);
+
+ gst_buffer_unref (outbuf);
+
+ return tmpbuf;
+}
+
static void
gst_omx_video_dec_loop (GstOMXVideoDec * self)
{
@@ -1392,6 +1415,12 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
gst_omx_port_release_buffer (port, buf);
goto invalid_buffer;
}
+
+ if (GST_OMX_BUFFER_POOL (self->out_port_pool)->need_copy)
+ outbuf =
+ copy_frame (&GST_OMX_BUFFER_POOL (self->out_port_pool)->video_info,
+ outbuf);
+
buf = NULL;
} else {
outbuf =
@@ -1407,6 +1436,7 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
} else if (buf->omx_buf->nFilledLen > 0 || buf->eglimage) {
if (self->out_port_pool) {
gint i, n;
+ GstBuffer *outbuf;
GstBufferPoolAcquireParams params = { 0, };
n = port->buffers->len;
@@ -1421,7 +1451,7 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
GST_OMX_BUFFER_POOL (self->out_port_pool)->current_buffer_index = i;
flow_ret =
gst_buffer_pool_acquire_buffer (self->out_port_pool,
- &frame->output_buffer, &params);
+ &outbuf, &params);
if (flow_ret != GST_FLOW_OK) {
flow_ret =
gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
@@ -1429,6 +1459,14 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
gst_omx_port_release_buffer (port, buf);
goto invalid_buffer;
}
+
+ if (GST_OMX_BUFFER_POOL (self->out_port_pool)->need_copy)
+ outbuf =
+ copy_frame (&GST_OMX_BUFFER_POOL (self->out_port_pool)->video_info,
+ outbuf);
+
+ frame->output_buffer = outbuf;
+
flow_ret =
gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
frame = NULL;