vp9enc: support GST_VIDEO_FORMAT_Y444
authorJakub Adam <jakub.adam@collabora.com>
Mon, 23 Mar 2020 20:44:30 +0000 (21:44 +0100)
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Tue, 8 Sep 2020 21:09:09 +0000 (21:09 +0000)
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/705>

ext/vpx/gstvp9enc.c
ext/vpx/gstvpxenc.c

index 1705b06..0733e23 100644 (file)
@@ -69,13 +69,13 @@ GST_DEBUG_CATEGORY_STATIC (gst_vp9enc_debug);
 #define GST_CAT_DEFAULT gst_vp9enc_debug
 
 
-/* FIXME: Y42B and Y444 do not work yet it seems */
+/* FIXME: Y42B do not work yet it seems */
 static GstStaticPadTemplate gst_vp9_enc_sink_template =
 GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
     /*GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ I420, YV12, Y42B, Y444 }")) */
-    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ I420, YV12 }"))
+    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ I420, YV12, Y444 }"))
     );
 
 static GstStaticPadTemplate gst_vp9_enc_src_template =
index 3849711..2d5b784 100644 (file)
@@ -1495,12 +1495,36 @@ gst_vpx_enc_stop (GstVideoEncoder * video_encoder)
   return TRUE;
 }
 
+#define INVALID_PROFILE -1
+
 static gint
-gst_vpx_enc_get_downstream_profile (GstVPXEnc * encoder)
+gst_vpx_gvalue_to_profile (const GValue * v)
+{
+  gchar *endptr = NULL;
+  gint profile = g_ascii_strtoull (g_value_get_string (v), &endptr, 10);
+
+  if (*endptr != '\0') {
+    profile = INVALID_PROFILE;
+  }
+
+  return profile;
+}
+
+static gint
+gst_vpx_enc_get_downstream_profile (GstVPXEnc * encoder, GstVideoInfo * info)
 {
   GstCaps *allowed;
   GstStructure *s;
-  gint profile = DEFAULT_PROFILE;
+  gint min_profile;
+  gint profile = INVALID_PROFILE;
+
+  switch (GST_VIDEO_INFO_FORMAT (info)) {
+    case GST_VIDEO_FORMAT_Y444:
+      min_profile = 1;
+      break;
+    default:
+      min_profile = 0;
+  }
 
   allowed = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder));
   if (allowed) {
@@ -1508,22 +1532,29 @@ gst_vpx_enc_get_downstream_profile (GstVPXEnc * encoder)
     s = gst_caps_get_structure (allowed, 0);
     if (gst_structure_has_field (s, "profile")) {
       const GValue *v = gst_structure_get_value (s, "profile");
-      const gchar *profile_str = NULL;
 
-      if (GST_VALUE_HOLDS_LIST (v) && gst_value_list_get_size (v) > 0) {
-        profile_str = g_value_get_string (gst_value_list_get_value (v, 0));
+      if (GST_VALUE_HOLDS_LIST (v)) {
+        gint i;
+
+        for (i = 0; i != gst_value_list_get_size (v); ++i) {
+          gint p = gst_vpx_gvalue_to_profile (gst_value_list_get_value (v, i));
+          if (p >= min_profile) {
+            profile = p;
+            break;
+          }
+        }
       } else if (G_VALUE_HOLDS_STRING (v)) {
-        profile_str = g_value_get_string (v);
+        profile = gst_vpx_gvalue_to_profile (v);
       }
 
-      if (profile_str) {
-        gchar *endptr = NULL;
+      if (profile < min_profile || profile > 3) {
+        profile = INVALID_PROFILE;
+      }
 
-        profile = g_ascii_strtoull (profile_str, &endptr, 10);
-        if (*endptr != '\0' || profile < 0 || profile > 3) {
-          GST_ERROR_OBJECT (encoder, "Invalid profile '%s'", profile_str);
-          profile = DEFAULT_PROFILE;
-        }
+      if (profile > 1 && info->finfo->bits == 8) {
+        GST_DEBUG_OBJECT (encoder,
+            "Codec bit-depth 8 not supported in profile > 1");
+        profile = INVALID_PROFILE;
       }
     }
     gst_caps_unref (allowed);
@@ -1562,7 +1593,14 @@ gst_vpx_enc_set_format (GstVideoEncoder * video_encoder,
     g_mutex_lock (&encoder->encoder_lock);
   }
 
-  encoder->cfg.g_profile = gst_vpx_enc_get_downstream_profile (encoder);
+  encoder->cfg.g_profile = gst_vpx_enc_get_downstream_profile (encoder, info);
+  if (encoder->cfg.g_profile == INVALID_PROFILE) {
+    GST_ELEMENT_ERROR (encoder, RESOURCE, OPEN_READ,
+        ("Invalid vpx profile"), (NULL));
+    g_mutex_unlock (&encoder->encoder_lock);
+    return FALSE;
+  }
+
   encoder->cfg.g_w = GST_VIDEO_INFO_WIDTH (info);
   encoder->cfg.g_h = GST_VIDEO_INFO_HEIGHT (info);