From 21602395480eddf12025553bbe3685d999bada94 Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Wed, 6 May 2020 12:27:56 -0400 Subject: [PATCH] v4l2slh264dec: Request large enough bitstream buffer The Cedrus driver would otherwise choose 1KB buffer, which is too small. This follows what some drivers do, which is simply to use the size a packed raw image would have. Specifications do not really guaranty any minimum compression ratio. Part-of: --- sys/v4l2codecs/gstv4l2codech264dec.c | 33 +++++++++++++++++++++++++++- sys/v4l2codecs/gstv4l2codecvp8dec.c | 2 +- sys/v4l2codecs/gstv4l2decoder.c | 9 +++++++- sys/v4l2codecs/gstv4l2decoder.h | 3 ++- 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/sys/v4l2codecs/gstv4l2codech264dec.c b/sys/v4l2codecs/gstv4l2codech264dec.c index 37eb1722d6..29f96d4f83 100644 --- a/sys/v4l2codecs/gstv4l2codech264dec.c +++ b/sys/v4l2codecs/gstv4l2codech264dec.c @@ -190,6 +190,37 @@ gst_v4l2_codec_h264_dec_stop (GstVideoDecoder * decoder) return GST_VIDEO_DECODER_CLASS (parent_class)->stop (decoder); } +static gint +get_pixel_bitdepth (GstV4l2CodecH264Dec * self) +{ + gint depth; + + switch (self->chroma_format_idc) { + case 0: + /* 4:0:0 */ + depth = self->bitdepth; + break; + case 1: + /* 4:2:0 */ + depth = self->bitdepth + self->bitdepth / 2; + break; + case 2: + /* 4:2:2 */ + depth = 2 * self->bitdepth; + break; + case 3: + /* 4:4:4 */ + depth = 3 * self->bitdepth; + default: + GST_WARNING_OBJECT (self, "Unsupported chroma format %i", + self->chroma_format_idc); + depth = 0; + break; + } + + return depth; +} + static gboolean gst_v4l2_codec_h264_dec_negotiate (GstVideoDecoder * decoder) { @@ -219,7 +250,7 @@ gst_v4l2_codec_h264_dec_negotiate (GstVideoDecoder * decoder) gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC); 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, get_pixel_bitdepth (self))) { GST_ELEMENT_ERROR (self, CORE, NEGOTIATION, ("Failed to configure H264 decoder"), ("gst_v4l2_decoder_set_sink_fmt() failed: %s", g_strerror (errno))); diff --git a/sys/v4l2codecs/gstv4l2codecvp8dec.c b/sys/v4l2codecs/gstv4l2codecvp8dec.c index 20487450b6..b6f3587249 100644 --- a/sys/v4l2codecs/gstv4l2codecvp8dec.c +++ b/sys/v4l2codecs/gstv4l2codecvp8dec.c @@ -159,7 +159,7 @@ gst_v4l2_codec_vp8_dec_negotiate (GstVideoDecoder * decoder) gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC); if (!gst_v4l2_decoder_set_sink_fmt (self->decoder, V4L2_PIX_FMT_VP8_FRAME, - self->width, self->height)) { + self->width, self->height, 12 /* 8 bits 4:2:0 */ )) { GST_ELEMENT_ERROR (self, CORE, NEGOTIATION, ("Failed to configure VP8 decoder"), ("gst_v4l2_decoder_set_sink_fmt() failed: %s", g_strerror (errno))); diff --git a/sys/v4l2codecs/gstv4l2decoder.c b/sys/v4l2codecs/gstv4l2decoder.c index 9b66018a31..5da801f867 100644 --- a/sys/v4l2codecs/gstv4l2decoder.c +++ b/sys/v4l2codecs/gstv4l2decoder.c @@ -270,7 +270,7 @@ gst_v4l2_decoder_enum_sink_fmt (GstV4l2Decoder * self, gint i, gboolean gst_v4l2_decoder_set_sink_fmt (GstV4l2Decoder * self, guint32 pix_fmt, - gint width, gint height) + gint width, gint height, gint pixel_bitdepth) { struct v4l2_format format = (struct v4l2_format) { .type = self->sink_buf_type, @@ -282,6 +282,13 @@ gst_v4l2_decoder_set_sink_fmt (GstV4l2Decoder * self, guint32 pix_fmt, }, }; gint ret; + /* Using raw image size for now, it is guarantied to be large enough */ + gsize sizeimage = (width * height * pixel_bitdepth) / 8; + + if (self->mplane) + format.fmt.pix_mp.plane_fmt[0].sizeimage = sizeimage; + else + format.fmt.pix.sizeimage = sizeimage; ret = ioctl (self->video_fd, VIDIOC_S_FMT, &format); if (ret < 0) { diff --git a/sys/v4l2codecs/gstv4l2decoder.h b/sys/v4l2codecs/gstv4l2decoder.h index d2ada04937..0d32e31c5e 100644 --- a/sys/v4l2codecs/gstv4l2decoder.h +++ b/sys/v4l2codecs/gstv4l2decoder.h @@ -51,7 +51,8 @@ gboolean gst_v4l2_decoder_enum_sink_fmt (GstV4l2Decoder * self, gint i, guint32 * out_fmt); gboolean gst_v4l2_decoder_set_sink_fmt (GstV4l2Decoder * self, guint32 fmt, - gint width, gint height); + gint width, gint height, + gint pixel_bitdepth); GstCaps * gst_v4l2_decoder_enum_src_formats (GstV4l2Decoder * self);