mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-23 22:46:24 +00:00
va: basedec: Copy the frames into other_pool if needed.
If decoder's crop_top/left value > 0 and the downstream does not support the VideoCropMeta, we need to manually copy the frames into the other_pool and output it. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2298>
This commit is contained in:
parent
55302c9705
commit
85c56c1f07
2 changed files with 87 additions and 11 deletions
|
@ -85,6 +85,8 @@ gst_va_base_dec_stop (GstVideoDecoder * decoder)
|
||||||
gst_buffer_pool_set_active (base->other_pool, FALSE);
|
gst_buffer_pool_set_active (base->other_pool, FALSE);
|
||||||
gst_clear_object (&base->other_pool);
|
gst_clear_object (&base->other_pool);
|
||||||
|
|
||||||
|
g_clear_pointer (&base->convert, gst_video_converter_free);
|
||||||
|
|
||||||
return GST_VIDEO_DECODER_CLASS (GST_VA_BASE_DEC_GET_PARENT_CLASS
|
return GST_VIDEO_DECODER_CLASS (GST_VA_BASE_DEC_GET_PARENT_CLASS
|
||||||
(decoder))->stop (decoder);
|
(decoder))->stop (decoder);
|
||||||
}
|
}
|
||||||
|
@ -817,6 +819,66 @@ bail:
|
||||||
gst_clear_caps (&preferred_caps);
|
gst_clear_caps (&preferred_caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_copy_buffer_and_apply_video_crop (GstVaBaseDec * base,
|
||||||
|
GstVideoFrame * src_frame, GstVideoFrame * dest_frame,
|
||||||
|
GstVideoCropMeta * video_crop)
|
||||||
|
{
|
||||||
|
GstVideoInfo dst_info = dest_frame->info;
|
||||||
|
|
||||||
|
dst_info.fps_n = src_frame->info.fps_n;
|
||||||
|
dst_info.fps_d = src_frame->info.fps_d;
|
||||||
|
|
||||||
|
if (base->convert) {
|
||||||
|
gboolean new_convert = FALSE;
|
||||||
|
gint x = 0, y = 0, width = 0, height = 0;
|
||||||
|
const GstStructure *config = gst_video_converter_get_config (base->convert);
|
||||||
|
|
||||||
|
if (!gst_structure_get_int (config, GST_VIDEO_CONVERTER_OPT_SRC_X, &x)
|
||||||
|
|| !gst_structure_get_int (config, GST_VIDEO_CONVERTER_OPT_SRC_Y, &y)
|
||||||
|
|| !gst_structure_get_int (config, GST_VIDEO_CONVERTER_OPT_SRC_WIDTH,
|
||||||
|
&width)
|
||||||
|
|| !gst_structure_get_int (config, GST_VIDEO_CONVERTER_OPT_SRC_HEIGHT,
|
||||||
|
&height))
|
||||||
|
new_convert = TRUE;
|
||||||
|
|
||||||
|
new_convert |= (video_crop->x != x);
|
||||||
|
new_convert |= (video_crop->y != y);
|
||||||
|
new_convert |= (video_crop->width != width);
|
||||||
|
new_convert |= (video_crop->height != height);
|
||||||
|
|
||||||
|
/* No need to check dest, it always has (0,0) -> (width, height) */
|
||||||
|
|
||||||
|
if (new_convert)
|
||||||
|
g_clear_pointer (&base->convert, gst_video_converter_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!base->convert) {
|
||||||
|
base->convert = gst_video_converter_new (&src_frame->info, &dst_info,
|
||||||
|
gst_structure_new ("options",
|
||||||
|
GST_VIDEO_CONVERTER_OPT_MATRIX_MODE,
|
||||||
|
GST_TYPE_VIDEO_MATRIX_MODE, GST_VIDEO_MATRIX_MODE_NONE,
|
||||||
|
GST_VIDEO_CONVERTER_OPT_SRC_X, G_TYPE_INT, video_crop->x,
|
||||||
|
GST_VIDEO_CONVERTER_OPT_SRC_Y, G_TYPE_INT, video_crop->y,
|
||||||
|
GST_VIDEO_CONVERTER_OPT_SRC_WIDTH, G_TYPE_INT, video_crop->width,
|
||||||
|
GST_VIDEO_CONVERTER_OPT_SRC_HEIGHT, G_TYPE_INT, video_crop->height,
|
||||||
|
GST_VIDEO_CONVERTER_OPT_DEST_X, G_TYPE_INT, 0,
|
||||||
|
GST_VIDEO_CONVERTER_OPT_DEST_Y, G_TYPE_INT, 0,
|
||||||
|
GST_VIDEO_CONVERTER_OPT_DEST_WIDTH, G_TYPE_INT, video_crop->width,
|
||||||
|
GST_VIDEO_CONVERTER_OPT_DEST_HEIGHT, G_TYPE_INT, video_crop->height,
|
||||||
|
NULL));
|
||||||
|
|
||||||
|
if (!base->convert) {
|
||||||
|
GST_WARNING_OBJECT (base, "failed to create a video convert");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_video_converter_frame (base->convert, src_frame, dest_frame);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_va_base_dec_copy_output_buffer (GstVaBaseDec * base,
|
gst_va_base_dec_copy_output_buffer (GstVaBaseDec * base,
|
||||||
GstVideoCodecFrame * codec_frame)
|
GstVideoCodecFrame * codec_frame)
|
||||||
|
@ -825,7 +887,8 @@ gst_va_base_dec_copy_output_buffer (GstVaBaseDec * base,
|
||||||
GstVideoFrame dest_frame;
|
GstVideoFrame dest_frame;
|
||||||
GstVideoInfo dest_vinfo;
|
GstVideoInfo dest_vinfo;
|
||||||
GstVideoInfo *src_vinfo;
|
GstVideoInfo *src_vinfo;
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer = NULL;
|
||||||
|
GstVideoCropMeta *video_crop;
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
|
|
||||||
g_return_val_if_fail (base && base->output_state, FALSE);
|
g_return_val_if_fail (base && base->output_state, FALSE);
|
||||||
|
@ -843,16 +906,24 @@ gst_va_base_dec_copy_output_buffer (GstVaBaseDec * base,
|
||||||
ret = gst_buffer_pool_acquire_buffer (base->other_pool, &buffer, NULL);
|
ret = gst_buffer_pool_acquire_buffer (base->other_pool, &buffer, NULL);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (!gst_video_frame_map (&src_frame, src_vinfo, codec_frame->output_buffer,
|
if (!gst_video_frame_map (&src_frame, src_vinfo, codec_frame->output_buffer,
|
||||||
GST_MAP_READ))
|
GST_MAP_READ))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (!gst_video_frame_map (&dest_frame, &dest_vinfo, buffer, GST_MAP_WRITE)) {
|
if (!gst_video_frame_map (&dest_frame, &dest_vinfo, buffer, GST_MAP_WRITE)) {
|
||||||
gst_video_frame_unmap (&src_frame);
|
gst_video_frame_unmap (&src_frame);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
video_crop = gst_buffer_get_video_crop_meta (codec_frame->output_buffer);
|
||||||
|
if (video_crop) {
|
||||||
|
if (!_copy_buffer_and_apply_video_crop (base,
|
||||||
|
&src_frame, &dest_frame, video_crop)) {
|
||||||
|
gst_video_frame_unmap (&src_frame);
|
||||||
|
gst_video_frame_unmap (&dest_frame);
|
||||||
|
GST_ERROR_OBJECT (base, "fail to apply the video crop.");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
/* gst_video_frame_copy can crop this, but does not know, so let
|
/* gst_video_frame_copy can crop this, but does not know, so let
|
||||||
* make it think it's all right */
|
* make it think it's all right */
|
||||||
GST_VIDEO_INFO_WIDTH (&src_frame.info) = base->width;
|
GST_VIDEO_INFO_WIDTH (&src_frame.info) = base->width;
|
||||||
|
@ -863,6 +934,7 @@ gst_va_base_dec_copy_output_buffer (GstVaBaseDec * base,
|
||||||
gst_video_frame_unmap (&dest_frame);
|
gst_video_frame_unmap (&dest_frame);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gst_video_frame_unmap (&src_frame);
|
gst_video_frame_unmap (&src_frame);
|
||||||
gst_video_frame_unmap (&dest_frame);
|
gst_video_frame_unmap (&dest_frame);
|
||||||
|
@ -872,6 +944,9 @@ gst_va_base_dec_copy_output_buffer (GstVaBaseDec * base,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
if (buffer)
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
|
||||||
GST_ERROR_OBJECT (base, "Failed copy output buffer.");
|
GST_ERROR_OBJECT (base, "Failed copy output buffer.");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,7 @@ struct _GstVaBaseDec
|
||||||
gboolean copy_frames;
|
gboolean copy_frames;
|
||||||
|
|
||||||
gboolean apply_video_crop;
|
gboolean apply_video_crop;
|
||||||
|
GstVideoConverter *convert;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstVaBaseDecClass
|
struct _GstVaBaseDecClass
|
||||||
|
|
Loading…
Reference in a new issue