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);
|
GstLcevcDec *lcevc = GST_LCEVC_DEC (decoder);
|
||||||
|
|
||||||
|
/* Clear input state */
|
||||||
|
g_clear_pointer (&lcevc->input_state, gst_video_codec_state_unref);
|
||||||
|
|
||||||
/* Destry LCEVC decoder */
|
/* Destry LCEVC decoder */
|
||||||
LCEVC_DestroyDecoder (lcevc->decoder_handle);
|
LCEVC_DestroyDecoder (lcevc->decoder_handle);
|
||||||
|
|
||||||
@ -294,21 +297,23 @@ gst_lcevc_dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
ensure_output_resolution (GstLcevcDec * lcevc, guint32 width, guint32 height,
|
ensure_output_resolution (GstLcevcDec * lcevc, guint32 width, guint32 height)
|
||||||
GstVideoCodecState * state)
|
|
||||||
{
|
{
|
||||||
/* Set output state with input resolution to do passthrough */
|
|
||||||
if (width != lcevc->out_width || height != lcevc->out_height) {
|
if (width != lcevc->out_width || height != lcevc->out_height) {
|
||||||
GstVideoCodecState *s;
|
GstVideoCodecState *s;
|
||||||
|
|
||||||
s = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (lcevc),
|
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)
|
if (!s)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
lcevc->out_width = width;
|
lcevc->out_width = width;
|
||||||
lcevc->out_height = height;
|
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);
|
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);
|
GstLcevcDec *lcevc = GST_LCEVC_DEC (decoder);
|
||||||
LCEVC_ColorFormat format;
|
LCEVC_ColorFormat format;
|
||||||
gint par_n, par_d;
|
|
||||||
guint32 w, h;
|
|
||||||
|
|
||||||
/* Make sure format is supported */
|
/* Make sure format is supported */
|
||||||
format =
|
format =
|
||||||
@ -330,30 +333,13 @@ gst_lcevc_dec_set_format (GstVideoDecoder * decoder, GstVideoCodecState * state)
|
|||||||
if (format == LCEVC_ColorFormat_Unknown)
|
if (format == LCEVC_ColorFormat_Unknown)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Keep input info */
|
/* Keep input state reference */
|
||||||
lcevc->in_info = state->info;
|
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
|
GST_INFO_OBJECT (lcevc, "Input resolution changed to %dx%d",
|
||||||
* pixel aspect ratio */
|
GST_VIDEO_INFO_WIDTH (&lcevc->input_state->info),
|
||||||
par_n = GST_VIDEO_INFO_PAR_N (&state->info);
|
GST_VIDEO_INFO_HEIGHT (&lcevc->input_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);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -406,6 +392,14 @@ receive_enhanced_picture (GstLcevcDec * lcevc)
|
|||||||
return FALSE;
|
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,
|
GST_INFO_OBJECT (lcevc,
|
||||||
"Received enhanced picture: ts=%" G_GINT64_FORMAT " e=%d w=%d h=%d"
|
"Received enhanced picture: ts=%" G_GINT64_FORMAT " e=%d w=%d h=%d"
|
||||||
" t=%d b=%d l=%d r=%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,
|
received_frame = find_pending_frame_from_picture_handle (lcevc,
|
||||||
picture_handle);
|
picture_handle);
|
||||||
if (received_frame) {
|
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 */
|
/* Add crop meta if downstream can crop */
|
||||||
if (lcevc->can_crop) {
|
if (lcevc->can_crop) {
|
||||||
cmeta = gst_buffer_add_video_crop_meta (received_frame->output_buffer);
|
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;
|
gboolean ret = FALSE;
|
||||||
GstLcevcMeta *lcevc_meta;
|
GstLcevcMeta *lcevc_meta;
|
||||||
GstMapInfo enhancement_info;
|
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);
|
lcevc_meta = gst_buffer_get_lcevc_meta (input_buffer);
|
||||||
if (!lcevc_meta) {
|
if (!lcevc_meta) {
|
||||||
@ -524,11 +515,7 @@ send_enhancement_data (GstLcevcDec * lcevc, GstBuffer * input_buffer)
|
|||||||
"Input buffer %" GST_TIME_FORMAT
|
"Input buffer %" GST_TIME_FORMAT
|
||||||
" enhancement data not found, doing passthrough",
|
" enhancement data not found, doing passthrough",
|
||||||
GST_TIME_ARGS (GST_BUFFER_PTS (input_buffer)));
|
GST_TIME_ARGS (GST_BUFFER_PTS (input_buffer)));
|
||||||
|
return ensure_output_resolution (lcevc, out_w, out_h);
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gst_buffer_map (lcevc_meta->enhancement_data, &enhancement_info,
|
if (!gst_buffer_map (lcevc_meta->enhancement_data, &enhancement_info,
|
||||||
@ -548,6 +535,18 @@ send_enhancement_data (GstLcevcDec * lcevc, GstBuffer * input_buffer)
|
|||||||
goto done;
|
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,
|
GST_INFO_OBJECT (lcevc,
|
||||||
"Sent input buffer %" GST_TIME_FORMAT " enhancement data with size %zu",
|
"Sent input buffer %" GST_TIME_FORMAT " enhancement data with size %zu",
|
||||||
GST_TIME_ARGS (GST_BUFFER_PTS (input_buffer)), enhancement_info.size);
|
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;
|
LCEVC_PictureHandle picture_handle;
|
||||||
GstVideoFrame frame = { 0, };
|
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_MAP_READ)) {
|
||||||
GST_ELEMENT_ERROR (lcevc, STREAM, DECODE, (NULL),
|
GST_ELEMENT_ERROR (lcevc, STREAM, DECODE, (NULL),
|
||||||
("Could not map input buffer %" GST_TIME_FORMAT,
|
("Could not map input buffer %" GST_TIME_FORMAT,
|
||||||
@ -589,8 +588,10 @@ send_base_picture (GstLcevcDec * lcevc, GstBuffer * input_buffer)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_INFO_OBJECT (lcevc, "Sent input buffer %" GST_TIME_FORMAT " base picture",
|
GST_INFO_OBJECT (lcevc,
|
||||||
GST_TIME_ARGS (GST_BUFFER_PTS (input_buffer)));
|
"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;
|
ret = TRUE;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@ -51,7 +51,7 @@ struct _GstLcevcDec {
|
|||||||
gint max_latency;
|
gint max_latency;
|
||||||
|
|
||||||
LCEVC_DecoderHandle decoder_handle;
|
LCEVC_DecoderHandle decoder_handle;
|
||||||
GstVideoInfo in_info;
|
GstVideoCodecState *input_state;
|
||||||
gboolean can_crop;
|
gboolean can_crop;
|
||||||
|
|
||||||
guint32 out_width;
|
guint32 out_width;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user