mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 12:49:40 +00:00
v4l2h264dec: Copy frames when GstVideoMeta is not supported
In some case, when downstream does not support GstVideoMeta, we need to normalize the stride and offset of the buffer so that downstream can render properly with a GstVideoMeta. This code is not called when GstVideoMeta is supported downstream.
This commit is contained in:
parent
3c2d25eebf
commit
21652a8e52
1 changed files with 74 additions and 0 deletions
|
@ -66,6 +66,7 @@ struct _GstV4l2CodecH264Dec
|
|||
gint min_pool_size;
|
||||
gboolean has_videometa;
|
||||
gboolean need_negotiation;
|
||||
gboolean copy_frames;
|
||||
|
||||
struct v4l2_ctrl_h264_sps sps;
|
||||
struct v4l2_ctrl_h264_pps pps;
|
||||
|
@ -462,6 +463,27 @@ gst_v4l2_codec_h264_dec_new_sequence (GstH264Decoder * decoder,
|
|||
}
|
||||
}
|
||||
|
||||
/* Check if we can zero-copy buffers */
|
||||
if (!self->has_videometa) {
|
||||
GstVideoInfo ref_vinfo;
|
||||
gint i;
|
||||
|
||||
gst_video_info_set_format (&ref_vinfo, GST_VIDEO_INFO_FORMAT (&self->vinfo),
|
||||
self->display_width, self->display_height);
|
||||
|
||||
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&self->vinfo); i++) {
|
||||
if (self->vinfo.stride[i] != ref_vinfo.stride[i] ||
|
||||
self->vinfo.offset[i] != ref_vinfo.offset[i]) {
|
||||
GST_WARNING_OBJECT (self,
|
||||
"GstVideoMeta support required, copying frames.");
|
||||
self->copy_frames = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self->copy_frames = FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -505,6 +527,54 @@ gst_v4l2_codec_h264_dec_start_picture (GstH264Decoder * decoder,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_v4l2_codec_h264_dec_copy_output_buffer (GstV4l2CodecH264Dec * self,
|
||||
GstVideoCodecFrame * codec_frame)
|
||||
{
|
||||
GstVideoFrame src_frame;
|
||||
GstVideoFrame dest_frame;
|
||||
GstVideoInfo dest_vinfo;
|
||||
GstBuffer *buffer;
|
||||
|
||||
gst_video_info_set_format (&dest_vinfo, GST_VIDEO_INFO_FORMAT (&self->vinfo),
|
||||
self->display_width, self->display_height);
|
||||
|
||||
buffer = gst_video_decoder_allocate_output_buffer (GST_VIDEO_DECODER (self));
|
||||
if (!buffer)
|
||||
goto fail;
|
||||
|
||||
if (!gst_video_frame_map (&src_frame, &self->vinfo,
|
||||
codec_frame->output_buffer, GST_MAP_READ))
|
||||
goto fail;
|
||||
|
||||
if (!gst_video_frame_map (&dest_frame, &dest_vinfo, buffer, GST_MAP_WRITE)) {
|
||||
gst_video_frame_unmap (&dest_frame);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* gst_video_frame_copy can crop this, but does not know, so let make it
|
||||
* think it's all right */
|
||||
GST_VIDEO_INFO_WIDTH (&src_frame.info) = self->display_width;
|
||||
GST_VIDEO_INFO_HEIGHT (&src_frame.info) = self->display_height;
|
||||
|
||||
if (!gst_video_frame_copy (&dest_frame, &src_frame)) {
|
||||
gst_video_frame_unmap (&src_frame);
|
||||
gst_video_frame_unmap (&dest_frame);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
gst_video_frame_unmap (&src_frame);
|
||||
gst_video_frame_unmap (&dest_frame);
|
||||
gst_buffer_replace (&codec_frame->output_buffer, buffer);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
GST_ERROR_OBJECT (self, "Failed copy output buffer.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_v4l2_codec_h264_dec_output_picture (GstH264Decoder * decoder,
|
||||
GstH264Picture * picture)
|
||||
|
@ -561,6 +631,10 @@ finish_frame:
|
|||
/* Hold on reference buffers for the rest of the picture lifetime */
|
||||
gst_h264_picture_set_user_data (picture,
|
||||
gst_buffer_ref (frame->output_buffer), (GDestroyNotify) gst_buffer_unref);
|
||||
|
||||
if (self->copy_frames)
|
||||
gst_v4l2_codec_h264_dec_copy_output_buffer (self, frame);
|
||||
|
||||
return gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue