meta-digi/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/0061-v4l2codecs-h264enc-Add...

151 lines
5.4 KiB
Diff

From 9984bd8f4646ce48b4d9b3645ffc67ffcdc75161 Mon Sep 17 00:00:00 2001
From: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Date: Wed, 15 Nov 2023 15:31:05 -0500
Subject: [PATCH 61/68] v4l2codecs: h264enc: Add profile negotiation
We currently only support main, constrained-baseline and baseline. Some
work on the SPS is needed to generate a valid header for high.
Upstream-Status: Pending
---
sys/v4l2codecs/gstv4l2codech264enc.c | 80 ++++++++++++++++++++++++----
1 file changed, 69 insertions(+), 11 deletions(-)
diff --git a/sys/v4l2codecs/gstv4l2codech264enc.c b/sys/v4l2codecs/gstv4l2codech264enc.c
index e7ae63a..b1617c9 100644
--- a/sys/v4l2codecs/gstv4l2codech264enc.c
+++ b/sys/v4l2codecs/gstv4l2codech264enc.c
@@ -47,10 +47,17 @@ GST_STATIC_PAD_TEMPLATE (GST_VIDEO_ENCODER_SINK_NAME,
GST_PAD_SINK, GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (GST_V4L2_DEFAULT_VIDEO_FORMATS)));
-static GstStaticPadTemplate src_template =
-GST_STATIC_PAD_TEMPLATE (GST_VIDEO_ENCODER_SRC_NAME,
- GST_PAD_SRC, GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/x-h264,alignment=au,stream-format=byte-stream"));
+static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("video/x-h264, "
+ "framerate = (fraction) [0/1, MAX], "
+ "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ], "
+ "stream-format = (string) byte-stream, "
+ "alignment = (string) au, "
+ "profile = (string) { main, constrained-baseline, baseline}")
+ );
+
#define H264ENC_DEFAULT_KEYFRAME_INTERVAL 30
@@ -90,6 +97,7 @@ struct _GstV4l2CodecH264Enc
guint64 targeted_bitrate;
gboolean cabac;
guint cabac_init_idc;
+ gchar *profile_name;
GstV4l2CodecAllocator *sink_allocator;
GstV4l2CodecAllocator *src_allocator;
@@ -234,6 +242,8 @@ gst_v4l2_codec_h264_enc_stop (GstVideoEncoder * encoder)
gst_video_codec_state_unref (self->output_state);
self->output_state = NULL;
+ g_clear_pointer (&self->profile_name, g_free);
+
return GST_VIDEO_ENCODER_CLASS (parent_class)->stop (encoder);
}
@@ -445,9 +455,19 @@ gst_v4l2_codec_h264_enc_init_sps_pps (GstV4l2CodecH264Enc * self,
memset (&self->sps, 0, sizeof (self->pps));
/* SPS */
- self->sps.profile_idc = 66;
- self->sps.constraint_set0_flag = 1;
- self->sps.constraint_set1_flag = 0;
+ if (g_str_equal (self->profile_name, "baseline")) {
+ self->sps.profile_idc = GST_H264_PROFILE_BASELINE;
+ self->sps.constraint_set0_flag = 1;
+ self->sps.constraint_set1_flag = 0;
+ } else if (g_str_equal (self->profile_name, "constrained-baseline")) {
+ self->sps.profile_idc = GST_H264_PROFILE_BASELINE;
+ self->sps.constraint_set0_flag = 1;
+ self->sps.constraint_set1_flag = 1;
+ } else if (g_str_equal (self->profile_name, "main")) {
+ self->sps.profile_idc = GST_H264_PROFILE_MAIN;
+ } else if (g_str_equal (self->profile_name, "high")) {
+ self->sps.profile_idc = GST_H264_PROFILE_HIGH;
+ }
self->sps.chroma_format_idc = 1; /* YUV 4:2:0 */
@@ -573,6 +593,43 @@ gst_v4l2_codec_h264_enc_init_sps_pps (GstV4l2CodecH264Enc * self,
self->pps.entropy_coding_mode_flag = self->cabac;
}
+static gchar *
+gst_v4l2_codec_h264_enc_decide_profile (GstV4l2CodecH264Enc * self)
+{
+ GstCaps *allowed_caps = NULL;
+ const gchar *profile_name;
+ GstStructure *structure;
+ gchar *ret;
+
+ g_object_get (self, "cabac", &self->cabac, "cabac-init-idc",
+ &self->cabac_init_idc, NULL);
+
+ /* First, check whether the downstream requires a specified profile. */
+ allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (self));
+ if (!allowed_caps)
+ allowed_caps = gst_pad_query_caps (GST_VIDEO_ENCODER_SRC_PAD (self), NULL);
+
+ allowed_caps = gst_caps_make_writable (allowed_caps);
+ allowed_caps = gst_caps_fixate (allowed_caps);
+ structure = gst_caps_get_structure (allowed_caps, 0);
+ profile_name = gst_structure_get_string (structure, "profile");
+
+ if (self->cabac) {
+ if (!g_strstr_len (profile_name, -1, "main")
+ && !g_strstr_len (profile_name, -1, "high")) {
+ GST_WARNING_OBJECT (self,
+ "CABAC is not support by user selected profile '%s'"
+ ", disabling this features", profile_name);
+ self->cabac = FALSE;
+ }
+ }
+
+ ret = g_strdup (profile_name);
+ gst_caps_unref (allowed_caps);
+
+ return ret;
+}
+
static gboolean
gst_v4l2_codec_h264_enc_set_format (GstVideoEncoder * encoder,
GstVideoCodecState * state)
@@ -615,9 +672,13 @@ gst_v4l2_codec_h264_enc_set_format (GstVideoEncoder * encoder,
if (self->output_state)
gst_video_codec_state_unref (self->output_state);
+ g_free (self->profile_name);
+ self->profile_name = gst_v4l2_codec_h264_enc_decide_profile (self);
+
caps = gst_caps_new_simple ("video/x-h264",
"stream-format", G_TYPE_STRING, "byte-stream",
- "alignment", G_TYPE_STRING, "au", NULL);
+ "alignment", G_TYPE_STRING, "au",
+ "profile", G_TYPE_STRING, self->profile_name, NULL);
self->output_state =
gst_video_encoder_set_output_state (GST_VIDEO_ENCODER (self),
@@ -641,9 +702,6 @@ gst_v4l2_codec_h264_enc_set_format (GstVideoEncoder * encoder,
gst_v4l2_codec_h264_enc_get_qp_range (self->encoder, &self->qp_min,
&self->qp_max);
- g_object_get (self, "cabac", &self->cabac, "cabac-init-idc",
- &self->cabac_init_idc, NULL);
-
gst_v4l2_codec_h264_enc_init_sps_pps (self, state);
return TRUE;
--
2.25.1