mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
y4mdec: Use the correct strides as used by y4m and convert to GStreamer strides if necessary
https://bugzilla.gnome.org/show_bug.cgi?id=696361
This commit is contained in:
parent
c2966fce30
commit
dfa6c17de5
2 changed files with 173 additions and 1 deletions
|
@ -196,10 +196,13 @@ gst_y4m_dec_finalize (GObject * object)
|
||||||
static GstStateChangeReturn
|
static GstStateChangeReturn
|
||||||
gst_y4m_dec_change_state (GstElement * element, GstStateChange transition)
|
gst_y4m_dec_change_state (GstElement * element, GstStateChange transition)
|
||||||
{
|
{
|
||||||
|
GstY4mDec *y4mdec;
|
||||||
GstStateChangeReturn ret;
|
GstStateChangeReturn ret;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_Y4M_DEC (element), GST_STATE_CHANGE_FAILURE);
|
g_return_val_if_fail (GST_IS_Y4M_DEC (element), GST_STATE_CHANGE_FAILURE);
|
||||||
|
|
||||||
|
y4mdec = GST_Y4M_DEC (element);
|
||||||
|
|
||||||
switch (transition) {
|
switch (transition) {
|
||||||
case GST_STATE_CHANGE_NULL_TO_READY:
|
case GST_STATE_CHANGE_NULL_TO_READY:
|
||||||
break;
|
break;
|
||||||
|
@ -217,6 +220,11 @@ gst_y4m_dec_change_state (GstElement * element, GstStateChange transition)
|
||||||
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
|
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
|
||||||
break;
|
break;
|
||||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||||
|
if (y4mdec->pool) {
|
||||||
|
gst_buffer_pool_set_active (y4mdec->pool, FALSE);
|
||||||
|
gst_object_unref (y4mdec->pool);
|
||||||
|
}
|
||||||
|
y4mdec->pool = NULL;
|
||||||
break;
|
break;
|
||||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
case GST_STATE_CHANGE_READY_TO_NULL:
|
||||||
break;
|
break;
|
||||||
|
@ -392,7 +400,49 @@ gst_y4m_dec_parse_header (GstY4mDec * y4mdec, char *header)
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_video_info_init (&y4mdec->info);
|
gst_video_info_init (&y4mdec->info);
|
||||||
gst_video_info_set_format (&y4mdec->info, format, width, height);
|
gst_video_info_set_format (&y4mdec->out_info, format, width, height);
|
||||||
|
y4mdec->info = y4mdec->out_info;
|
||||||
|
|
||||||
|
switch (y4mdec->info.finfo->format) {
|
||||||
|
case GST_VIDEO_FORMAT_I420:
|
||||||
|
y4mdec->info.offset[0] = 0;
|
||||||
|
y4mdec->info.stride[0] = width;
|
||||||
|
y4mdec->info.offset[1] = y4mdec->info.stride[0] * height;
|
||||||
|
y4mdec->info.stride[1] = GST_ROUND_UP_2 (width) / 2;
|
||||||
|
y4mdec->info.offset[2] =
|
||||||
|
y4mdec->info.offset[1] +
|
||||||
|
y4mdec->info.stride[1] * (GST_ROUND_UP_2 (height) / 2);
|
||||||
|
y4mdec->info.stride[2] = GST_ROUND_UP_2 (width) / 2;
|
||||||
|
y4mdec->info.size =
|
||||||
|
y4mdec->info.offset[2] +
|
||||||
|
y4mdec->info.stride[2] * (GST_ROUND_UP_2 (height) / 2);
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_FORMAT_Y42B:
|
||||||
|
y4mdec->info.offset[0] = 0;
|
||||||
|
y4mdec->info.stride[0] = width;
|
||||||
|
y4mdec->info.offset[1] = y4mdec->info.stride[0] * height;
|
||||||
|
y4mdec->info.stride[1] = GST_ROUND_UP_2 (width) / 2;
|
||||||
|
y4mdec->info.offset[2] =
|
||||||
|
y4mdec->info.offset[1] + y4mdec->info.stride[1] * height;
|
||||||
|
y4mdec->info.stride[2] = GST_ROUND_UP_2 (width) / 2;
|
||||||
|
y4mdec->info.size =
|
||||||
|
y4mdec->info.offset[2] + y4mdec->info.stride[2] * height;
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_FORMAT_Y444:
|
||||||
|
y4mdec->info.offset[0] = 0;
|
||||||
|
y4mdec->info.stride[0] = width;
|
||||||
|
y4mdec->info.offset[1] = y4mdec->info.stride[0] * height;
|
||||||
|
y4mdec->info.stride[1] = width;
|
||||||
|
y4mdec->info.offset[2] =
|
||||||
|
y4mdec->info.offset[1] + y4mdec->info.stride[1] * height;
|
||||||
|
y4mdec->info.stride[2] = width;
|
||||||
|
y4mdec->info.size =
|
||||||
|
y4mdec->info.offset[2] + y4mdec->info.stride[2] * height;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
switch (interlaced_char) {
|
switch (interlaced_char) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -457,6 +507,7 @@ gst_y4m_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
||||||
if (!y4mdec->have_header) {
|
if (!y4mdec->have_header) {
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
|
GstQuery *query;
|
||||||
|
|
||||||
if (n_avail < MAX_HEADER_LENGTH)
|
if (n_avail < MAX_HEADER_LENGTH)
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
@ -481,6 +532,78 @@ gst_y4m_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
||||||
|
|
||||||
caps = gst_video_info_to_caps (&y4mdec->info);
|
caps = gst_video_info_to_caps (&y4mdec->info);
|
||||||
ret = gst_pad_set_caps (y4mdec->srcpad, caps);
|
ret = gst_pad_set_caps (y4mdec->srcpad, caps);
|
||||||
|
|
||||||
|
query = gst_query_new_allocation (caps, FALSE);
|
||||||
|
y4mdec->video_meta = FALSE;
|
||||||
|
|
||||||
|
if (y4mdec->pool) {
|
||||||
|
gst_buffer_pool_set_active (y4mdec->pool, FALSE);
|
||||||
|
gst_object_unref (y4mdec->pool);
|
||||||
|
}
|
||||||
|
y4mdec->pool = NULL;
|
||||||
|
|
||||||
|
if (gst_pad_peer_query (y4mdec->srcpad, query)) {
|
||||||
|
y4mdec->video_meta =
|
||||||
|
gst_query_find_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* We only need a pool if we need to do stride conversion for downstream */
|
||||||
|
if (!y4mdec->video_meta && memcmp (&y4mdec->info, &y4mdec->out_info,
|
||||||
|
sizeof (y4mdec->info)) != 0) {
|
||||||
|
GstBufferPool *pool = NULL;
|
||||||
|
GstAllocator *allocator = NULL;
|
||||||
|
GstAllocationParams params;
|
||||||
|
GstStructure *config;
|
||||||
|
guint size, min, max;
|
||||||
|
|
||||||
|
if (gst_query_get_n_allocation_params (query) > 0) {
|
||||||
|
gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms);
|
||||||
|
} else {
|
||||||
|
allocator = NULL;
|
||||||
|
gst_allocation_params_init (¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gst_query_get_n_allocation_pools (query) > 0) {
|
||||||
|
gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min,
|
||||||
|
&max);
|
||||||
|
size = MAX (size, y4mdec->out_info.size);
|
||||||
|
} else {
|
||||||
|
pool = NULL;
|
||||||
|
size = y4mdec->out_info.size;
|
||||||
|
min = max = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pool == NULL) {
|
||||||
|
pool = gst_video_buffer_pool_new ();
|
||||||
|
}
|
||||||
|
|
||||||
|
config = gst_buffer_pool_get_config (pool);
|
||||||
|
gst_buffer_pool_config_set_params (config, caps, size, min, max);
|
||||||
|
gst_buffer_pool_config_set_allocator (config, allocator, ¶ms);
|
||||||
|
gst_buffer_pool_set_config (pool, config);
|
||||||
|
|
||||||
|
if (allocator)
|
||||||
|
gst_object_unref (allocator);
|
||||||
|
|
||||||
|
y4mdec->pool = pool;
|
||||||
|
}
|
||||||
|
} else if (memcmp (&y4mdec->info, &y4mdec->out_info,
|
||||||
|
sizeof (y4mdec->info)) != 0) {
|
||||||
|
GstBufferPool *pool;
|
||||||
|
GstStructure *config;
|
||||||
|
|
||||||
|
/* No pool, create our own if we need to do stride conversion */
|
||||||
|
pool = gst_video_buffer_pool_new ();
|
||||||
|
config = gst_buffer_pool_get_config (pool);
|
||||||
|
gst_buffer_pool_config_set_params (config, caps, y4mdec->out_info.size, 0,
|
||||||
|
0);
|
||||||
|
gst_buffer_pool_set_config (pool, config);
|
||||||
|
y4mdec->pool = pool;
|
||||||
|
}
|
||||||
|
if (y4mdec->pool) {
|
||||||
|
gst_buffer_pool_set_active (y4mdec->pool, TRUE);
|
||||||
|
}
|
||||||
|
gst_query_unref (query);
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
GST_DEBUG_OBJECT (y4mdec, "Couldn't set caps on src pad");
|
GST_DEBUG_OBJECT (y4mdec, "Couldn't set caps on src pad");
|
||||||
|
@ -554,6 +677,52 @@ gst_y4m_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
||||||
|
|
||||||
y4mdec->frame_index++;
|
y4mdec->frame_index++;
|
||||||
|
|
||||||
|
if (y4mdec->video_meta) {
|
||||||
|
gst_buffer_add_video_meta_full (buffer, 0, y4mdec->info.finfo->format,
|
||||||
|
y4mdec->info.width, y4mdec->info.height, y4mdec->info.finfo->n_planes,
|
||||||
|
y4mdec->info.offset, y4mdec->info.stride);
|
||||||
|
} else if (memcmp (&y4mdec->info, &y4mdec->out_info,
|
||||||
|
sizeof (y4mdec->info)) != 0) {
|
||||||
|
GstBuffer *outbuf;
|
||||||
|
GstVideoFrame iframe, oframe;
|
||||||
|
gint i, j;
|
||||||
|
gint w, h, istride, ostride;
|
||||||
|
guint8 *src, *dest;
|
||||||
|
|
||||||
|
/* Allocate a new buffer and do stride conversion */
|
||||||
|
g_assert (y4mdec->pool != NULL);
|
||||||
|
|
||||||
|
flow_ret = gst_buffer_pool_acquire_buffer (y4mdec->pool, &outbuf, NULL);
|
||||||
|
if (flow_ret != GST_FLOW_OK) {
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_video_frame_map (&iframe, &y4mdec->info, buffer, GST_MAP_READ);
|
||||||
|
gst_video_frame_map (&oframe, &y4mdec->out_info, outbuf, GST_MAP_WRITE);
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
w = GST_VIDEO_FRAME_COMP_WIDTH (&iframe, i);;
|
||||||
|
h = GST_VIDEO_FRAME_COMP_HEIGHT (&iframe, i);;
|
||||||
|
istride = GST_VIDEO_FRAME_COMP_STRIDE (&iframe, i);;
|
||||||
|
ostride = GST_VIDEO_FRAME_COMP_STRIDE (&oframe, i);;
|
||||||
|
src = GST_VIDEO_FRAME_COMP_DATA (&iframe, i);
|
||||||
|
dest = GST_VIDEO_FRAME_COMP_DATA (&oframe, i);
|
||||||
|
|
||||||
|
for (j = 0; j < h; j++) {
|
||||||
|
memcpy (dest, src, w);
|
||||||
|
|
||||||
|
dest += ostride;
|
||||||
|
src += istride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_video_frame_unmap (&iframe);
|
||||||
|
gst_video_frame_unmap (&oframe);
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
buffer = outbuf;
|
||||||
|
}
|
||||||
|
|
||||||
flow_ret = gst_pad_push (y4mdec->srcpad, buffer);
|
flow_ret = gst_pad_push (y4mdec->srcpad, buffer);
|
||||||
if (flow_ret != GST_FLOW_OK)
|
if (flow_ret != GST_FLOW_OK)
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -51,6 +51,9 @@ struct _GstY4mDec
|
||||||
GstSegment segment;
|
GstSegment segment;
|
||||||
|
|
||||||
GstVideoInfo info;
|
GstVideoInfo info;
|
||||||
|
GstVideoInfo out_info;
|
||||||
|
gboolean video_meta;
|
||||||
|
GstBufferPool *pool;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstY4mDecClass
|
struct _GstY4mDecClass
|
||||||
|
|
Loading…
Reference in a new issue