summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJorge Zapata <jorgeluis.zapata@gmail.com>2012-07-06 12:38:50 +0200
committerJosep Torra <n770galaxy@gmail.com>2013-05-22 14:24:55 +0200
commitf15e0fb60da4060b787cef4885b8b002973c22c0 (patch)
treedbe7fc35ccd194a102ff08f5d66f4e7f9e4140d3
parent8176858690204c7017dfa007a3c6054f54bf84ae (diff)
qtdemux: Add support for encrypted tracks
Parse the atoms needed for encrypted tracks. Send signals whenever the encryption atoms have been parsed. Add a generic signal to decrypt encrypted buffers.
-rw-r--r--gst/isomp4/qtdemux.c367
-rw-r--r--gst/isomp4/qtdemux.h6
-rw-r--r--gst/isomp4/qtdemux_fourcc.h11
-rw-r--r--gst/isomp4/qtdemux_types.c9
4 files changed, 372 insertions, 21 deletions
diff --git a/gst/isomp4/qtdemux.c b/gst/isomp4/qtdemux.c
index fbf944a95..f769f2c97 100644
--- a/gst/isomp4/qtdemux.c
+++ b/gst/isomp4/qtdemux.c
@@ -344,6 +344,9 @@ struct _QtDemuxStream
guint32 def_sample_duration;
guint32 def_sample_size;
guint32 def_sample_flags;
+
+ gboolean encrypted;
+ guint32 senc_sample_index;
};
enum QtDemuxState
@@ -354,6 +357,16 @@ enum QtDemuxState
QTDEMUX_STATE_BUFFER_MDAT /* Buffering the mdat atom */
};
+enum
+{
+ SIGNAL_CENC_TENC,
+ SIGNAL_CENC_SENC,
+ SIGNAL_DECRYPT,
+ LAST_SIGNAL
+};
+
+static guint gst_qtdemux_signals[LAST_SIGNAL] = { 0 };
+
static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
guint32 fourcc, GstByteReader * parser);
@@ -432,6 +445,75 @@ static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
static void
+g_cclosure_marshal_BUFFER__UINT_BUFFER_UINT (GClosure * closure,
+ GValue * return_value,
+ guint n_param_values,
+ const GValue * param_values,
+ gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data)
+{
+ typedef gpointer (*GMarshalFunc_BUFFER__UINT_BUFFER_UINT) (gpointer data1,
+ guint arg_1, gpointer arg_2, guint arg_3, gpointer data2);
+ register GMarshalFunc_BUFFER__UINT_BUFFER_UINT callback;
+ register GCClosure *cc = (GCClosure *) closure;
+ register gpointer data1, data2;
+ gpointer v_return;
+
+ g_return_if_fail (return_value != NULL);
+ g_return_if_fail (n_param_values == 4);
+
+ if (G_CCLOSURE_SWAP_DATA (closure)) {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ } else {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+
+
+ callback =
+ (GMarshalFunc_BUFFER__UINT_BUFFER_UINT) (marshal_data ? marshal_data :
+ cc->callback);
+
+ v_return = callback (data1,
+ g_value_get_uint (param_values + 1),
+ g_value_peek_pointer (param_values + 2),
+ g_value_get_uint (param_values + 3), data2);
+
+ gst_value_take_buffer (return_value, v_return);
+}
+
+static void
+g_cclosure_marshal_VOID__UINT_BUFFER (GClosure * closure,
+ GValue * return_value G_GNUC_UNUSED,
+ guint n_param_values,
+ const GValue * param_values,
+ gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__UINT_BUFFER) (gpointer data1, guint arg_1,
+ gpointer arg_2, gpointer data2);
+ register GMarshalFunc_VOID__UINT_BUFFER callback;
+ register GCClosure *cc = (GCClosure *) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA (closure)) {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ } else {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback =
+ (GMarshalFunc_VOID__UINT_BUFFER) (marshal_data ? marshal_data :
+ cc->callback);
+
+ callback (data1,
+ g_value_get_uint (param_values + 1),
+ g_value_peek_pointer (param_values + 2), data2);
+}
+
+static void
gst_qtdemux_base_init (gpointer klass)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
@@ -471,6 +553,64 @@ gst_qtdemux_class_init (GstQTDemuxClass * klass)
gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
gst_tag_register_musicbrainz_tags ();
+
+ /**
+ * GstQTDemux::cenc-tenc:
+ * @demux: the demuxer instance
+ * @track_id: the track identifier
+ * @tenc: a #GstBuffer containing tenc node
+ *
+ * This signal gets emitted whenever a tenc atom is found to allow
+ * the initialization of an external decrypter.
+ *
+ * Since: 0.10.31
+ */
+ gst_qtdemux_signals[SIGNAL_CENC_TENC] =
+ g_signal_new ("cenc-tenc", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstQTDemuxClass, cenc_tenc),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__UINT_BUFFER, G_TYPE_NONE, 2,
+ G_TYPE_UINT, GST_TYPE_BUFFER);
+
+ /**
+ * GstQTDemux::cenc-senc:
+ * @demux: the demuxer instance
+ * @track_id: the track identifier
+ * @senc: a #GstBuffer containing senc node
+ *
+ * This signal gets emitted whenever a senc atom is found to allow
+ * the initialization of an external decrypter.
+ *
+ * Since: 0.10.31
+ */
+ gst_qtdemux_signals[SIGNAL_CENC_SENC] =
+ g_signal_new ("cenc-senc", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstQTDemuxClass, cenc_senc),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__UINT_BUFFER, G_TYPE_NONE, 2,
+ G_TYPE_UINT, GST_TYPE_BUFFER);
+
+ /**
+ * GstQTDemux::decrypt:
+ * @demux: the demuxer instance
+ * @track_id: the track identifier
+ * @buffer: a #GstBuffer that has to be decrypted
+ * @sample_index: the sample index that might be needed for decrypt algorithm
+ *
+ * Returns: a #GstBuffer with data decrypted.
+ *
+ * This signal gets emitted whenever an encrypted buffer is available to allow
+ * the implemention of an external decrypter to return a new buffer with
+ * content decrypted.
+ *
+ * Since: 0.10.31
+ */
+ gst_qtdemux_signals[SIGNAL_DECRYPT] =
+ g_signal_new ("decrypt", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstQTDemuxClass, decrypt),
+ NULL, NULL,
+ g_cclosure_marshal_BUFFER__UINT_BUFFER_UINT, GST_TYPE_BUFFER, 3,
+ G_TYPE_UINT, GST_TYPE_BUFFER, G_TYPE_UINT);
}
static void
@@ -1854,6 +1994,17 @@ gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
switch (transition) {
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ /* When decrypt signal is connected we support demuxing DRM */
+ if (g_signal_handler_find (qtdemux, G_SIGNAL_MATCH_ID,
+ gst_qtdemux_signals[SIGNAL_DECRYPT], 0, NULL, NULL, NULL)) {
+ qtdemux->supports_drm = TRUE;
+ GST_INFO_OBJECT (qtdemux, "Support for DRM is enabled");
+ } else {
+ qtdemux->supports_drm = FALSE;
+ }
+ break;
+
case GST_STATE_CHANGE_PAUSED_TO_READY:
break;
default:
@@ -2477,6 +2628,24 @@ qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
base_offset = -2;
goto next;
}
+
+ /* On encrypted streams emit a signal with the senc node */
+ if (stream->encrypted) {
+ GNode *node;
+ GstBuffer *buf = NULL;
+ node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_senc);
+ if (node) {
+ buf = gst_buffer_new ();
+ GST_BUFFER_DATA (buf) = node->data;
+ GST_BUFFER_SIZE (buf) = GST_READ_UINT32_BE (node->data);
+ g_signal_emit (qtdemux, gst_qtdemux_signals[SIGNAL_CENC_SENC], 0,
+ stream->track_id, buf);
+ gst_buffer_unref (buf);
+ }
+
+ stream->senc_sample_index = 0;
+ }
+
if (G_UNLIKELY (base_offset < -1))
goto lost_offset;
/* Track Run node */
@@ -3638,6 +3807,21 @@ gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
{
GstFlowReturn ret = GST_FLOW_OK;
+ if (G_UNLIKELY (stream->encrypted)) {
+ GstBuffer *dec_buf = NULL;
+
+ GST_DEBUG_OBJECT (qtdemux, "decrypting stream index = %d track index %d",
+ stream->senc_sample_index, stream->track_id);
+ /* send the decrypt signal */
+ g_signal_emit (qtdemux, gst_qtdemux_signals[SIGNAL_DECRYPT], 0,
+ stream->track_id, buf, stream->senc_sample_index++, &dec_buf);
+
+ if (dec_buf) {
+ gst_buffer_unref (buf);
+ buf = dec_buf;
+ }
+ }
+
if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
gchar *url;
@@ -4791,6 +4975,7 @@ qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
qtdemux_parse_container (qtdemux, node, buffer + 16, end);
break;
}
+ case FOURCC_enca:
case FOURCC_mp4a:
case FOURCC_alac:
{
@@ -4885,6 +5070,7 @@ qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
}
break;
}
+ case FOURCC_encv:
case FOURCC_avc1:
{
GST_MEMDUMP_OBJECT (qtdemux, "avc1", buffer, end - buffer);
@@ -6347,6 +6533,126 @@ bad_data:
return 0;
}
+/* called whenever the scheme is cenc */
+static gboolean
+qtdemux_parse_cenc (GstQTDemux * qtdemux, QtDemuxStream * stream,
+ guint32 scheme_version, GNode * schi)
+{
+ GNode *tenc;
+ GstBuffer *buf;
+
+ if (scheme_version != 0x00010000) {
+ GST_WARNING_OBJECT (qtdemux, "Wrong version number %08x", scheme_version);
+ return FALSE;
+ }
+
+ /* get the 'tenc' box from the 'schi' */
+ if (!(tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc))) {
+ GST_WARNING_OBJECT (qtdemux, "No tenc found");
+ return FALSE;
+ }
+
+ buf = gst_buffer_new ();
+ GST_BUFFER_DATA (buf) = tenc->data;
+ GST_BUFFER_SIZE (buf) = GST_READ_UINT32_BE (tenc->data);
+ g_signal_emit (qtdemux, gst_qtdemux_signals[SIGNAL_CENC_TENC], 0,
+ stream->track_id, buf);
+ gst_buffer_unref (buf);
+
+ return TRUE;
+}
+
+static void
+qtdemux_parse_schm (GstQTDemux * qtdemux, GNode * schm, guint32 * scheme_type,
+ guint32 * scheme_version)
+{
+ guint32 flags;
+ guint32 length;
+ const gchar *schm_data;
+
+ schm_data = (const gchar *) schm->data;
+
+ length = QT_UINT32 (schm_data);
+ flags = QT_UINT24 (schm_data + 8);
+
+ *scheme_type = QT_FOURCC (schm_data + 12);
+ *scheme_version = QT_UINT32 (schm_data + 16);
+
+ GST_LOG_OBJECT (qtdemux, "schm type %" GST_FOURCC_FORMAT,
+ GST_FOURCC_ARGS (*scheme_type));
+ GST_LOG_OBJECT (qtdemux, "schm version %u", *scheme_version);
+
+ if ((flags & QT_FLAG_CONTAINER) && (length > 20)) {
+ GST_LOG_OBJECT (qtdemux, "schm uri %.*s", length - 20, schm_data + 20);
+ }
+}
+
+static gboolean
+qtdemux_parse_sinf (GstQTDemux * qtdemux, QtDemuxStream * stream,
+ GNode * sinf, guint32 * fourcc)
+{
+ GNode *frma;
+ GNode *schm;
+ GNode *schi;
+ const guint8 *frma_data;
+ gboolean ret = TRUE;
+ guint32 scheme_type;
+ guint32 scheme_version;
+
+ /* now the 'frma' */
+ if (!(frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma))) {
+ GST_WARNING_OBJECT (qtdemux, "No frma found");
+ return FALSE;
+ }
+
+ frma_data = (const guint8 *) frma->data;
+ *fourcc = QT_FOURCC (frma_data + 8);
+
+ /* get the scheme type box */
+ if (!(schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm))) {
+ GST_WARNING_OBJECT (qtdemux, "No schm found");
+ return FALSE;
+ }
+
+ qtdemux_parse_schm (qtdemux, schm, &scheme_type, &scheme_version);
+
+ /* get the scheme information box */
+ if (!(schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi))) {
+ GST_WARNING_OBJECT (qtdemux, "No schi found");
+ return FALSE;
+ }
+
+ /* parse the data on this box */
+ switch (scheme_type) {
+ case FOURCC_cenc:
+ ret = qtdemux_parse_cenc (qtdemux, stream, scheme_version, schi);
+ break;
+
+ default:
+ GST_WARNING_OBJECT (qtdemux,
+ "Unsupported scheme type %" GST_FOURCC_FORMAT,
+ GST_FOURCC_ARGS (scheme_type));
+ return FALSE;
+ }
+
+ return ret;
+}
+
+static gboolean
+qtdemux_parse_encx (GstQTDemux * qtdemux, QtDemuxStream * stream,
+ GNode * encx, guint32 * fourcc)
+{
+ GNode *sinf;
+
+ /* now the 'sinf' */
+ if (!(sinf = qtdemux_tree_get_child_by_type (encx, FOURCC_sinf))) {
+ GST_WARNING_OBJECT (qtdemux, "No sinf found");
+ return FALSE;
+ }
+
+ return qtdemux_parse_sinf (qtdemux, stream, sinf, fourcc);
+}
+
/* parse the traks.
* With each track we associate a new QtDemuxStream that contains all the info
* about the trak.
@@ -6509,14 +6815,32 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
goto corrupt_file;
GST_LOG_OBJECT (qtdemux, "stsd len: %d", len);
- stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
+ fourcc = QT_FOURCC (stsd_data + 16 + 4);
GST_LOG_OBJECT (qtdemux, "stsd type: %" GST_FOURCC_FORMAT,
- GST_FOURCC_ARGS (stream->fourcc));
+ GST_FOURCC_ARGS (fourcc));
- if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi) ||
- ((fourcc & 0xFFFFFF00) == GST_MAKE_FOURCC ('e', 'n', 'c', 0)))
+ if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
goto error_encrypted;
+ /* get the real fourcc */
+ if ((fourcc == FOURCC_encv) || (fourcc == FOURCC_enca)) {
+ GNode *encx;
+
+ if (!qtdemux->supports_drm)
+ goto error_encrypted;
+
+ if (!(encx = qtdemux_tree_get_child_by_type (stsd, fourcc)))
+ goto corrupt_file;
+ if (!qtdemux_parse_encx (qtdemux, stream, encx, &(stream->fourcc)))
+ goto corrupt_file;
+
+ stream->encrypted = TRUE;
+ GST_LOG_OBJECT (qtdemux, "track decrypted format %" GST_FOURCC_FORMAT,
+ GST_FOURCC_ARGS (stream->fourcc));
+ } else {
+ stream->fourcc = fourcc;
+ }
+
if (stream->subtype == FOURCC_vide) {
guint32 w = 0, h = 0;
@@ -6546,7 +6870,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
QT_UINT16 (stsd_data + offset + 48));
stream->caps =
- qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
+ qtdemux_video_caps (qtdemux, stream, stream->fourcc, stsd_data, &codec);
if (codec) {
list = gst_tag_list_new ();
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
@@ -6577,7 +6901,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
if (esds) {
gst_qtdemux_handle_esds (qtdemux, stream, esds, list);
} else {
- switch (fourcc) {
+ switch (stream->fourcc) {
case FOURCC_avc1:
{
gint len = QT_UINT32 (stsd_data) - 0x66;
@@ -6674,7 +6998,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
GNode *glbl;
GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
- GST_FOURCC_ARGS (fourcc));
+ GST_FOURCC_ARGS (stream->fourcc));
/* codec data might be in glbl extension atom */
glbl = mp4v ?
@@ -6965,7 +7289,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
GST_INFO_OBJECT (qtdemux,
"type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
- GST_FOURCC_ARGS (fourcc), stream->caps);
+ GST_FOURCC_ARGS (stream->fourcc), stream->caps);
} else if (stream->subtype == FOURCC_soun) {
int version, samplesize;
@@ -7003,7 +7327,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
stream->bytes_per_packet = stream->bytes_per_sample;
offset = 52;
- switch (fourcc) {
+ switch (stream->fourcc) {
/* Yes, these have to be hard-coded */
case FOURCC_MAC6:
{
@@ -7056,7 +7380,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
}
if (version == 0x00010000) {
- switch (fourcc) {
+ switch (stream->fourcc) {
case FOURCC_twos:
case FOURCC_sowt:
case FOURCC_raw_:
@@ -7108,10 +7432,10 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
GST_WARNING_OBJECT (qtdemux, "unknown version %08x", version);
}
- stream->caps = qtdemux_audio_caps (qtdemux, stream, fourcc, NULL, 0,
+ stream->caps = qtdemux_audio_caps (qtdemux, stream, stream->fourcc, NULL, 0,
&codec);
- switch (fourcc) {
+ switch (stream->fourcc) {
case FOURCC_in24:
{
GNode *enda;
@@ -7217,7 +7541,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
bitrate, NULL);
}
- mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a);
+ mp4a = qtdemux_tree_get_child_by_type (stsd, fourcc);
wave = NULL;
esds = NULL;
if (mp4a) {
@@ -7236,7 +7560,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
codec id as the bottom 16 bits - but byte-swapped to store in QT (which
is big-endian).
*/
- if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
+ if ((stream->fourcc & 0xffff) == (('s' << 8) | 'm')) {
if (len < offset + 20) {
GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
} else {
@@ -7250,7 +7574,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
const guint8 *waveheader;
guint32 headerlen;
- waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
+ waveheadernode =
+ qtdemux_tree_get_child_by_type (wavenode, stream->fourcc);
if (waveheadernode) {
waveheader = (const guint8 *) waveheadernode->data;
headerlen = QT_UINT32 (waveheader);
@@ -7285,7 +7610,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
} else if (esds) {
gst_qtdemux_handle_esds (qtdemux, stream, esds, list);
} else {
- switch (fourcc) {
+ switch (stream->fourcc) {
#if 0
/* FIXME: what is in the chunk? */
case FOURCC_QDMC:
@@ -7383,14 +7708,14 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
}
GST_INFO_OBJECT (qtdemux,
"type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
- GST_FOURCC_ARGS (fourcc), stream->caps);
+ GST_FOURCC_ARGS (stream->fourcc), stream->caps);
} else if (stream->subtype == FOURCC_strm) {
- if (fourcc == FOURCC_rtsp) {
+ if (stream->fourcc == FOURCC_rtsp) {
stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
} else {
GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
- GST_FOURCC_ARGS (fourcc));
+ GST_FOURCC_ARGS (stream->fourcc));
goto unknown_stream;
}
stream->sampled = TRUE;
@@ -7401,7 +7726,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
offset = 16;
stream->caps =
- qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
+ qtdemux_sub_caps (qtdemux, stream, stream->fourcc, stsd_data, &codec);
if (codec) {
list = gst_tag_list_new ();
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
@@ -7411,7 +7736,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
}
/* hunt for sort-of codec data */
- switch (fourcc) {
+ switch (stream->fourcc) {
case FOURCC_mp4s:
{
guint len;
diff --git a/gst/isomp4/qtdemux.h b/gst/isomp4/qtdemux.h
index f2d839d7e..38a4e9feb 100644
--- a/gst/isomp4/qtdemux.h
+++ b/gst/isomp4/qtdemux.h
@@ -112,10 +112,16 @@ struct _GstQTDemux {
gboolean upstream_seekable;
gboolean upstream_size;
+
+ /* DRM is supported only if there's a listener for decrypt signal */
+ gboolean supports_drm;
};
struct _GstQTDemuxClass {
GstElementClass parent_class;
+ void (*cenc_tenc) (GstQTDemux * demux, guint32 track_id, GstBuffer * tenc);
+ void (*cenc_senc) (GstQTDemux * demux, guint32 track_id, GstBuffer * senc);
+ GstBuffer* (*decrypt) (GstQTDemux * demux, guint32 track_id, GstBuffer *buff, guint32 sample_index);
};
GType gst_qtdemux_get_type (void);
diff --git a/gst/isomp4/qtdemux_fourcc.h b/gst/isomp4/qtdemux_fourcc.h
index d747825ac..5d55a2e71 100644
--- a/gst/isomp4/qtdemux_fourcc.h
+++ b/gst/isomp4/qtdemux_fourcc.h
@@ -238,6 +238,17 @@ G_BEGIN_DECLS
/* MPEG DASH */
#define FOURCC_tfdt GST_MAKE_FOURCC('t','f','d','t')
+#define FOURCC_encv GST_MAKE_FOURCC('e','n','c','v')
+#define FOURCC_enca GST_MAKE_FOURCC('e','n','c','a')
+#define FOURCC_sinf GST_MAKE_FOURCC('s','i','n','f')
+#define FOURCC_schm GST_MAKE_FOURCC('s','c','h','m')
+#define FOURCC_schi GST_MAKE_FOURCC('s','c','h','i')
+
+/* ISO/IEC 23001-7 */
+#define FOURCC_cenc GST_MAKE_FOURCC('c','e','n','c')
+#define FOURCC_tenc GST_MAKE_FOURCC('t','e','n','c')
+#define FOURCC_senc GST_MAKE_FOURCC('s','e','n','c')
+
G_END_DECLS
#endif /* __GST_QTDEMUX_FOURCC_H__ */
diff --git a/gst/isomp4/qtdemux_types.c b/gst/isomp4/qtdemux_types.c
index 65afc8e2a..5acd548fe 100644
--- a/gst/isomp4/qtdemux_types.c
+++ b/gst/isomp4/qtdemux_types.c
@@ -172,6 +172,15 @@ static const QtNodeType qt_node_types[] = {
{FOURCC_ovc1, "ovc1", 0},
{FOURCC_owma, "owma", 0},
{FOURCC_tfdt, "Track fragment decode time", 0, qtdemux_dump_tfdt},
+ {FOURCC_frma, "frma", 0},
+ {FOURCC_encv, "encv", 0},
+ {FOURCC_enca, "enca", 0},
+ {FOURCC_sinf, "sinf", QT_FLAG_CONTAINER,},
+ {FOURCC_schm, "schm", 0},
+ {FOURCC_schi, "schi", QT_FLAG_CONTAINER,},
+ {FOURCC_cenc, "cenc", 0},
+ {FOURCC_tenc, "tenc", 0},
+ {FOURCC_senc, "senc", 0},
{0, "unknown", 0,},
};