theoradec: Don't use custom allocation logic and always crop locally

All video frames have to be copied from libtheora's memory to the output
frame anyway, so we can as well do the cropping here directly instead of
copying the full frames and having downstream do the cropping.

This reduces the complexity of the code considerably, and among other
things gets rid of a bug related to buffer pool configuration.

Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/2612

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6203>
This commit is contained in:
Sebastian Dröge 2024-02-23 13:08:21 +02:00 committed by GStreamer Marge Bot
parent 95436d1eb4
commit ee06666507
2 changed files with 13 additions and 125 deletions

View file

@ -108,8 +108,6 @@ static GstFlowReturn theora_dec_parse (GstVideoDecoder * decoder,
GstVideoCodecFrame * frame, GstAdapter * adapter, gboolean at_eos);
static GstFlowReturn theora_dec_handle_frame (GstVideoDecoder * decoder,
GstVideoCodecFrame * frame);
static gboolean theora_dec_decide_allocation (GstVideoDecoder * decoder,
GstQuery * query);
static GstFlowReturn theora_dec_decode_buffer (GstTheoraDec * dec,
GstBuffer * buf, GstVideoCodecFrame * frame);
@ -190,8 +188,6 @@ gst_theora_dec_class_init (GstTheoraDecClass * klass)
video_decoder_class->parse = GST_DEBUG_FUNCPTR (theora_dec_parse);
video_decoder_class->handle_frame =
GST_DEBUG_FUNCPTR (theora_dec_handle_frame);
video_decoder_class->decide_allocation =
GST_DEBUG_FUNCPTR (theora_dec_decide_allocation);
GST_DEBUG_CATEGORY_INIT (theoradec_debug, "theoradec", 0, "Theora decoder");
GST_DEBUG_CATEGORY_GET (CAT_PERFORMANCE, "GST_PERFORMANCE");
@ -223,7 +219,6 @@ theora_dec_start (GstVideoDecoder * decoder)
GST_DEBUG_OBJECT (dec, "start");
GST_DEBUG_OBJECT (dec, "Setting have_header to FALSE");
dec->have_header = FALSE;
dec->can_crop = FALSE;
return TRUE;
}
@ -254,7 +249,6 @@ theora_dec_stop (GstVideoDecoder * decoder)
gst_video_codec_state_unref (dec->output_state);
dec->output_state = NULL;
}
dec->can_crop = FALSE;
return TRUE;
}
@ -647,7 +641,7 @@ null_buffer:
}
}
/* Allocate buffer and copy image data into Y444 format */
/* Allocate output frame and copy image data */
static GstFlowReturn
theora_handle_image (GstTheoraDec * dec, th_ycbcr_buffer buf,
GstVideoCodecFrame * frame)
@ -669,7 +663,6 @@ theora_handle_image (GstTheoraDec * dec, th_ycbcr_buffer buf,
return result;
}
if (!dec->can_crop) {
/* we need to crop the hard way */
offset_x = dec->info.pic_x;
offset_y = dec->info.pic_y;
@ -682,47 +675,6 @@ theora_handle_image (GstTheoraDec * dec, th_ycbcr_buffer buf,
offset_x--;
if (offset_y & 1 && dec->info.pixel_fmt == TH_PF_420)
offset_y--;
} else {
/* copy the whole frame */
offset_x = 0;
offset_y = 0;
pic_width = dec->info.frame_width;
pic_height = dec->info.frame_height;
if (dec->info.pic_width != dec->info.frame_width ||
dec->info.pic_height != dec->info.frame_height ||
dec->info.pic_x != 0 || dec->info.pic_y != 0) {
GstVideoMeta *vmeta;
GstVideoCropMeta *cmeta;
vmeta = gst_buffer_get_video_meta (frame->output_buffer);
/* If the buffer pool didn't add the meta already
* we add it ourselves here */
if (!vmeta)
vmeta = gst_buffer_add_video_meta (frame->output_buffer,
GST_VIDEO_FRAME_FLAG_NONE,
dec->output_state->info.finfo->format,
dec->info.frame_width, dec->info.frame_height);
/* Just to be sure that the buffer pool doesn't do something
* completely weird and we would crash later
*/
g_assert (vmeta->format == dec->output_state->info.finfo->format);
g_assert (vmeta->width == dec->info.frame_width);
g_assert (vmeta->height == dec->info.frame_height);
g_assert (gst_buffer_get_size (frame->output_buffer) >=
dec->uncropped_info.size);
cmeta = gst_buffer_add_video_crop_meta (frame->output_buffer);
/* we can do things slightly more efficient when we know that
* downstream understands clipping */
cmeta->x = dec->info.pic_x;
cmeta->y = dec->info.pic_y;
cmeta->width = dec->info.pic_width;
cmeta->height = dec->info.pic_height;
}
}
/* if only libtheora would allow us to give it a destination frame */
GST_CAT_TRACE_OBJECT (CAT_PERFORMANCE, dec,
@ -918,69 +870,6 @@ theora_dec_handle_frame (GstVideoDecoder * bdec, GstVideoCodecFrame * frame)
return res;
}
static gboolean
theora_dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query)
{
GstTheoraDec *dec = GST_THEORA_DEC (decoder);
GstBufferPool *pool;
guint size, min, max;
GstStructure *config;
if ((dec->info.pic_width != dec->info.frame_width ||
dec->info.pic_height != dec->info.frame_height) &&
(gst_query_get_n_allocation_pools (query) > 0)) {
gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
if (pool) {
dec->can_crop = FALSE;
config = gst_buffer_pool_get_config (pool);
if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL)) {
gst_buffer_pool_config_add_option (config,
GST_BUFFER_POOL_OPTION_VIDEO_META);
dec->can_crop =
gst_query_find_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE,
NULL);
}
if (dec->can_crop) {
GstVideoInfo *info = &dec->uncropped_info;
GstCaps *caps;
GST_LOG_OBJECT (decoder,
"Using GstVideoCropMeta, uncropped wxh = %dx%d", info->width,
info->height);
gst_video_info_set_format (info, info->finfo->format,
dec->info.frame_width, dec->info.frame_height);
/* Calculate uncropped size */
size = MAX (size, info->size);
caps = gst_video_info_to_caps (info);
gst_buffer_pool_config_set_params (config, caps, size, min, max);
gst_caps_unref (caps);
}
if (gst_buffer_pool_set_config (pool, config)) {
gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
} else {
GstVideoInfo *info = &dec->uncropped_info;
GST_DEBUG_OBJECT (dec, "ignoring unusable pool");
gst_query_remove_nth_allocation_pool (query, 0);
gst_video_info_set_format (info, info->finfo->format,
dec->info.pic_width, dec->info.pic_height);
dec->can_crop = FALSE;
}
gst_object_unref (pool);
}
}
return GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation (decoder,
query);
}
static void
theora_dec_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)

View file

@ -76,7 +76,6 @@ struct _GstTheoraDec
gint telemetry_qi;
gint telemetry_bits;
gboolean can_crop;
GstVideoInfo uncropped_info;
};