lcevcdec: Peek the decoder for output resolution
The output resolution is not always twice as big as the input resultion divided by the pixel aspect ratio. This is the case for LCEVC '0D' mode, where the output resolution is the same as the input resolution, and the only enhancement is the picture being clearer. This patch uses LCEVC_PeekDecoder() after sending the LCEVC enhancement data to know what the output resolution will be before allocating the output picture. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/9463>
This commit is contained in:
parent
3208d6c62a
commit
d66213bfa3
@ -272,6 +272,9 @@ gst_lcevc_dec_stop (GstVideoDecoder * decoder)
|
||||
{
|
||||
GstLcevcDec *lcevc = GST_LCEVC_DEC (decoder);
|
||||
|
||||
/* Clear input state */
|
||||
g_clear_pointer (&lcevc->input_state, gst_video_codec_state_unref);
|
||||
|
||||
/* Destry LCEVC decoder */
|
||||
LCEVC_DestroyDecoder (lcevc->decoder_handle);
|
||||
|
||||
@ -294,21 +297,23 @@ gst_lcevc_dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ensure_output_resolution (GstLcevcDec * lcevc, guint32 width, guint32 height,
|
||||
GstVideoCodecState * state)
|
||||
ensure_output_resolution (GstLcevcDec * lcevc, guint32 width, guint32 height)
|
||||
{
|
||||
/* Set output state with input resolution to do passthrough */
|
||||
if (width != lcevc->out_width || height != lcevc->out_height) {
|
||||
GstVideoCodecState *s;
|
||||
|
||||
s = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (lcevc),
|
||||
GST_VIDEO_INFO_FORMAT (&lcevc->in_info), width, height, state);
|
||||
GST_VIDEO_INFO_FORMAT (&lcevc->input_state->info), width, height,
|
||||
lcevc->input_state);
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
lcevc->out_width = width;
|
||||
lcevc->out_height = height;
|
||||
|
||||
GST_INFO_OBJECT (lcevc, "Set output resolution to %dx%d", lcevc->out_width,
|
||||
lcevc->out_height);
|
||||
|
||||
gst_video_codec_state_unref (s);
|
||||
}
|
||||
|
||||
@ -320,8 +325,6 @@ gst_lcevc_dec_set_format (GstVideoDecoder * decoder, GstVideoCodecState * state)
|
||||
{
|
||||
GstLcevcDec *lcevc = GST_LCEVC_DEC (decoder);
|
||||
LCEVC_ColorFormat format;
|
||||
gint par_n, par_d;
|
||||
guint32 w, h;
|
||||
|
||||
/* Make sure format is supported */
|
||||
format =
|
||||
@ -330,30 +333,13 @@ gst_lcevc_dec_set_format (GstVideoDecoder * decoder, GstVideoCodecState * state)
|
||||
if (format == LCEVC_ColorFormat_Unknown)
|
||||
return FALSE;
|
||||
|
||||
/* Keep input info */
|
||||
lcevc->in_info = state->info;
|
||||
/* Keep input state reference */
|
||||
g_clear_pointer (&lcevc->input_state, gst_video_codec_state_unref);
|
||||
lcevc->input_state = gst_video_codec_state_ref (state);
|
||||
|
||||
/* Output resultion is always twice as big as input resultion divided by
|
||||
* pixel aspect ratio */
|
||||
par_n = GST_VIDEO_INFO_PAR_N (&state->info);
|
||||
if (par_n == 0)
|
||||
par_n = 1;
|
||||
par_d = GST_VIDEO_INFO_PAR_D (&state->info);
|
||||
if (par_d == 0)
|
||||
par_d = 1;
|
||||
w = (GST_VIDEO_INFO_WIDTH (&state->info) * 2) / par_d;
|
||||
h = (GST_VIDEO_INFO_HEIGHT (&state->info) * 2) / par_n;
|
||||
|
||||
/* Set pixel aspect ratio back to 1/1 */
|
||||
GST_VIDEO_INFO_PAR_N (&state->info) = 1;
|
||||
GST_VIDEO_INFO_PAR_D (&state->info) = 1;
|
||||
|
||||
/* Set output resolution */
|
||||
if (!ensure_output_resolution (lcevc, w, h, state))
|
||||
return FALSE;
|
||||
|
||||
/* We always work with full RAW video frames */
|
||||
gst_video_decoder_set_subframe_mode (decoder, FALSE);
|
||||
GST_INFO_OBJECT (lcevc, "Input resolution changed to %dx%d",
|
||||
GST_VIDEO_INFO_WIDTH (&lcevc->input_state->info),
|
||||
GST_VIDEO_INFO_HEIGHT (&lcevc->input_state->info));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -406,6 +392,14 @@ receive_enhanced_picture (GstLcevcDec * lcevc)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Enhanced resolution should always match the output width and height */
|
||||
if (pic_desc.width != lcevc->out_width ||
|
||||
pic_desc.height != lcevc->out_height) {
|
||||
GST_ELEMENT_ERROR (lcevc, STREAM, DECODE, (NULL),
|
||||
("Decoded LCEVC picture has wrong resolution"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GST_INFO_OBJECT (lcevc,
|
||||
"Received enhanced picture: ts=%" G_GINT64_FORMAT " e=%d w=%d h=%d"
|
||||
" t=%d b=%d l=%d r=%d",
|
||||
@ -416,13 +410,6 @@ receive_enhanced_picture (GstLcevcDec * lcevc)
|
||||
received_frame = find_pending_frame_from_picture_handle (lcevc,
|
||||
picture_handle);
|
||||
if (received_frame) {
|
||||
/* Change output allocation if enhanced picutre resolution changed */
|
||||
if (!ensure_output_resolution (lcevc, pic_desc.width, pic_desc.height,
|
||||
NULL)) {
|
||||
gst_video_codec_frame_unref (received_frame);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Add crop meta if downstream can crop */
|
||||
if (lcevc->can_crop) {
|
||||
cmeta = gst_buffer_add_video_crop_meta (received_frame->output_buffer);
|
||||
@ -517,6 +504,10 @@ send_enhancement_data (GstLcevcDec * lcevc, GstBuffer * input_buffer)
|
||||
gboolean ret = FALSE;
|
||||
GstLcevcMeta *lcevc_meta;
|
||||
GstMapInfo enhancement_info;
|
||||
uint32_t out_w, out_h;
|
||||
|
||||
out_w = GST_VIDEO_INFO_WIDTH (&lcevc->input_state->info);
|
||||
out_h = GST_VIDEO_INFO_HEIGHT (&lcevc->input_state->info);
|
||||
|
||||
lcevc_meta = gst_buffer_get_lcevc_meta (input_buffer);
|
||||
if (!lcevc_meta) {
|
||||
@ -524,11 +515,7 @@ send_enhancement_data (GstLcevcDec * lcevc, GstBuffer * input_buffer)
|
||||
"Input buffer %" GST_TIME_FORMAT
|
||||
" enhancement data not found, doing passthrough",
|
||||
GST_TIME_ARGS (GST_BUFFER_PTS (input_buffer)));
|
||||
|
||||
/* Set output state with input resolution to do passthrough */
|
||||
return ensure_output_resolution (lcevc,
|
||||
GST_VIDEO_INFO_WIDTH (&lcevc->in_info),
|
||||
GST_VIDEO_INFO_HEIGHT (&lcevc->in_info), NULL);
|
||||
return ensure_output_resolution (lcevc, out_w, out_h);
|
||||
}
|
||||
|
||||
if (!gst_buffer_map (lcevc_meta->enhancement_data, &enhancement_info,
|
||||
@ -548,6 +535,18 @@ send_enhancement_data (GstLcevcDec * lcevc, GstBuffer * input_buffer)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Now peek and update the output resolution */
|
||||
if (LCEVC_PeekDecoder (lcevc->decoder_handle, input_buffer->pts,
|
||||
&out_w, &out_h) != LCEVC_Success) {
|
||||
GST_INFO_OBJECT (lcevc, "Could not peek decoder for output resolution");
|
||||
goto done;
|
||||
}
|
||||
if (!ensure_output_resolution (lcevc, out_w, out_h)) {
|
||||
GST_INFO_OBJECT (lcevc, "Could not set output resolution to %dx%d", out_w,
|
||||
out_h);
|
||||
goto done;
|
||||
}
|
||||
|
||||
GST_INFO_OBJECT (lcevc,
|
||||
"Sent input buffer %" GST_TIME_FORMAT " enhancement data with size %zu",
|
||||
GST_TIME_ARGS (GST_BUFFER_PTS (input_buffer)), enhancement_info.size);
|
||||
@ -565,7 +564,7 @@ send_base_picture (GstLcevcDec * lcevc, GstBuffer * input_buffer)
|
||||
LCEVC_PictureHandle picture_handle;
|
||||
GstVideoFrame frame = { 0, };
|
||||
|
||||
if (!gst_video_frame_map (&frame, &lcevc->in_info, input_buffer,
|
||||
if (!gst_video_frame_map (&frame, &lcevc->input_state->info, input_buffer,
|
||||
GST_MAP_READ)) {
|
||||
GST_ELEMENT_ERROR (lcevc, STREAM, DECODE, (NULL),
|
||||
("Could not map input buffer %" GST_TIME_FORMAT,
|
||||
@ -589,8 +588,10 @@ send_base_picture (GstLcevcDec * lcevc, GstBuffer * input_buffer)
|
||||
goto done;
|
||||
}
|
||||
|
||||
GST_INFO_OBJECT (lcevc, "Sent input buffer %" GST_TIME_FORMAT " base picture",
|
||||
GST_TIME_ARGS (GST_BUFFER_PTS (input_buffer)));
|
||||
GST_INFO_OBJECT (lcevc,
|
||||
"Sent input buffer %" GST_TIME_FORMAT " base picture %dx%d",
|
||||
GST_TIME_ARGS (GST_BUFFER_PTS (input_buffer)),
|
||||
GST_VIDEO_FRAME_WIDTH (&frame), GST_VIDEO_FRAME_HEIGHT (&frame));
|
||||
ret = TRUE;
|
||||
|
||||
done:
|
||||
|
@ -51,7 +51,7 @@ struct _GstLcevcDec {
|
||||
gint max_latency;
|
||||
|
||||
LCEVC_DecoderHandle decoder_handle;
|
||||
GstVideoInfo in_info;
|
||||
GstVideoCodecState *input_state;
|
||||
gboolean can_crop;
|
||||
|
||||
guint32 out_width;
|
||||
|
Loading…
x
Reference in New Issue
Block a user