summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlessandro Decina <alessandro.d@gmail.com>2014-12-10 22:36:53 +1100
committerSebastian Dröge <sebastian@centricular.com>2014-12-16 15:08:57 +0100
commit723afa2e92b7d520bb068695381296c4316c34e2 (patch)
treeda93564aa35ad70220d081b4846c4736fb2dc4f6
parent18acaa58c7a22b9963f20e7d3d1107037ec89f97 (diff)
downloadgstreamer-plugins-bad-723afa2e92b7d520bb068695381296c4316c34e2.tar.gz
vtenc: negotiate profile and level with downstream
-rw-r--r--sys/applemedia/vtenc.c100
-rw-r--r--sys/applemedia/vtenc.h1
2 files changed, 98 insertions, 3 deletions
diff --git a/sys/applemedia/vtenc.c b/sys/applemedia/vtenc.c
index 1a9912d5a..8230883fd 100644
--- a/sys/applemedia/vtenc.c
+++ b/sys/applemedia/vtenc.c
@@ -251,6 +251,7 @@ gst_vtenc_init (GstVTEnc * self)
self->dump_attributes = FALSE;
self->latency_frames = -1;
self->session = NULL;
+ self->profile_level = NULL;
}
static guint
@@ -482,6 +483,9 @@ gst_vtenc_stop (GstVideoEncoder * enc)
gst_vtenc_destroy_session (self, &self->session);
GST_OBJECT_UNLOCK (self);
+ if (self->profile_level)
+ CFRelease (self->profile_level);
+
if (self->options != NULL) {
CFRelease (self->options);
self->options = NULL;
@@ -502,6 +506,94 @@ gst_vtenc_stop (GstVideoEncoder * enc)
return TRUE;
}
+static CFStringRef
+gst_vtenc_profile_level_key (GstVTEnc * self, const gchar * profile,
+ const gchar * level_arg)
+{
+ char level[64];
+ gchar *key = NULL;
+ CFStringRef ret = NULL;
+
+ if (profile == NULL)
+ profile = "main";
+ if (level_arg == NULL)
+ level_arg = "AutoLevel";
+ strncpy (level, level_arg, sizeof (level));
+
+ if (!strcmp (profile, "constrained-baseline") ||
+ !strcmp (profile, "baseline")) {
+ profile = "Baseline";
+ } else if (g_str_has_prefix (profile, "high")) {
+ profile = "High";
+ } else if (!strcmp (profile, "main")) {
+ profile = "Main";
+ } else {
+ g_assert_not_reached ();
+ }
+
+ if (strlen (level) == 1) {
+ level[1] = '_';
+ level[2] = '0';
+ } else if (strlen (level) == 3) {
+ level[1] = '_';
+ }
+
+ key = g_strdup_printf ("H264_%s_%s", profile, level);
+ ret = CFStringCreateWithBytes (NULL, (const guint8 *) key, strlen (key),
+ kCFStringEncodingASCII, 0);
+
+ GST_INFO_OBJECT (self, "negotiated profile and level %s", key);
+
+ g_free (key);
+
+ return ret;
+}
+
+static gboolean
+gst_vtenc_negotiate_profile_and_level (GstVideoEncoder * enc)
+{
+ GstVTEnc *self = GST_VTENC_CAST (enc);
+ GstCaps *allowed_caps = NULL;
+ gboolean ret = TRUE;
+ const gchar *profile = NULL;
+ const gchar *level = NULL;
+
+ allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (enc));
+ if (allowed_caps) {
+ GstStructure *s;
+
+ if (gst_caps_is_empty (allowed_caps)) {
+ GST_ERROR_OBJECT (self, "no allowed downstream caps");
+ goto fail;
+ }
+
+ allowed_caps = gst_caps_make_writable (allowed_caps);
+ allowed_caps = gst_caps_fixate (allowed_caps);
+ s = gst_caps_get_structure (allowed_caps, 0);
+
+ profile = gst_structure_get_string (s, "profile");
+ level = gst_structure_get_string (s, "level");
+ }
+
+ if (self->profile_level)
+ CFRelease (self->profile_level);
+ self->profile_level = gst_vtenc_profile_level_key (self, profile, level);
+ if (self->profile_level == NULL) {
+ GST_ERROR_OBJECT (enc, "invalid profile and level");
+ goto fail;
+ }
+
+out:
+ if (allowed_caps)
+ gst_caps_unref (allowed_caps);
+
+ return ret;
+
+fail:
+ ret = FALSE;
+ goto out;
+}
+
static gboolean
gst_vtenc_set_format (GstVideoEncoder * enc, GstVideoCodecState * state)
{
@@ -522,6 +614,8 @@ gst_vtenc_set_format (GstVideoEncoder * enc, GstVideoCodecState * state)
gst_vtenc_destroy_session (self, &self->session);
GST_OBJECT_UNLOCK (self);
+ gst_vtenc_negotiate_profile_and_level (enc);
+
session = gst_vtenc_create_session (self);
GST_OBJECT_LOCK (self);
self->session = session;
@@ -589,8 +683,9 @@ gst_vtenc_negotiate_downstream (GstVTEnc * self, CMSampleBufferRef sbuf)
gst_structure_set (s, "codec_data", GST_TYPE_BUFFER, codec_data_buf, NULL);
sps[0] = codec_data[1];
- sps[1] = codec_data[2];
+ sps[1] = codec_data[2] & ~0xDF;
sps[2] = codec_data[3];
+
gst_codec_utils_h264_caps_set_level_and_profile (caps, sps, 3);
gst_buffer_unref (codec_data_buf);
@@ -696,8 +791,7 @@ gst_vtenc_create_session (GstVTEnc * self)
(gdouble) self->negotiated_fps_n / (gdouble) self->negotiated_fps_d);
status = VTSessionSetProperty (session,
- kVTCompressionPropertyKey_ProfileLevel,
- kVTProfileLevel_H264_Baseline_AutoLevel);
+ kVTCompressionPropertyKey_ProfileLevel, self->profile_level);
GST_DEBUG_OBJECT (self, "kVTCompressionPropertyKey_ProfileLevel => %d",
(int) status);
diff --git a/sys/applemedia/vtenc.h b/sys/applemedia/vtenc.h
index f2873cdf6..38eab1e9a 100644
--- a/sys/applemedia/vtenc.h
+++ b/sys/applemedia/vtenc.h
@@ -57,6 +57,7 @@ struct _GstVTEnc
const GstVTEncoderDetails * details;
+ CFStringRef profile_level;
guint bitrate;
gboolean allow_frame_reordering;
gboolean realtime;