[FFmpeg-devel,RFC] avcodec/avcodec.h: Add encryption info side data

Submitted by Jacob Trimble on Dec. 5, 2017, 11 p.m.

Details

Message ID CAO7y9i9conKY6DE6TEBpeRPpX+SQe9z38MLZ2puaSKz0JAOx-A@mail.gmail.com
State New
Headers show

Commit Message

Jacob Trimble Dec. 5, 2017, 11 p.m.
I am trying to playback encrypted content.  I know that libavformat
handles decryption already when using clearkey, but I want to handle
the decryption myself.  The encryption info is parsed in mov.c but not
exposed to the app.

This adds some structures to hold new side-data that will hold the
info needed to decrypt.  I wanted to post this first before I
implemented the code in mov.c (and probably eventually matroskadec.c
for webm).

Also, can I use the flexible array member feature, it was introduced
in C99?  Would a 0-length array be better?

Comments

Derek Buitenhuis Dec. 5, 2017, 11:25 p.m.
On 12/5/2017 11:00 PM, Jacob Trimble wrote:
> Also, can I use the flexible array member feature, it was introduced
> in C99?  Would a 0-length array be better?

No, I don't think this would be OK inside a public header, unfortunately.

- Derek
Jacob Trimble Dec. 6, 2017, 12:36 a.m.
On Tue, Dec 5, 2017 at 3:25 PM, Derek Buitenhuis
<derek.buitenhuis@gmail.com> wrote:
> On 12/5/2017 11:00 PM, Jacob Trimble wrote:
>> Also, can I use the flexible array member feature, it was introduced
>> in C99?  Would a 0-length array be better?
>
> No, I don't think this would be OK inside a public header, unfortunately.

Would a 0-length array work?  Otherwise I would need to have it be a
1-length array and have to account for that when calculating the size
to allocate; it would also require a comment to ignore the size of the
array.

The reason I want it to be an array is because I want a variable
number of elements, but I want the data contained in the struct.
Since this will be extra data, AFAIK it will only be free()'d, so I
can't use pointers or it will leak.

Another alternative would be to still malloc more than needed and have
the memory past the struct be the array.  That seems like a hack, but
would allow a simple free().  For example:

info = malloc(sizeof(AVPacketEncryptionInfo) +
sizeof(AVPacketSubsampleInfo) * num_subsamples);
info.subsamples = (uint8_t*)info + sizeof(AVPacketEncryptionInfo);
Derek Buitenhuis Dec. 6, 2017, 1:22 a.m.
On 12/6/2017 12:36 AM, Jacob Trimble wrote:
> Would a 0-length array work?  Otherwise I would need to have it be a
> 1-length array and have to account for that when calculating the size
> to allocate; it would also require a comment to ignore the size of the
> array.

Aren't 0-length arrays a GNU extensions? If so, I would gather that it
probably is not OK in a public header, either.

> The reason I want it to be an array is because I want a variable
> number of elements, but I want the data contained in the struct.
> Since this will be extra data, AFAIK it will only be free()'d, so I
> can't use pointers or it will leak.
> 
> Another alternative would be to still malloc more than needed and have
> the memory past the struct be the array.  That seems like a hack, but
> would allow a simple free().  For example:

I'm not entirely sure what way we prefer nowadays, but you can see
we've had side data with variable length members before with e.g.
AV_PKT_DATA_QUALITY_STATS, but that doesn't have a struct associated
with it. I'm hoping someone more up to date with the side data stuff
can chime in with a suggestion on what our current best practices
are for it.

- Derek

Patch hide | download patch | download mbox

From 608524d302bec8a8339e8389cfbdebfd573cf75b Mon Sep 17 00:00:00 2001
From: Jacob Trimble <modmaker@google.com>
Date: Tue, 5 Dec 2017 14:52:22 -0800
Subject: [PATCH] avpacket: Add encryption info side data.

Signed-off-by: Jacob Trimble <modmaker@google.com>
---
 libavcodec/avcodec.h | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 5db6a81320..7c9b071c48 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1112,6 +1112,58 @@  typedef struct AVCPBProperties {
     uint64_t vbv_delay;
 } AVCPBProperties;
 
+/**
+ * This describes encryption info for a packet.  This contains frame-specific
+ * info for how to decrypt the packet before passing it to the decoder.  If this
+ * side-data is present, then the packet is encrypted.
+ *
+ * Since this uses a flexible array member, the size and layout of this type
+ * is part of the public API/ABI.
+ */
+typedef struct AVPacketEncryptionInfo {
+    /** The fourcc encryption scheme. */
+    char scheme[4];
+
+    /** The ID of the key used to encrypt the packet. */
+    uint8_t key_id[16];
+
+    /** The initialization vector. */
+    uint8_t iv[16];
+
+    /** The size of the IV, this will either be 8 or 16. */
+    int iv_size;
+
+    /**
+     * Only used for pattern encryption.  This is the number of 16-byte blocks
+     * that are encrypted.
+     */
+    unsigned int crypt_byte_size;
+
+    /**
+     * Only used for pattern encryption.  This is the number of 16-byte blocks
+     * that are clear.
+     */
+    unsigned int skip_byte_size;
+
+    /**
+     * The number of sub-samples in this packet.  If 0, then the whole sample
+     * is encrypted.
+     */
+    unsigned int subsample_count;
+
+    struct {
+      /** The number of bytes that are clear. */
+      unsigned int bytes_of_clear_data;
+
+      /**
+       * The number of bytes that are protected.  If using pattern encryption,
+       * the pattern applies to only the protected bytes; if not using pattern
+       * encryption, all these bytes are encrypted.
+       */
+      unsigned int bytes_of_protected_data;
+    } subsamples[];
+} AVPacketEncryptionInfo;
+
 /**
  * The decoder will keep a reference to the frame and may reuse it later.
  */
@@ -1327,6 +1379,19 @@  enum AVPacketSideDataType {
      */
     AV_PKT_DATA_A53_CC,
 
+    /**
+     * This side data is encryption "initialization data".
+     * For MP4 this is the entire 'pssh' box.
+     * For WebM this is the key ID.
+     */
+    AV_PKT_DATA_ENCRYPTION_INIT_DATA,
+
+    /**
+     * This side data is an AVPacketEncryptionInfo structure and contains info
+     * about how the packet is encrypted.
+     */
+    AV_PKT_DATA_PACKET_ENCRYPTION_INFO,
+
     /**
      * The number of side data types.
      * This is not part of the public API/ABI in the sense that it may
-- 
2.15.1.424.g9478a66081-goog