Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/GStreamer/gst-plugins-good.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/gst
diff options
context:
space:
mode:
authorStefan BrĂ¼ns <stefan.bruens@rwth-aachen.de>2020-05-02 03:21:00 +0300
committerStefanBruens <stefan.bruens@rwth-aachen.de>2020-09-16 03:59:34 +0300
commitee3ea2a94d839092a5c518125dac5584a37c6c99 (patch)
tree5a659ef06fd5e19df62a59e0cd4f6e15b1e2c3ee /gst
parent6e68873d7f4076e3d659b83c2ea20fbfecc5e07c (diff)
qtdemux: Add support for AAX encrypted audio streams
This is modelled after the DASH Common Encryption scheme, but is somewhat simpler as more parts are fixed, i.e. just one encryption scheme. The output caps are fixed to 'application/x-aavd'. All information required for decryption are part of the 'adrm' atom, which is passed on as a property. The property is attached to the buffer. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/577>
Diffstat (limited to 'gst')
-rw-r--r--gst/isomp4/qtdemux.c96
1 files changed, 92 insertions, 4 deletions
diff --git a/gst/isomp4/qtdemux.c b/gst/isomp4/qtdemux.c
index 2929cb4a9..146f409cb 100644
--- a/gst/isomp4/qtdemux.c
+++ b/gst/isomp4/qtdemux.c
@@ -111,6 +111,7 @@ GST_DEBUG_CATEGORY (qtdemux_debug);
#define GST_CAT_DEFAULT qtdemux_debug
typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
+typedef struct _QtDemuxAavdEncryptionInfo QtDemuxAavdEncryptionInfo;
/* Macros for converting to/from timescale */
#define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
@@ -234,6 +235,11 @@ struct _QtDemuxCencSampleSetInfo
GPtrArray *crypto_info;
};
+struct _QtDemuxAavdEncryptionInfo
+{
+ GstStructure *default_properties;
+};
+
static const gchar *
qt_demux_state_string (enum QtDemuxState state)
{
@@ -2526,6 +2532,12 @@ gst_qtdemux_stream_clear (QtDemuxStream * stream)
if (info->crypto_info)
g_ptr_array_free (info->crypto_info, TRUE);
}
+ if (stream->protection_scheme_type == FOURCC_aavd) {
+ QtDemuxAavdEncryptionInfo *info =
+ (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
+ if (info->default_properties)
+ gst_structure_free (info->default_properties);
+ }
g_free (stream->protection_scheme_info);
stream->protection_scheme_info = NULL;
}
@@ -5694,6 +5706,16 @@ gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
+ if (stream->protected && stream->protection_scheme_type == FOURCC_aavd) {
+ GstStructure *crypto_info;
+ QtDemuxAavdEncryptionInfo *info =
+ (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
+
+ crypto_info = gst_structure_copy (info->default_properties);
+ if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
+ GST_ERROR_OBJECT (qtdemux, "failed to attach aavd metadata to buffer");
+ }
+
if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
GstStructure *crypto_info;
QtDemuxCencSampleSetInfo *info =
@@ -8271,6 +8293,17 @@ gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
FALSE);
+ if (stream->protection_scheme_type == FOURCC_aavd) {
+ s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
+ if (!gst_structure_has_name (s, "application/x-aavd")) {
+ gst_structure_set (s,
+ "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
+ NULL);
+ gst_structure_set_name (s, "application/x-aavd");
+ }
+ return TRUE;
+ }
+
if (stream->protection_scheme_type != FOURCC_cenc) {
GST_ERROR_OBJECT (qtdemux,
"unsupported protection scheme: %" GST_FOURCC_FORMAT,
@@ -10249,6 +10282,42 @@ qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
}
}
+static gboolean
+qtdemux_parse_protection_aavd (GstQTDemux * qtdemux,
+ QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
+{
+ GNode *adrm;
+ guint32 adrm_size;
+ GstBuffer *adrm_buf = NULL;
+ QtDemuxAavdEncryptionInfo *info;
+
+ adrm = qtdemux_tree_get_child_by_type (container, FOURCC_adrm);
+ if (G_UNLIKELY (!adrm)) {
+ GST_ERROR_OBJECT (qtdemux, "aavd box does not contain mandatory adrm box");
+ return FALSE;
+ }
+ adrm_size = QT_UINT32 (adrm->data);
+ adrm_buf =
+ gst_buffer_new_wrapped (g_memdup (adrm->data, adrm_size), adrm_size);
+
+ stream->protection_scheme_type = FOURCC_aavd;
+
+ if (!stream->protection_scheme_info)
+ stream->protection_scheme_info = g_new0 (QtDemuxAavdEncryptionInfo, 1);
+
+ info = (QtDemuxAavdEncryptionInfo *) stream->protection_scheme_info;
+
+ if (info->default_properties)
+ gst_structure_free (info->default_properties);
+ info->default_properties = gst_structure_new ("application/x-aavd",
+ "encrypted", G_TYPE_BOOLEAN, TRUE,
+ "adrm", GST_TYPE_BUFFER, adrm_buf, NULL);
+ gst_buffer_unref (adrm_buf);
+
+ *original_fmt = FOURCC_mp4a;
+ return TRUE;
+}
+
/* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
* protected streams (sinf, frma, schm and schi); if the protection scheme is
* Common Encryption (cenc), the function will also parse the tenc box (defined
@@ -10697,6 +10766,19 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
goto error_encrypted;
+ if (fourcc == FOURCC_aavd) {
+ if (stream->subtype != FOURCC_soun) {
+ GST_ERROR_OBJECT (qtdemux,
+ "Unexpeced stsd type 'aavd' outside 'soun' track");
+ } else {
+ /* encrypted audio with sound sample description v0 */
+ GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
+ stream->protected = TRUE;
+ if (!qtdemux_parse_protection_aavd (qtdemux, stream, enc, &fourcc))
+ GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
+ }
+ }
+
if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
/* FIXME this looks wrong, there might be multiple children
* with the same type */
@@ -12245,16 +12327,22 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
GST_TAG_BITRATE, bitrate, NULL);
}
+ esds = NULL;
mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
- if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca)
- mp4a = NULL;
- else if (!stream->protected)
+ if (stream->protected) {
+ if (QTDEMUX_TREE_NODE_FOURCC (mp4a) == FOURCC_aavd) {
+ esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
+ }
+ if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
+ mp4a = NULL;
+ }
+ } else {
mp4a = NULL;
+ }
}
wave = NULL;
- esds = NULL;
if (mp4a) {
wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
if (wave)