[FFmpeg-devel] [PATCH] Add support for parsing Matroska ContentEncKeyID

Frank Galligan frankgalligan at gmail.com
Thu Mar 7 17:11:38 CET 2013


From: Frank Galligan <fgalligan at chromium.org>

This patch adds the enums for the ContentEncryption elements.
This patch also adds support for parsing the ContentEncKeyID. The
ContentEncKeyID is then base64 encoded and stored in the stream's
metadata.
---
 libavformat/matroska.h    |  9 ++++++++
 libavformat/matroskadec.c | 53 ++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 57 insertions(+), 5 deletions(-)

diff --git a/libavformat/matroska.h b/libavformat/matroska.h
index 8e6f8cc..8a7e10b 100644
--- a/libavformat/matroska.h
+++ b/libavformat/matroska.h
@@ -137,6 +137,15 @@
 #define MATROSKA_ID_ENCODINGCOMPALGO 0x4254
 #define MATROSKA_ID_ENCODINGCOMPSETTINGS 0x4255
 
+#define MATROSKA_ID_ENCODINGENCRYPTION 0x5035
+#define MATROSKA_ID_ENCODINGENCAESSETTINGS 0x47E7
+#define MATROSKA_ID_ENCODINGENCALGO 0x47E1
+#define MATROSKA_ID_ENCODINGENCKEYID 0x47E2
+#define MATROSKA_ID_ENCODINGSIGALGO 0x47E5
+#define MATROSKA_ID_ENCODINGSIGHASHALGO 0x47E6
+#define MATROSKA_ID_ENCODINGSIGKEYID 0x47E4
+#define MATROSKA_ID_ENCODINGSIGNATURE 0x47E3
+
 /* ID in the cues master */
 #define MATROSKA_ID_POINTENTRY 0xBB
 
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 249a023..8c9fbc6 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -39,6 +39,7 @@
 #include "matroska.h"
 #include "libavcodec/bytestream.h"
 #include "libavcodec/mpeg4audio.h"
+#include "libavutil/base64.h"
 #include "libavutil/intfloat.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/avstring.h"
@@ -102,9 +103,15 @@ typedef struct {
 } MatroskaTrackCompression;
 
 typedef struct {
+    uint64_t algo;
+    EbmlBin  key_id;
+} MatroskaTrackEncryption;
+
+typedef struct {
     uint64_t scope;
     uint64_t type;
     MatroskaTrackCompression compression;
+    MatroskaTrackEncryption encryption;
 } MatroskaTrackEncoding;
 
 typedef struct {
@@ -345,10 +352,21 @@ static EbmlSyntax matroska_track_encoding_compression[] = {
     { 0 }
 };
 
+static EbmlSyntax matroska_track_encoding_encryption[] = {
+    { MATROSKA_ID_ENCODINGENCALGO,        EBML_UINT, 0, offsetof(MatroskaTrackEncryption,algo), {.u=0} },
+    { MATROSKA_ID_ENCODINGENCKEYID,       EBML_BIN, 0, offsetof(MatroskaTrackEncryption,key_id) },
+    { MATROSKA_ID_ENCODINGENCAESSETTINGS, EBML_NONE },
+    { MATROSKA_ID_ENCODINGSIGALGO,        EBML_NONE },
+    { MATROSKA_ID_ENCODINGSIGHASHALGO,    EBML_NONE },
+    { MATROSKA_ID_ENCODINGSIGKEYID,       EBML_NONE },
+    { MATROSKA_ID_ENCODINGSIGNATURE,      EBML_NONE },
+    { 0 }
+};
 static EbmlSyntax matroska_track_encoding[] = {
     { MATROSKA_ID_ENCODINGSCOPE,      EBML_UINT, 0, offsetof(MatroskaTrackEncoding,scope), {.u=1} },
     { MATROSKA_ID_ENCODINGTYPE,       EBML_UINT, 0, offsetof(MatroskaTrackEncoding,type), {.u=0} },
     { MATROSKA_ID_ENCODINGCOMPRESSION,EBML_NEST, 0, offsetof(MatroskaTrackEncoding,compression), {.n=matroska_track_encoding_compression} },
+    { MATROSKA_ID_ENCODINGENCRYPTION, EBML_NEST, 0, offsetof(MatroskaTrackEncoding,encryption), {.n=matroska_track_encoding_encryption} },
     { MATROSKA_ID_ENCODINGORDER,      EBML_NONE },
     { 0 }
 };
@@ -1539,6 +1557,7 @@ static int matroska_read_header(AVFormatContext *s)
         int extradata_offset = 0;
         uint32_t fourcc = 0;
         AVIOContext b;
+        char* key_id_base64 = NULL;
 
         /* Apply some sanity checks. */
         if (track->type != MATROSKA_TRACK_TYPE_VIDEO &&
@@ -1569,8 +1588,24 @@ static int matroska_read_header(AVFormatContext *s)
             av_log(matroska->ctx, AV_LOG_ERROR,
                    "Multiple combined encodings not supported");
         } else if (encodings_list->nb_elem == 1) {
-            if (encodings[0].type ||
-                (
+            if (encodings[0].type) {
+                if (encodings[0].encryption.key_id.size > 0) {
+                    /* Save the encryption key id to be stored later as a
+                       metadata tag. */
+                    const int b64_size = AV_BASE64_SIZE(encodings[0].encryption.key_id.size);
+                    key_id_base64 = (char*)av_malloc(b64_size);
+                    if (key_id_base64 == NULL)
+                        return AVERROR(ENOMEM);
+
+                    av_base64_encode(key_id_base64, b64_size,
+                                     encodings[0].encryption.key_id.data,
+                                     encodings[0].encryption.key_id.size);
+                } else {
+                    encodings[0].scope = 0;
+                    av_log(matroska->ctx, AV_LOG_ERROR,
+                           "Unsupported encoding type");
+                }
+            } else if (
 #if CONFIG_ZLIB
                  encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_ZLIB &&
 #endif
@@ -1580,7 +1615,7 @@ static int matroska_read_header(AVFormatContext *s)
 #if CONFIG_LZO
                  encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_LZO &&
 #endif
-                 encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP)) {
+                 encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP) {
                 encodings[0].scope = 0;
                 av_log(matroska->ctx, AV_LOG_ERROR,
                        "Unsupported encoding type");
@@ -1610,8 +1645,16 @@ static int matroska_read_header(AVFormatContext *s)
         }
 
         st = track->stream = avformat_new_stream(s, NULL);
-        if (st == NULL)
+        if (st == NULL) {
+            av_free(key_id_base64);
             return AVERROR(ENOMEM);
+        }
+        
+        if (key_id_base64) {
+            /* export encryption key id as base64 metadata tag */
+            av_dict_set(&st->metadata, "enc_key_id", key_id_base64, 0);
+            av_free(key_id_base64);
+        }
 
         if (!strcmp(track->codec_id, "V_MS/VFW/FOURCC")
             && track->codec_priv.size >= 40
@@ -2103,7 +2146,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska,
     int offset = 0, res;
     AVPacket *pkt;
 
-    if (encodings && encodings->scope & 1) {
+    if (encodings && !encodings->type && encodings->scope & 1) {
         res = matroska_decode_buffer(&pkt_data, &pkt_size, track);
         if (res < 0)
             return res;
-- 
1.8.1.3



More information about the ffmpeg-devel mailing list