From 310488694dd0d8777bb507d458585ada57b2b752 Mon Sep 17 00:00:00 2001 From: Guillaume Desmottes Date: Thu, 16 May 2019 10:38:49 +0200 Subject: [PATCH 1/5] omxh264enc: no need to check if codeconfig has startcode We currently only support stream-format=byte-stream so there is no point re-checking for it when handling CODECCONFIG buffer. --- omx/gstomxh264enc.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/omx/gstomxh264enc.c b/omx/gstomxh264enc.c index b67e0d7..505bdfe 100644 --- a/omx/gstomxh264enc.c +++ b/omx/gstomxh264enc.c @@ -835,32 +835,28 @@ gst_omx_h264_enc_handle_output_frame (GstOMXVideoEnc * enc, GstOMXPort * port, GstOMXH264Enc *self = GST_OMX_H264_ENC (enc); if (buf->omx_buf->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { - /* The codec data is SPS/PPS with a startcode => bytestream stream format + /* The codec data is SPS/PPS but our output is stream-format=byte-stream. * For bytestream stream format the SPS/PPS is only in-stream and not * in the caps! */ - if (buf->omx_buf->nFilledLen >= 4 && - GST_READ_UINT32_BE (buf->omx_buf->pBuffer + - buf->omx_buf->nOffset) == 0x00000001) { - GstBuffer *hdrs; - GstMapInfo map = GST_MAP_INFO_INIT; + GstBuffer *hdrs; + GstMapInfo map = GST_MAP_INFO_INIT; - GST_DEBUG_OBJECT (self, "got codecconfig in byte-stream format"); + GST_DEBUG_OBJECT (self, "got codecconfig in byte-stream format"); - hdrs = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen); + hdrs = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen); - gst_buffer_map (hdrs, &map, GST_MAP_WRITE); - memcpy (map.data, - buf->omx_buf->pBuffer + buf->omx_buf->nOffset, - buf->omx_buf->nFilledLen); - gst_buffer_unmap (hdrs, &map); - self->headers = g_list_append (self->headers, hdrs); + gst_buffer_map (hdrs, &map, GST_MAP_WRITE); + memcpy (map.data, + buf->omx_buf->pBuffer + buf->omx_buf->nOffset, + buf->omx_buf->nFilledLen); + gst_buffer_unmap (hdrs, &map); + self->headers = g_list_append (self->headers, hdrs); - if (frame) - gst_video_codec_frame_unref (frame); + if (frame) + gst_video_codec_frame_unref (frame); - return GST_FLOW_OK; - } + return GST_FLOW_OK; } else if (self->headers) { gst_video_encoder_set_headers (GST_VIDEO_ENCODER (self), self->headers); self->headers = NULL; -- GitLab From 0a5988383d00bc6ffc77c1fc1f184c9211de0df0 Mon Sep 17 00:00:00 2001 From: Guillaume Desmottes Date: Thu, 16 May 2019 10:38:49 +0200 Subject: [PATCH 2/5] omxh264enc: send codec data downstream We are operating in stream-format=byte-stream so the codec data buffer is meant to be part of the buffer flow. The base class will push it when a key frame is requested (as we stored it with gst_video_encoder_set_headers()) but we still have to push it right away as part of the normal buffer flow. Also set the HEADER flag on this buffer. --- omx/gstomxh264enc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/omx/gstomxh264enc.c b/omx/gstomxh264enc.c index 505bdfe..5de2249 100644 --- a/omx/gstomxh264enc.c +++ b/omx/gstomxh264enc.c @@ -841,22 +841,26 @@ gst_omx_h264_enc_handle_output_frame (GstOMXVideoEnc * enc, GstOMXPort * port, */ GstBuffer *hdrs; GstMapInfo map = GST_MAP_INFO_INIT; + GstFlowReturn flow_ret; GST_DEBUG_OBJECT (self, "got codecconfig in byte-stream format"); hdrs = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen); + GST_BUFFER_FLAG_SET (hdrs, GST_BUFFER_FLAG_HEADER); gst_buffer_map (hdrs, &map, GST_MAP_WRITE); memcpy (map.data, buf->omx_buf->pBuffer + buf->omx_buf->nOffset, buf->omx_buf->nFilledLen); gst_buffer_unmap (hdrs, &map); - self->headers = g_list_append (self->headers, hdrs); + self->headers = g_list_append (self->headers, gst_buffer_ref (hdrs)); + + flow_ret = gst_pad_push (GST_VIDEO_ENCODER_SRC_PAD (self), hdrs); if (frame) gst_video_codec_frame_unref (frame); - return GST_FLOW_OK; + return flow_ret; } else if (self->headers) { gst_video_encoder_set_headers (GST_VIDEO_ENCODER (self), self->headers); self->headers = NULL; -- GitLab From 3a1015ef64a5fcd294f9682ffa9671c2c33c7eee Mon Sep 17 00:00:00 2001 From: Guillaume Desmottes Date: Thu, 16 May 2019 10:50:18 +0200 Subject: [PATCH 3/5] omxh265enc: handle CODECCONFIG buffers Exact same code as omxh264enc. --- omx/gstomxh265enc.c | 74 +++++++++++++++++++++++++++++++++++++++++++++ omx/gstomxh265enc.h | 2 ++ 2 files changed, 76 insertions(+) diff --git a/omx/gstomxh265enc.c b/omx/gstomxh265enc.c index ea14ca7..db1b3e6 100644 --- a/omx/gstomxh265enc.c +++ b/omx/gstomxh265enc.c @@ -40,6 +40,8 @@ static void gst_omx_h265_enc_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_omx_h265_enc_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); +static GstFlowReturn gst_omx_h265_enc_handle_output_frame (GstOMXVideoEnc * + self, GstOMXPort * port, GstOMXBuffer * buf, GstVideoCodecFrame * frame); enum { @@ -104,15 +106,43 @@ gst_omx_h265_enc_loop_filter_mode_get_type (void) } #endif +static gboolean +gst_omx_h265_enc_flush (GstVideoEncoder * enc) +{ + GstOMXH265Enc *self = GST_OMX_H265_ENC (enc); + + g_list_free_full (self->headers, (GDestroyNotify) gst_buffer_unref); + self->headers = NULL; + + return GST_VIDEO_ENCODER_CLASS (parent_class)->flush (enc); +} + +static gboolean +gst_omx_h265_enc_stop (GstVideoEncoder * enc) +{ + GstOMXH265Enc *self = GST_OMX_H265_ENC (enc); + + g_list_free_full (self->headers, (GDestroyNotify) gst_buffer_unref); + self->headers = NULL; + + return GST_VIDEO_ENCODER_CLASS (parent_class)->stop (enc); +} + static void gst_omx_h265_enc_class_init (GstOMXH265EncClass * klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstVideoEncoderClass *basevideoenc_class = GST_VIDEO_ENCODER_CLASS (klass); GstOMXVideoEncClass *videoenc_class = GST_OMX_VIDEO_ENC_CLASS (klass); videoenc_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_h265_enc_set_format); videoenc_class->get_caps = GST_DEBUG_FUNCPTR (gst_omx_h265_enc_get_caps); + videoenc_class->handle_output_frame = + GST_DEBUG_FUNCPTR (gst_omx_h265_enc_handle_output_frame); + + basevideoenc_class->flush = gst_omx_h265_enc_flush; + basevideoenc_class->stop = gst_omx_h265_enc_stop; gobject_class->set_property = gst_omx_h265_enc_set_property; gobject_class->get_property = gst_omx_h265_enc_get_property; @@ -648,3 +678,47 @@ gst_omx_h265_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port, return caps; } + +static GstFlowReturn +gst_omx_h265_enc_handle_output_frame (GstOMXVideoEnc * enc, GstOMXPort * port, + GstOMXBuffer * buf, GstVideoCodecFrame * frame) +{ + GstOMXH265Enc *self = GST_OMX_H265_ENC (enc); + + if (buf->omx_buf->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { + /* The codec data is SPS/PPS but our output is stream-format=byte-stream. + * For bytestream stream format the SPS/PPS is only in-stream and not + * in the caps! + */ + GstBuffer *hdrs; + GstMapInfo map = GST_MAP_INFO_INIT; + GstFlowReturn flow_ret; + + GST_DEBUG_OBJECT (self, "got codecconfig in byte-stream format"); + + hdrs = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen); + GST_BUFFER_FLAG_SET (hdrs, GST_BUFFER_FLAG_HEADER); + + gst_buffer_map (hdrs, &map, GST_MAP_WRITE); + memcpy (map.data, + buf->omx_buf->pBuffer + buf->omx_buf->nOffset, + buf->omx_buf->nFilledLen); + gst_buffer_unmap (hdrs, &map); + self->headers = g_list_append (self->headers, gst_buffer_ref (hdrs)); + + flow_ret = gst_pad_push (GST_VIDEO_ENCODER_SRC_PAD (self), hdrs); + + if (frame) + gst_video_codec_frame_unref (frame); + + return flow_ret; + } else if (self->headers) { + gst_video_encoder_set_headers (GST_VIDEO_ENCODER (self), self->headers); + self->headers = NULL; + } + + return + GST_OMX_VIDEO_ENC_CLASS + (gst_omx_h265_enc_parent_class)->handle_output_frame (enc, port, buf, + frame); +} diff --git a/omx/gstomxh265enc.h b/omx/gstomxh265enc.h index c53be18..b67fa1f 100644 --- a/omx/gstomxh265enc.h +++ b/omx/gstomxh265enc.h @@ -55,6 +55,8 @@ struct _GstOMXH265Enc gboolean constrained_intra_prediction; guint32 loop_filter_mode; #endif + + GList *headers; }; struct _GstOMXH265EncClass -- GitLab From 2b680a0bfef12840d266f5107237e6544fa604ec Mon Sep 17 00:00:00 2001 From: Guillaume Desmottes Date: Thu, 16 May 2019 10:50:18 +0200 Subject: [PATCH 4/5] omxvideodec: allow to start decoder on HEADER buffer If the headers are sent in their own buffer it won't have the SYNC_FRAME flag but we still do want to start decoding rather than dropping it. --- omx/gstomxvideodec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c index aa6845a..af83f9f 100644 --- a/omx/gstomxvideodec.c +++ b/omx/gstomxvideodec.c @@ -2751,6 +2751,7 @@ gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder, gboolean done = FALSE; gboolean first_ouput_buffer = TRUE; guint memory_idx = 0; /* only used in dynamic buffer mode */ + gboolean header; self = GST_OMX_VIDEO_DEC (decoder); @@ -2761,8 +2762,9 @@ gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder, return self->downstream_flow_ret; } + header = GST_BUFFER_FLAG_IS_SET (frame->input_buffer, GST_BUFFER_FLAG_HEADER); if (!self->started) { - if (!GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame)) { + if (!GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame) && !header) { gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame); return GST_FLOW_OK; } -- GitLab From 372f21e6dbaf6c17a4a17212fc7bcd3f2c00a54e Mon Sep 17 00:00:00 2001 From: Guillaume Desmottes Date: Thu, 16 May 2019 10:50:18 +0200 Subject: [PATCH 5/5] omxvideodec: fix OMX flags on header buffer The header (SPS/PPS) buffer should have the CODECONFIG flag and not the ENDOFFRAME one as it's not actually a frame. --- omx/gstomxvideodec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c index af83f9f..ea4c177 100644 --- a/omx/gstomxvideodec.c +++ b/omx/gstomxvideodec.c @@ -2895,7 +2895,6 @@ gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder, } buf->omx_buf->nFlags |= OMX_BUFFERFLAG_CODECCONFIG; - buf->omx_buf->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; if (GST_CLOCK_TIME_IS_VALID (timestamp)) GST_OMX_SET_TICKS (buf->omx_buf->nTimeStamp, @@ -2975,6 +2974,9 @@ gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder, if (first_ouput_buffer && GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame)) buf->omx_buf->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; + if (header) + buf->omx_buf->nFlags |= OMX_BUFFERFLAG_CODECCONFIG; + /* TODO: Set flags * - OMX_BUFFERFLAG_DECODEONLY for buffers that are outside * the segment -- GitLab