diff mbox

[FFmpeg-devel] add support for parsing pssh box

Message ID PS1PR03MB1868E5CEC51DAE8E44C6A09EB0910@PS1PR03MB1868.apcprd03.prod.outlook.com
State New
Headers show

Commit Message

Zewu Chen May 17, 2018, 6:32 a.m. UTC
Use structure AVEncryptionInitInfo to provide CENC initialization information
for the application.

Signed-off-by: Chen Zewu <bjweare@outlook.com>
---
 libavformat/isom.h |  1 +
 libavformat/mov.c  | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+)

Comments

Jacob Trimble May 17, 2018, 4:38 p.m. UTC | #1
On Wed, May 16, 2018 at 11:32 PM, Zewu Chen <bjweare@outlook.com> wrote:
> Use structure AVEncryptionInitInfo to provide CENC initialization information
> for the application.
>
> Signed-off-by: Chen Zewu <bjweare@outlook.com>
> ---
>  libavformat/isom.h |  1 +
>  libavformat/mov.c  | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 65 insertions(+)
>
> diff --git a/libavformat/isom.h b/libavformat/isom.h
> index fb36112..f0f5b2c 100644
> --- a/libavformat/isom.h
> +++ b/libavformat/isom.h
> @@ -274,6 +274,7 @@ typedef struct MOVContext {
>      MOVFragmentIndex frag_index;
>      int atom_depth;
>      unsigned int aax_mode;  ///< 'aax' file has been detected
> +    AVEncryptionInitInfo *cenc_init_info;
>      uint8_t file_key[20];
>      uint8_t file_iv[20];
>      void *activation_bytes;
> diff --git a/libavformat/mov.c b/libavformat/mov.c
> index 1975011..f87f10b 100644
> --- a/libavformat/mov.c
> +++ b/libavformat/mov.c
> @@ -6165,6 +6165,52 @@ static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
>      return 0;
>  }
>
> +static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
> +{
> +    int i, err;
> +    int64_t start_pos;
> +    uint8_t version = 0;
> +    uint32_t num_key_ids = 0;
> +    uint32_t data_size = 0;
> +
> +    if (c->fc->nb_streams < 1)
> +        return AVERROR_INVALIDDATA;
> +
> +    version = avio_r8(pb);
> +    avio_skip(pb, 3); /* flags */
> +
> +    start_pos = avio_tell(pb);
> +
> +    avio_skip(pb, 16); /* system id */
> +
> +    if (version > 0) {
> +        num_key_ids = avio_rb32(pb);
> +        avio_skip(pb, 16*num_key_ids); /* KIDs */
> +    }
> +
> +    data_size = avio_rb32(pb);
> +
> +    if (c->cenc_init_info)
> +        av_log(c->fc, AV_LOG_WARNING, "Duplicated PSSH atom\n");
> +    av_free(c->cenc_init_info);
> +    c->cenc_init_info = av_encryption_init_info_alloc(16, num_key_ids, 16, data_size);
> +    if (!c->cenc_init_info)
> +        return AVERROR(ENOMEM);
> +
> +    avio_seek(pb, start_pos, SEEK_SET);
> +    avio_read(pb, c->cenc_init_info->system_id, 16);
> +
> +    if (version > 0)
> +        avio_skip(pb, 4); /*  kid_count */
> +    for (i = 0; i < num_key_ids; i++)
> +        avio_read(pb, c->cenc_init_info->key_ids[i], 16);
> +
> +    avio_skip(pb, 4); /* data_size */
> +    avio_read(pb, c->cenc_init_info->data, data_size);
> +
> +    return err;
> +}
> +
>  static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
>  {
>      AVStream *st;
> @@ -6507,6 +6553,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = {
>  { MKTAG('s','a','i','z'), mov_read_saiz },
>  { MKTAG('s','a','i','o'), mov_read_saio },
>  { MKTAG('s','c','h','m'), mov_read_schm },
> +{ MKTAG('p','s','s','h'), mov_read_pssh },
>  { MKTAG('s','c','h','i'), mov_read_default },
>  { MKTAG('t','e','n','c'), mov_read_tenc },
>  { MKTAG('d','f','L','a'), mov_read_dfla },
> @@ -6982,6 +7029,7 @@ static int mov_read_close(AVFormatContext *s)
>      }
>      av_freep(&mov->frag_index.item);
>
> +    av_freep(&mov->cenc_init_info);
>      av_freep(&mov->aes_decrypt);
>      av_freep(&mov->chapter_tracks);
>
> @@ -7263,6 +7311,22 @@ static int mov_read_header(AVFormatContext *s)
>
>      ff_rfps_calculate(s);
>
> +    if (mov->cenc_init_info) {
> +        for (i = 0; i < s->nb_streams; i++) {
> +            AVStream *st = s->streams[i];
> +            uint8_t *info;
> +            size_t info_size;
> +
> +            info = av_encryption_init_info_add_side_data(mov->cenc_init_info, &info_size);
> +            if (!info)
> +                return AVERROR(ENOMEM);
> +
> +            err = av_stream_add_side_data(st, AV_PKT_DATA_ENCRYPTION_INIT_INFO, info, info_size);
> +            if (err < 0)
> +                break;
> +        }
> +    }
> +
>      for (i = 0; i < s->nb_streams; i++) {
>          AVStream *st = s->streams[i];
>          MOVStreamContext *sc = st->priv_data;
> --
> 1.9.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

MP4 can have multiple PSSH boxes in it, so this would depend on
http://ffmpeg.org/pipermail/ffmpeg-devel/2018-May/229665.html

I also have implemented this with multiple PSSH support as well as
exposing the AVEncryptionInfo, but I am waiting on that patch to be
merged.  I sent a first version that only supported one PSSH box in it
in January, with no movement on it.
diff mbox

Patch

diff --git a/libavformat/isom.h b/libavformat/isom.h
index fb36112..f0f5b2c 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -274,6 +274,7 @@  typedef struct MOVContext {
     MOVFragmentIndex frag_index;
     int atom_depth;
     unsigned int aax_mode;  ///< 'aax' file has been detected
+    AVEncryptionInitInfo *cenc_init_info;
     uint8_t file_key[20];
     uint8_t file_iv[20];
     void *activation_bytes;
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 1975011..f87f10b 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -6165,6 +6165,52 @@  static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     return 0;
 }
 
+static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+    int i, err;
+    int64_t start_pos;
+    uint8_t version = 0;
+    uint32_t num_key_ids = 0;
+    uint32_t data_size = 0;
+
+    if (c->fc->nb_streams < 1)
+        return AVERROR_INVALIDDATA;
+
+    version = avio_r8(pb);
+    avio_skip(pb, 3); /* flags */
+
+    start_pos = avio_tell(pb);
+
+    avio_skip(pb, 16); /* system id */
+
+    if (version > 0) {
+        num_key_ids = avio_rb32(pb);
+        avio_skip(pb, 16*num_key_ids); /* KIDs */
+    }
+
+    data_size = avio_rb32(pb);
+
+    if (c->cenc_init_info)
+        av_log(c->fc, AV_LOG_WARNING, "Duplicated PSSH atom\n");
+    av_free(c->cenc_init_info);
+    c->cenc_init_info = av_encryption_init_info_alloc(16, num_key_ids, 16, data_size);
+    if (!c->cenc_init_info)
+        return AVERROR(ENOMEM);
+
+    avio_seek(pb, start_pos, SEEK_SET);
+    avio_read(pb, c->cenc_init_info->system_id, 16);
+
+    if (version > 0)
+        avio_skip(pb, 4); /*  kid_count */
+    for (i = 0; i < num_key_ids; i++)
+        avio_read(pb, c->cenc_init_info->key_ids[i], 16);
+
+    avio_skip(pb, 4); /* data_size */
+    avio_read(pb, c->cenc_init_info->data, data_size);
+
+    return err;
+}
+
 static int mov_read_tenc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 {
     AVStream *st;
@@ -6507,6 +6553,7 @@  static const MOVParseTableEntry mov_default_parse_table[] = {
 { MKTAG('s','a','i','z'), mov_read_saiz },
 { MKTAG('s','a','i','o'), mov_read_saio },
 { MKTAG('s','c','h','m'), mov_read_schm },
+{ MKTAG('p','s','s','h'), mov_read_pssh },
 { MKTAG('s','c','h','i'), mov_read_default },
 { MKTAG('t','e','n','c'), mov_read_tenc },
 { MKTAG('d','f','L','a'), mov_read_dfla },
@@ -6982,6 +7029,7 @@  static int mov_read_close(AVFormatContext *s)
     }
     av_freep(&mov->frag_index.item);
 
+    av_freep(&mov->cenc_init_info);
     av_freep(&mov->aes_decrypt);
     av_freep(&mov->chapter_tracks);
 
@@ -7263,6 +7311,22 @@  static int mov_read_header(AVFormatContext *s)
 
     ff_rfps_calculate(s);
 
+    if (mov->cenc_init_info) {
+        for (i = 0; i < s->nb_streams; i++) {
+            AVStream *st = s->streams[i];
+            uint8_t *info;
+            size_t info_size;
+
+            info = av_encryption_init_info_add_side_data(mov->cenc_init_info, &info_size);
+            if (!info)
+                return AVERROR(ENOMEM);
+
+            err = av_stream_add_side_data(st, AV_PKT_DATA_ENCRYPTION_INIT_INFO, info, info_size);
+            if (err < 0)
+                break;
+        }
+    }
+
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *st = s->streams[i];
         MOVStreamContext *sc = st->priv_data;