151 lines
5.4 KiB
Diff
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
|
|
|