diff options
author | Alessandro Decina <alessandro.d@gmail.com> | 2014-12-10 22:36:53 +1100 |
---|---|---|
committer | Sebastian Dröge <sebastian@centricular.com> | 2014-12-16 15:08:57 +0100 |
commit | 723afa2e92b7d520bb068695381296c4316c34e2 (patch) | |
tree | da93564aa35ad70220d081b4846c4736fb2dc4f6 | |
parent | 18acaa58c7a22b9963f20e7d3d1107037ec89f97 (diff) | |
download | gstreamer-plugins-bad-723afa2e92b7d520bb068695381296c4316c34e2.tar.gz |
vtenc: negotiate profile and level with downstream
-rw-r--r-- | sys/applemedia/vtenc.c | 100 | ||||
-rw-r--r-- | sys/applemedia/vtenc.h | 1 |
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; |