mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
v4l2codech264dec: Implement finish frame
This enables the request to be processed by the HW (STREAMON) and to be pushed downstream for further processing.
This commit is contained in:
parent
3cc6643050
commit
0d740a184e
1 changed files with 82 additions and 5 deletions
|
@ -110,6 +110,9 @@ gst_v4l2_codec_h264_dec_stop (GstVideoDecoder * decoder)
|
||||||
{
|
{
|
||||||
GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
|
GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
|
||||||
|
|
||||||
|
gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SINK);
|
||||||
|
gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC);
|
||||||
|
|
||||||
if (self->sink_allocator) {
|
if (self->sink_allocator) {
|
||||||
gst_v4l2_codec_allocator_detach (self->sink_allocator);
|
gst_v4l2_codec_allocator_detach (self->sink_allocator);
|
||||||
g_clear_object (&self->sink_allocator);
|
g_clear_object (&self->sink_allocator);
|
||||||
|
@ -142,6 +145,9 @@ gst_v4l2_codec_h264_dec_negotiate (GstVideoDecoder * decoder)
|
||||||
if (self->src_allocator)
|
if (self->src_allocator)
|
||||||
gst_v4l2_codec_allocator_detach (self->src_allocator);
|
gst_v4l2_codec_allocator_detach (self->src_allocator);
|
||||||
|
|
||||||
|
gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SINK);
|
||||||
|
gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC);
|
||||||
|
|
||||||
if (!gst_v4l2_decoder_set_sink_fmt (self->decoder, V4L2_PIX_FMT_H264_SLICE,
|
if (!gst_v4l2_decoder_set_sink_fmt (self->decoder, V4L2_PIX_FMT_H264_SLICE,
|
||||||
self->coded_width, self->coded_height)) {
|
self->coded_width, self->coded_height)) {
|
||||||
GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
|
GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
|
||||||
|
@ -174,7 +180,25 @@ gst_v4l2_codec_h264_dec_negotiate (GstVideoDecoder * decoder)
|
||||||
|
|
||||||
self->output_state->caps = gst_video_info_to_caps (&self->output_state->info);
|
self->output_state->caps = gst_video_info_to_caps (&self->output_state->info);
|
||||||
|
|
||||||
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
|
if (GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder)) {
|
||||||
|
if (!gst_v4l2_decoder_streamon (self->decoder, GST_PAD_SINK)) {
|
||||||
|
GST_ELEMENT_ERROR (self, RESOURCE, FAILED,
|
||||||
|
("Could not enable the decoder driver."),
|
||||||
|
("VIDIOC_STREAMON(SINK) failed: %s", g_strerror (errno)));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gst_v4l2_decoder_streamon (self->decoder, GST_PAD_SRC)) {
|
||||||
|
GST_ELEMENT_ERROR (self, RESOURCE, FAILED,
|
||||||
|
("Could not enable the decoder driver."),
|
||||||
|
("VIDIOC_STREAMON(SRC) failed: %s", g_strerror (errno)));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -440,6 +464,10 @@ gst_v4l2_codec_h264_dec_start_picture (GstH264Decoder * decoder,
|
||||||
{
|
{
|
||||||
GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
|
GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
|
||||||
|
|
||||||
|
/* FIXME base class should not call us if negotiation failed */
|
||||||
|
if (!self->sink_allocator)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* Ensure we have a bitstream to write into */
|
/* Ensure we have a bitstream to write into */
|
||||||
if (!self->bitstream) {
|
if (!self->bitstream) {
|
||||||
self->bitstream = gst_v4l2_codec_allocator_alloc (self->sink_allocator);
|
self->bitstream = gst_v4l2_codec_allocator_alloc (self->sink_allocator);
|
||||||
|
@ -474,10 +502,57 @@ static GstFlowReturn
|
||||||
gst_v4l2_codec_h264_dec_output_picture (GstH264Decoder * decoder,
|
gst_v4l2_codec_h264_dec_output_picture (GstH264Decoder * decoder,
|
||||||
GstH264Picture * picture)
|
GstH264Picture * picture)
|
||||||
{
|
{
|
||||||
/* We dequeue frames, until the system_frame_number matches, this ensure
|
GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
|
||||||
* that the frame we want to output is actually decoded now */
|
GstV4l2Request *request = gst_h264_picture_get_user_data (picture);
|
||||||
/* TODO implement */
|
gint ret;
|
||||||
return GST_FLOW_OK;
|
guint32 frame_num;
|
||||||
|
GstVideoCodecFrame *frame, *other_frame;
|
||||||
|
GstH264Picture *other_pic;
|
||||||
|
GstV4l2Request *other_request;
|
||||||
|
|
||||||
|
if (gst_v4l2_request_is_done (request))
|
||||||
|
goto finish_frame;
|
||||||
|
|
||||||
|
ret = gst_v4l2_request_poll (request, GST_SECOND);
|
||||||
|
if (ret == 0) {
|
||||||
|
GST_ELEMENT_ERROR (self, STREAM, DECODE,
|
||||||
|
("Decoding frame took too long"), (NULL));
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
} else if (ret < 0) {
|
||||||
|
GST_ELEMENT_ERROR (self, STREAM, DECODE,
|
||||||
|
("Decoding request failed: %s", g_strerror (errno)), (NULL));
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (TRUE) {
|
||||||
|
if (!gst_v4l2_decoder_dequeue_src (self->decoder, &frame_num)) {
|
||||||
|
GST_ELEMENT_ERROR (self, STREAM, DECODE,
|
||||||
|
("Decoder did not produce a frame"), (NULL));
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame_num == picture->system_frame_number)
|
||||||
|
break;
|
||||||
|
|
||||||
|
other_frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (self),
|
||||||
|
frame_num);
|
||||||
|
g_return_val_if_fail (other_frame, GST_FLOW_ERROR);
|
||||||
|
|
||||||
|
other_pic = gst_video_codec_frame_get_user_data (other_frame);
|
||||||
|
other_request = gst_h264_picture_get_user_data (other_pic);
|
||||||
|
gst_v4l2_request_set_done (other_request);
|
||||||
|
gst_video_codec_frame_unref (other_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
finish_frame:
|
||||||
|
gst_v4l2_request_set_done (request);
|
||||||
|
frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (self),
|
||||||
|
picture->system_frame_number);
|
||||||
|
|
||||||
|
g_return_val_if_fail (frame, GST_FLOW_ERROR);
|
||||||
|
|
||||||
|
gst_h264_picture_set_user_data (picture, NULL, NULL);
|
||||||
|
return gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -570,7 +645,9 @@ gst_v4l2_codec_h264_dec_end_picture (GstH264Decoder * decoder,
|
||||||
frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (self),
|
frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (self),
|
||||||
picture->system_frame_number);
|
picture->system_frame_number);
|
||||||
g_return_val_if_fail (frame, FALSE);
|
g_return_val_if_fail (frame, FALSE);
|
||||||
|
g_warn_if_fail (frame->output_buffer == NULL);
|
||||||
frame->output_buffer = buffer;
|
frame->output_buffer = buffer;
|
||||||
|
gst_video_codec_frame_unref (frame);
|
||||||
|
|
||||||
if (!gst_v4l2_decoder_queue_src_buffer (self->decoder, buffer,
|
if (!gst_v4l2_decoder_queue_src_buffer (self->decoder, buffer,
|
||||||
picture->system_frame_number)) {
|
picture->system_frame_number)) {
|
||||||
|
|
Loading…
Reference in a new issue