mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
theoradec: move negotiation code around
Move the format negotiation to the bufferpool negotiation.
This commit is contained in:
parent
271939d118
commit
f9bdf436f9
2 changed files with 137 additions and 125 deletions
|
@ -768,122 +768,26 @@ theora_handle_comment_packet (GstTheoraDec * dec, ogg_packet * packet)
|
|||
}
|
||||
|
||||
static GstFlowReturn
|
||||
theora_negotiate_pool (GstTheoraDec * dec)
|
||||
theora_negotiate (GstTheoraDec * dec)
|
||||
{
|
||||
GstVideoFormat format;
|
||||
GstQuery *query;
|
||||
GstBufferPool *pool;
|
||||
guint size, min, max, prefix, alignment;
|
||||
GstStructure *config;
|
||||
GstCaps *caps;
|
||||
GstVideoInfo info;
|
||||
GstVideoInfo info, cinfo;
|
||||
|
||||
/* for the output caps we always take the cropped dimensions */
|
||||
info = dec->vinfo;
|
||||
gst_video_info_set_format (&info, GST_VIDEO_INFO_FORMAT (&info),
|
||||
dec->info.pic_width, dec->info.pic_height);
|
||||
caps = gst_video_info_to_caps (&info);
|
||||
gst_pad_set_caps (dec->srcpad, caps);
|
||||
|
||||
/* find a pool for the negotiated caps now */
|
||||
query = gst_query_new_allocation (caps, TRUE);
|
||||
|
||||
if (gst_pad_peer_query (dec->srcpad, query)) {
|
||||
GST_DEBUG_OBJECT (dec, "got downstream ALLOCATION hints");
|
||||
/* we got configuration from our peer, parse them */
|
||||
gst_query_parse_allocation_params (query, &size, &min, &max, &prefix,
|
||||
&alignment, &pool);
|
||||
|
||||
/* check if downstream supports cropping */
|
||||
dec->has_cropping =
|
||||
gst_query_has_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE);
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (dec, "didn't get downstream ALLOCATION hints");
|
||||
size = 0;
|
||||
min = max = 0;
|
||||
prefix = 0;
|
||||
alignment = 0;
|
||||
pool = NULL;
|
||||
dec->has_cropping = FALSE;
|
||||
}
|
||||
|
||||
if (pool == NULL) {
|
||||
/* we did not get a pool, make one ourselves then */
|
||||
pool = gst_video_buffer_pool_new ();
|
||||
}
|
||||
|
||||
if (dec->pool)
|
||||
gst_object_unref (dec->pool);
|
||||
dec->pool = pool;
|
||||
|
||||
if (dec->has_cropping) {
|
||||
dec->outinfo = dec->vinfo;
|
||||
/* we can crop, configure the pool with buffers of caps and size of the
|
||||
* decoded picture size and then crop them with metadata */
|
||||
gst_caps_unref (caps);
|
||||
caps = gst_video_info_to_caps (&dec->vinfo);
|
||||
} else {
|
||||
/* no cropping, use cropped videoinfo */
|
||||
dec->outinfo = info;
|
||||
}
|
||||
size = MAX (size, GST_VIDEO_INFO_SIZE (&dec->outinfo));
|
||||
|
||||
config = gst_buffer_pool_get_config (pool);
|
||||
gst_buffer_pool_config_set (config, caps, size, min, max, prefix, alignment);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
/* just set the option, if the pool can support it we will transparently use
|
||||
* it through the video info API. We could also see if the pool support this
|
||||
* option and only activate it then. */
|
||||
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
|
||||
|
||||
GST_DEBUG_OBJECT (dec, "downstream cropping %d", dec->has_cropping);
|
||||
|
||||
gst_buffer_pool_set_config (pool, config);
|
||||
/* and activate */
|
||||
gst_buffer_pool_set_active (pool, TRUE);
|
||||
|
||||
gst_query_unref (query);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
|
||||
{
|
||||
GstVideoFormat format;
|
||||
gint par_num, par_den;
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
GList *walk;
|
||||
|
||||
GST_DEBUG_OBJECT (dec, "fps %d/%d, PAR %d/%d",
|
||||
dec->info.fps_numerator, dec->info.fps_denominator,
|
||||
dec->info.aspect_numerator, dec->info.aspect_denominator);
|
||||
|
||||
/* calculate par
|
||||
* the info.aspect_* values reflect PAR;
|
||||
* 0:x and x:0 are allowed and can be interpreted as 1:1.
|
||||
*/
|
||||
if (dec->have_par) {
|
||||
/* we had a par on the sink caps, override the encoded par */
|
||||
GST_DEBUG_OBJECT (dec, "overriding with input PAR");
|
||||
par_num = dec->par_num;
|
||||
par_den = dec->par_den;
|
||||
} else {
|
||||
/* take encoded par */
|
||||
par_num = dec->info.aspect_numerator;
|
||||
par_den = dec->info.aspect_denominator;
|
||||
}
|
||||
if (par_num == 0 || par_den == 0) {
|
||||
par_num = par_den = 1;
|
||||
}
|
||||
/* theora has:
|
||||
*
|
||||
* frame_width/frame_height : dimension of the encoded frame
|
||||
* pic_width/pic_height : dimension of the visible part
|
||||
* pic_x/pic_y : offset in encoded frame where visible part starts
|
||||
*/
|
||||
GST_DEBUG_OBJECT (dec, "frame dimension %dx%d, PAR %d/%d",
|
||||
dec->info.frame_width, dec->info.frame_height, par_num, par_den);
|
||||
GST_DEBUG_OBJECT (dec, "frame dimension %dx%d, PAR %d/%d, fps %d/%d",
|
||||
dec->info.frame_width, dec->info.frame_height,
|
||||
dec->info.aspect_numerator, dec->info.aspect_denominator,
|
||||
dec->info.fps_numerator, dec->info.fps_denominator);
|
||||
GST_DEBUG_OBJECT (dec, "picture dimension %dx%d, offset %d:%d",
|
||||
dec->info.pic_width, dec->info.pic_height, dec->info.pic_x,
|
||||
dec->info.pic_y);
|
||||
|
@ -915,36 +819,135 @@ theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
|
|||
dec->need_cropping = FALSE;
|
||||
}
|
||||
|
||||
/* our info contains the dimensions for the coded picture before cropping */
|
||||
gst_video_info_set_format (&dec->vinfo, format, dec->info.frame_width,
|
||||
/* info contains the dimensions for the coded picture before cropping */
|
||||
gst_video_info_set_format (&info, format, dec->info.frame_width,
|
||||
dec->info.frame_height);
|
||||
dec->vinfo.fps_n = dec->info.fps_numerator;
|
||||
dec->vinfo.fps_d = dec->info.fps_denominator;
|
||||
dec->vinfo.par_n = par_num;
|
||||
dec->vinfo.par_d = par_den;
|
||||
info.fps_n = dec->info.fps_numerator;
|
||||
info.fps_d = dec->info.fps_denominator;
|
||||
/* calculate par
|
||||
* the info.aspect_* values reflect PAR;
|
||||
* 0:x and x:0 are allowed and can be interpreted as 1:1.
|
||||
*/
|
||||
if (dec->have_par) {
|
||||
/* we had a par on the sink caps, override the encoded par */
|
||||
GST_DEBUG_OBJECT (dec, "overriding with input PAR %dx%d", dec->par_num,
|
||||
dec->par_den);
|
||||
info.par_n = dec->par_num;
|
||||
info.par_d = dec->par_den;
|
||||
} else {
|
||||
/* take encoded par */
|
||||
info.par_n = dec->info.aspect_numerator;
|
||||
info.par_d = dec->info.aspect_denominator;
|
||||
}
|
||||
if (info.par_n == 0 || info.par_d == 0) {
|
||||
info.par_n = info.par_d = 1;
|
||||
}
|
||||
|
||||
/* these values are for all versions of the colorspace specified in the
|
||||
* theora info */
|
||||
dec->vinfo.chroma_site = GST_VIDEO_CHROMA_SITE_JPEG;
|
||||
dec->vinfo.colorimetry.range = GST_VIDEO_COLOR_RANGE_16_235;
|
||||
dec->vinfo.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
|
||||
dec->vinfo.colorimetry.transfer = GST_VIDEO_TRANSFER_BT709;
|
||||
info.chroma_site = GST_VIDEO_CHROMA_SITE_JPEG;
|
||||
info.colorimetry.range = GST_VIDEO_COLOR_RANGE_16_235;
|
||||
info.colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_BT601;
|
||||
info.colorimetry.transfer = GST_VIDEO_TRANSFER_BT709;
|
||||
switch (dec->info.colorspace) {
|
||||
case TH_CS_ITU_REC_470M:
|
||||
dec->vinfo.colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT470M;
|
||||
info.colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT470M;
|
||||
break;
|
||||
case TH_CS_ITU_REC_470BG:
|
||||
dec->vinfo.colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT470BG;
|
||||
info.colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_BT470BG;
|
||||
break;
|
||||
default:
|
||||
dec->vinfo.colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_UNKNOWN;
|
||||
info.colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
/* remove reconfigure flag now */
|
||||
gst_pad_check_reconfigure (dec->srcpad);
|
||||
|
||||
theora_negotiate_pool (dec);
|
||||
/* for the output caps we always take the cropped dimensions */
|
||||
cinfo = info;
|
||||
gst_video_info_set_format (&cinfo, GST_VIDEO_INFO_FORMAT (&info),
|
||||
dec->info.pic_width, dec->info.pic_height);
|
||||
caps = gst_video_info_to_caps (&cinfo);
|
||||
gst_pad_set_caps (dec->srcpad, caps);
|
||||
|
||||
/* find a pool for the negotiated caps now */
|
||||
query = gst_query_new_allocation (caps, TRUE);
|
||||
|
||||
if (gst_pad_peer_query (dec->srcpad, query)) {
|
||||
GST_DEBUG_OBJECT (dec, "got downstream ALLOCATION hints");
|
||||
/* we got configuration from our peer, parse them */
|
||||
gst_query_parse_allocation_params (query, &size, &min, &max, &prefix,
|
||||
&alignment, &pool);
|
||||
|
||||
/* check if downstream supports cropping */
|
||||
dec->has_cropping =
|
||||
gst_query_has_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE);
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (dec, "didn't get downstream ALLOCATION hints");
|
||||
size = 0;
|
||||
min = max = 0;
|
||||
prefix = 0;
|
||||
alignment = 0;
|
||||
pool = NULL;
|
||||
dec->has_cropping = FALSE;
|
||||
}
|
||||
GST_DEBUG_OBJECT (dec, "downstream cropping %d", dec->has_cropping);
|
||||
|
||||
if (pool == NULL) {
|
||||
/* we did not get a pool, make one ourselves then */
|
||||
pool = gst_video_buffer_pool_new ();
|
||||
}
|
||||
|
||||
if (dec->pool)
|
||||
gst_object_unref (dec->pool);
|
||||
dec->pool = pool;
|
||||
|
||||
if (dec->has_cropping) {
|
||||
dec->vinfo = info;
|
||||
/* we can crop, configure the pool with buffers of caps and size of the
|
||||
* decoded picture size and then crop them with metadata */
|
||||
gst_caps_unref (caps);
|
||||
caps = gst_video_info_to_caps (&info);
|
||||
} else {
|
||||
/* no cropping, use cropped videoinfo */
|
||||
dec->vinfo = cinfo;
|
||||
}
|
||||
size = MAX (size, GST_VIDEO_INFO_SIZE (&dec->vinfo));
|
||||
|
||||
config = gst_buffer_pool_get_config (pool);
|
||||
gst_buffer_pool_config_set (config, caps, size, min, max, prefix, alignment);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
/* just set the option, if the pool can support it we will transparently use
|
||||
* it through the video info API. We could also see if the pool support this
|
||||
* option and only activate it then. */
|
||||
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
|
||||
|
||||
gst_buffer_pool_set_config (pool, config);
|
||||
/* and activate */
|
||||
gst_buffer_pool_set_active (pool, TRUE);
|
||||
|
||||
gst_query_unref (query);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
|
||||
/* ERRORS */
|
||||
invalid_format:
|
||||
{
|
||||
GST_ERROR_OBJECT (dec, "Invalid pixel format %d", dec->info.pixel_fmt);
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
|
||||
{
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
GList *walk;
|
||||
|
||||
if ((ret = theora_negotiate (dec)) != GST_FLOW_OK)
|
||||
goto negotiate_failed;
|
||||
|
||||
/* done */
|
||||
dec->decoder = th_decode_alloc (&dec->info, dec->setup);
|
||||
|
@ -983,10 +986,10 @@ theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
|
|||
return ret;
|
||||
|
||||
/* ERRORS */
|
||||
invalid_format:
|
||||
negotiate_failed:
|
||||
{
|
||||
GST_ERROR_OBJECT (dec, "Invalid pixel format %d", dec->info.pixel_fmt);
|
||||
return GST_FLOW_ERROR;
|
||||
GST_ERROR_OBJECT (dec, "failed to negotiate");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1114,15 +1117,19 @@ theora_handle_image (GstTheoraDec * dec, th_ycbcr_buffer buf, GstBuffer ** out)
|
|||
GstVideoCropMeta *crop;
|
||||
gint offset_x, offset_y;
|
||||
|
||||
if (gst_pad_check_reconfigure (dec->srcpad))
|
||||
theora_negotiate_pool (dec);
|
||||
if G_UNLIKELY
|
||||
(gst_pad_check_reconfigure (dec->srcpad))
|
||||
if G_UNLIKELY
|
||||
((result = theora_negotiate (dec)) != GST_FLOW_OK)
|
||||
goto negotiate_failed;
|
||||
|
||||
result = gst_buffer_pool_acquire_buffer (dec->pool, out, NULL);
|
||||
if (G_UNLIKELY (result != GST_FLOW_OK))
|
||||
goto no_buffer;
|
||||
|
||||
if (!gst_video_frame_map (&frame, &dec->outinfo, *out, GST_MAP_WRITE))
|
||||
goto invalid_frame;
|
||||
if G_UNLIKELY
|
||||
(!gst_video_frame_map (&frame, &dec->vinfo, *out, GST_MAP_WRITE))
|
||||
goto invalid_frame;
|
||||
|
||||
if (!dec->has_cropping) {
|
||||
/* we need to crop the hard way */
|
||||
|
@ -1180,6 +1187,12 @@ theora_handle_image (GstTheoraDec * dec, th_ycbcr_buffer buf, GstBuffer ** out)
|
|||
return GST_FLOW_OK;
|
||||
|
||||
/* ERRORS */
|
||||
negotiate_failed:
|
||||
{
|
||||
GST_DEBUG_OBJECT (dec, "could not negotiate, reason: %s",
|
||||
gst_flow_get_name (result));
|
||||
return result;
|
||||
}
|
||||
no_buffer:
|
||||
{
|
||||
GST_DEBUG_OBJECT (dec, "could not get buffer, reason: %s",
|
||||
|
|
|
@ -70,7 +70,6 @@ struct _GstTheoraDec
|
|||
guint64 frame_nr;
|
||||
gboolean need_keyframe;
|
||||
GstVideoInfo vinfo;
|
||||
GstVideoInfo outinfo;
|
||||
|
||||
gint output_bpp;
|
||||
GstBufferPool *pool;
|
||||
|
|
Loading…
Reference in a new issue