]> granicus.if.org Git - libvpx/commitdiff
Basic encryption feature for libvpx.
authorDmitry Kovalev <dkovalev@google.com>
Sat, 16 Mar 2013 01:21:55 +0000 (18:21 -0700)
committerDmitry Kovalev <dkovalev@google.com>
Sat, 16 Mar 2013 01:21:55 +0000 (18:21 -0700)
New decoder control paramter VP8_SET_DECRYPT_KEY to set the decryption key.

Change-Id: I6fc1f44d41f74f3b3f702778af1a6f8f5cc9439f

13 files changed:
configure
test/decode_test_driver.cc
test/decode_test_driver.h
test/encode_test_driver.cc
test/test.mk
test/vp8_boolcoder_test.cc
test/vp8_decrypt_test.cc [new file with mode: 0644]
vp8/decoder/dboolhuff.c
vp8/decoder/dboolhuff.h
vp8/decoder/decodframe.c
vp8/decoder/onyxd_int.h
vp8/vp8_dx_iface.c
vpx/vp8dx.h

index 89a1eb11e708d05e88df29aee7839721497d0d01..ad33c9c1c378ef01a27b8a236ac32f74a79fb5c4 100755 (executable)
--- a/configure
+++ b/configure
@@ -298,6 +298,7 @@ CONFIG_LIST="
     multi_res_encoding
     temporal_denoising
     experimental
+    decrypt
     ${EXPERIMENT_LIST}
 "
 CMDLINE_SELECT="
@@ -347,6 +348,7 @@ CMDLINE_SELECT="
     multi_res_encoding
     temporal_denoising
     experimental
+    decrypt
 "
 
 process_cmdline() {
index 84afe7f842e1e2fd703b04fe8050a11db7c22ca3..0db48e4a79a2b4d17a9bc55e573f544bfa4bce31 100644 (file)
 
 namespace libvpx_test {
 #if CONFIG_VP8_DECODER
-void Decoder::DecodeFrame(const uint8_t *cxdata, int size) {
-  if (!decoder_.priv) {
-    const vpx_codec_err_t res_init = vpx_codec_dec_init(&decoder_,
-                                                        &vpx_codec_vp8_dx_algo,
-                                                        &cfg_, 0);
-    ASSERT_EQ(VPX_CODEC_OK, res_init) << DecodeError();
-  }
 
+vpx_codec_err_t Decoder::DecodeFrame(const uint8_t *cxdata, int size) {
   vpx_codec_err_t res_dec;
   REGISTER_STATE_CHECK(res_dec = vpx_codec_decode(&decoder_,
                                                   cxdata, size, NULL, 0));
-  ASSERT_EQ(VPX_CODEC_OK, res_dec) << DecodeError();
+  return res_dec;
 }
 
 void DecoderTest::RunLoop(CompressedVideoSource *video) {
@@ -34,7 +28,9 @@ void DecoderTest::RunLoop(CompressedVideoSource *video) {
 
   // Decode frames.
   for (video->Begin(); video->cxdata(); video->Next()) {
-    decoder.DecodeFrame(video->cxdata(), video->frame_size());
+    vpx_codec_err_t res_dec = decoder.DecodeFrame(video->cxdata(),
+                                                  video->frame_size());
+    ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder.DecodeError();
 
     DxDataIterator dec_iter = decoder.GetDxData();
     const vpx_image_t *img = NULL;
index 6408bee017320d85f02122f1af7cda9c75bc9033..7d31a08954ad6c8070a2575bea90bea4fe4f5b69 100644 (file)
@@ -44,13 +44,14 @@ class Decoder {
   Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline)
       : cfg_(cfg), deadline_(deadline) {
     memset(&decoder_, 0, sizeof(decoder_));
+    Init();
   }
 
   ~Decoder() {
     vpx_codec_destroy(&decoder_);
   }
 
-  void DecodeFrame(const uint8_t *cxdata, int size);
+  vpx_codec_err_t DecodeFrame(const uint8_t *cxdata, int size);
 
   DxDataIterator GetDxData() {
     return DxDataIterator(&decoder_);
@@ -65,12 +66,24 @@ class Decoder {
     ASSERT_EQ(VPX_CODEC_OK, res) << DecodeError();
   }
 
- protected:
+  void Control(int ctrl_id, const void *arg) {
+    const vpx_codec_err_t res = vpx_codec_control_(&decoder_, ctrl_id, arg);
+    ASSERT_EQ(VPX_CODEC_OK, res) << DecodeError();
+  }
+
   const char *DecodeError() {
     const char *detail = vpx_codec_error_detail(&decoder_);
     return detail ? detail : vpx_codec_error(&decoder_);
   }
 
+ protected:
+  void Init() {
+    const vpx_codec_err_t res = vpx_codec_dec_init(&decoder_,
+                                                   &vpx_codec_vp8_dx_algo,
+                                                   &cfg_, 0);
+    ASSERT_EQ(VPX_CODEC_OK, res) << DecodeError();
+  }
+
   vpx_codec_ctx_t     decoder_;
   vpx_codec_dec_cfg_t cfg_;
   unsigned int        deadline_;
index 56339cae03f6e90be7db31ceb8999da11d58bf19..404aaa2907fae72c86121e13930800966c52e94b 100644 (file)
@@ -160,13 +160,16 @@ void EncoderTest::RunLoop(VideoSource *video) {
 
       while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) {
         again = true;
-
+#if CONFIG_VP8_DECODER
+        vpx_codec_err_t res_dec;
+#endif
         switch (pkt->kind) {
           case VPX_CODEC_CX_FRAME_PKT:
 #if CONFIG_VP8_DECODER
             has_cxdata = true;
-            decoder.DecodeFrame((const uint8_t*)pkt->data.frame.buf,
-                                pkt->data.frame.sz);
+            res_dec = decoder.DecodeFrame((const uint8_t*)pkt->data.frame.buf,
+                                          pkt->data.frame.sz);
+            ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder.DecodeError();
 #endif
             ASSERT_GE(pkt->data.frame.pts, last_pts_);
             last_pts_ = pkt->data.frame.pts;
index e0e6d1ee28e172fb1615846367ec43ca84672343..a1345b876e5b71b64f57557e41d4f1bc6086f80a 100644 (file)
@@ -27,6 +27,7 @@ LIBVPX_TEST_SRCS-$(CONFIG_VP8_DECODER) += decode_test_driver.cc
 LIBVPX_TEST_SRCS-$(CONFIG_VP8_DECODER) += decode_test_driver.h
 LIBVPX_TEST_SRCS-$(CONFIG_VP8_DECODER) += ivf_video_source.h
 LIBVPX_TEST_SRCS-$(CONFIG_VP8_DECODER) += test_vector_test.cc
+
 ##
 ## WHITE BOX TESTS
 ##
@@ -51,6 +52,7 @@ LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += set_roi.cc
 LIBVPX_TEST_SRCS-yes                   += sixtap_predict_test.cc
 LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += subtract_test.cc
 LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += variance_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP8_DECODER) += vp8_decrypt_test.cc
 LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += vp8_fdct4x4_test.cc
 
 endif # VP8
index 4e21be8c53c78dc623bd5f2ec67352548ff476f3..ab19c3412d128f1940bd3c94d315b3b9cb0ec46b 100644 (file)
@@ -26,6 +26,20 @@ extern "C" {
 
 namespace {
 const int num_tests = 10;
+
+void encrypt_buffer(uint8_t *buffer, int size, const uint8_t *key) {
+  for (int i = 0; i < size; ++i) {
+    buffer[i] ^= key[i % 32];
+  }
+}
+
+const uint8_t secret_key[32] = {
+  234,  32,   2,  3,  4, 230,   6,  11,
+    0, 132,  22, 23, 45,  21, 124, 255,
+    0,  43,  52,  3, 23,  63,  99,   7,
+  120,   8, 252, 84,  4,  83,   6,  13
+};
+
 }  // namespace
 
 using libvpx_test::ACMRandom;
@@ -71,7 +85,12 @@ TEST(VP8, TestBitIO) {
         vp8_stop_encode(&bw);
 
         BOOL_DECODER br;
-        vp8dx_start_decode(&br, bw_buffer, buffer_size);
+
+#if CONFIG_DECRYPT
+        encrypt_buffer(bw_buffer, buffer_size, secret_key);
+#endif
+
+        vp8dx_start_decode(&br, bw_buffer, buffer_size, bw_buffer, secret_key);
         bit_rnd.Reset(random_seed);
         for (int i = 0; i < bits_to_test; ++i) {
           if (bit_method == 2) {
diff --git a/test/vp8_decrypt_test.cc b/test/vp8_decrypt_test.cc
new file mode 100644 (file)
index 0000000..ea7b920
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <cstdio>
+#include <cstdlib>
+#include <string>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/decode_test_driver.h"
+#include "test/ivf_video_source.h"
+
+#if CONFIG_DECRYPT
+
+namespace {
+
+const uint8_t decrypt_key[32] = {
+  255, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+}  // namespace
+
+namespace libvpx_test {
+
+TEST(TestDecrypt, NullKey) {
+  vpx_codec_dec_cfg_t cfg = {0};
+  vpx_codec_ctx_t decoder = {0};
+  vpx_codec_err_t res = vpx_codec_dec_init(&decoder, &vpx_codec_vp8_dx_algo,
+                                           &cfg, 0);
+  ASSERT_EQ(VPX_CODEC_OK, res);
+
+  res = vpx_codec_control(&decoder, VP8_SET_DECRYPT_KEY, NULL);
+  ASSERT_EQ(VPX_CODEC_INVALID_PARAM, res);
+}
+
+TEST(TestDecrypt, DecryptWorks) {
+  libvpx_test::IVFVideoSource video("vp80-00-comprehensive-001.ivf");
+  video.Init();
+
+  vpx_codec_dec_cfg_t dec_cfg = {0};
+  Decoder decoder(dec_cfg, 0);
+
+  // Zero decrypt key (by default)
+  video.Begin();
+  vpx_codec_err_t res = decoder.DecodeFrame(video.cxdata(), video.frame_size());
+  ASSERT_EQ(VPX_CODEC_OK, res) << decoder.DecodeError();
+
+  // Non-zero decrypt key
+  video.Next();
+  decoder.Control(VP8_SET_DECRYPT_KEY, decrypt_key);
+  res = decoder.DecodeFrame(video.cxdata(), video.frame_size());
+  ASSERT_NE(VPX_CODEC_OK, res) << decoder.DecodeError();
+}
+
+}  // namespace libvpx_test
+
+#endif  // CONFIG_DECRYPT
index cd6d575557aa32836eb1533723695696ba5a1884..aa7a56a021b13a538fb924f90e15e0e8ccb233e1 100644 (file)
 
 int vp8dx_start_decode(BOOL_DECODER *br,
                        const unsigned char *source,
-                       unsigned int source_sz)
+                       unsigned int source_sz,
+                       const unsigned char *origin,
+                       const unsigned char *key)
 {
     br->user_buffer_end = source+source_sz;
     br->user_buffer     = source;
     br->value    = 0;
     br->count    = -8;
     br->range    = 255;
+    br->origin = origin;
+    br->key = key;
 
     if (source_sz && !source)
         return 1;
@@ -52,7 +56,9 @@ void vp8dx_bool_decoder_fill(BOOL_DECODER *br)
         while(shift >= loop_end)
         {
             count += CHAR_BIT;
-            value |= (VP8_BD_VALUE)*bufptr++ << shift;
+            value |= ((VP8_BD_VALUE)decrypt_byte(bufptr, br->origin,
+                                                 br->key)) << shift;
+            ++bufptr;
             shift -= CHAR_BIT;
         }
     }
index 756821a6e84ad28c37ab45bb8289cbe5d968d9de..46a4dd60ed90c14818a3df694774e40c93992d00 100644 (file)
@@ -28,6 +28,18 @@ typedef size_t VP8_BD_VALUE;
   Even relatively modest values like 100 would work fine.*/
 #define VP8_LOTS_OF_BITS (0x40000000)
 
+static unsigned char decrypt_byte(const unsigned char *ch,
+                                  const unsigned char *origin,
+                                  const unsigned char *key)
+{
+#if CONFIG_DECRYPT
+    const int offset = (int)(ch - origin);
+    return *ch ^ key[offset % 32];  // VP8_DECRYPT_KEY_SIZE
+#else
+    return *ch;
+#endif
+}
+
 typedef struct
 {
     const unsigned char *user_buffer_end;
@@ -35,13 +47,17 @@ typedef struct
     VP8_BD_VALUE         value;
     int                  count;
     unsigned int         range;
+    const unsigned char *origin;
+    const unsigned char *key;
 } BOOL_DECODER;
 
 DECLARE_ALIGNED(16, extern const unsigned char, vp8_norm[256]);
 
 int vp8dx_start_decode(BOOL_DECODER *br,
                        const unsigned char *source,
-                       unsigned int source_sz);
+                       unsigned int source_sz,
+                       const unsigned char *origin,
+                       const unsigned char *key);
 
 void vp8dx_bool_decoder_fill(BOOL_DECODER *br);
 
index 6f8282a6436ea38f2c4fd68ebd2e75056024b538..7060005a96f7ab09713acac060b4e5dd5637ada2 100644 (file)
@@ -893,7 +893,9 @@ static void setup_token_decoder(VP8D_COMP *pbi,
     {
         if (vp8dx_start_decode(bool_decoder,
                                pbi->fragments.ptrs[partition_idx],
-                               pbi->fragments.sizes[partition_idx]))
+                               pbi->fragments.sizes[partition_idx],
+                               pbi->fragments.ptrs[0],
+                               pbi->decrypt_key))
             vpx_internal_error(&pbi->common.error, VPX_CODEC_MEM_ERROR,
                                "Failed to allocate bool decoder %d",
                                partition_idx);
@@ -980,10 +982,11 @@ static void init_frame(VP8D_COMP *pbi)
 
 int vp8_decode_frame(VP8D_COMP *pbi)
 {
-    vp8_reader *const bc = & pbi->mbc[8];
-    VP8_COMMON *const pc = & pbi->common;
-    MACROBLOCKD *const xd  = & pbi->mb;
+    vp8_reader *const bc = &pbi->mbc[8];
+    VP8_COMMON *const pc = &pbi->common;
+    MACROBLOCKD *const xd  = &pbi->mb;
     const unsigned char *data = pbi->fragments.ptrs[0];
+    const unsigned char *const origin = data;
     const unsigned char *data_end =  data + pbi->fragments.sizes[0];
     ptrdiff_t first_partition_length_in_bytes;
 
@@ -1016,13 +1019,21 @@ int vp8_decode_frame(VP8D_COMP *pbi)
     }
     else
     {
-        pc->frame_type = (FRAME_TYPE)(data[0] & 1);
-        pc->version = (data[0] >> 1) & 7;
-        pc->show_frame = (data[0] >> 4) & 1;
+        const unsigned char data0 = decrypt_byte(data + 0, origin,
+                                                 pbi->decrypt_key);
+        const unsigned char data1 = decrypt_byte(data + 1, origin,
+                                                 pbi->decrypt_key);
+        const unsigned char data2 = decrypt_byte(data + 2, origin,
+                                                 pbi->decrypt_key);
+
+        pc->frame_type = (FRAME_TYPE)(data0 & 1);
+        pc->version = (data0 >> 1) & 7;
+        pc->show_frame = (data0 >> 4) & 1;
         first_partition_length_in_bytes =
-            (data[0] | (data[1] << 8) | (data[2] << 16)) >> 5;
+            (data0 | (data1 << 8) | (data2 << 16)) >> 5;
 
-        if (!pbi->ec_active && (data + first_partition_length_in_bytes > data_end
+        if (!pbi->ec_active &&
+            (data + first_partition_length_in_bytes > data_end
             || data + first_partition_length_in_bytes < data))
             vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
                                "Truncated packet or corrupt partition 0 length");
@@ -1040,7 +1051,13 @@ int vp8_decode_frame(VP8D_COMP *pbi)
              */
             if (!pbi->ec_active || data + 3 < data_end)
             {
-                if (data[0] != 0x9d || data[1] != 0x01 || data[2] != 0x2a)
+                const unsigned char data0 = decrypt_byte(data + 0, origin,
+                                                         pbi->decrypt_key);
+                const unsigned char data1 = decrypt_byte(data + 1, origin,
+                                                         pbi->decrypt_key);
+                const unsigned char data2 = decrypt_byte(data + 2, origin,
+                                                         pbi->decrypt_key);
+                if (data0 != 0x9d || data1 != 0x01 || data2 != 0x2a)
                     vpx_internal_error(&pc->error, VPX_CODEC_UNSUP_BITSTREAM,
                                    "Invalid frame sync code");
             }
@@ -1051,10 +1068,19 @@ int vp8_decode_frame(VP8D_COMP *pbi)
              */
             if (!pbi->ec_active || data + 6 < data_end)
             {
-                pc->Width = (data[3] | (data[4] << 8)) & 0x3fff;
-                pc->horiz_scale = data[4] >> 6;
-                pc->Height = (data[5] | (data[6] << 8)) & 0x3fff;
-                pc->vert_scale = data[6] >> 6;
+                const unsigned char data3 = decrypt_byte(data + 3, origin,
+                                                         pbi->decrypt_key);
+                const unsigned char data4 = decrypt_byte(data + 4, origin,
+                                                         pbi->decrypt_key);
+                const unsigned char data5 = decrypt_byte(data + 5, origin,
+                                                         pbi->decrypt_key);
+                const unsigned char data6 = decrypt_byte(data + 6, origin,
+                                                         pbi->decrypt_key);
+
+                pc->Width = (data3 | (data4 << 8)) & 0x3fff;
+                pc->horiz_scale = data4 >> 6;
+                pc->Height = (data5 | (data6 << 8)) & 0x3fff;
+                pc->vert_scale = data6 >> 6;
             }
             data += 7;
 
@@ -1072,7 +1098,11 @@ int vp8_decode_frame(VP8D_COMP *pbi)
 
     init_frame(pbi);
 
-    if (vp8dx_start_decode(bc, data, (unsigned int)(data_end - data)))
+    if (vp8dx_start_decode(bc,
+                           data,
+                           (unsigned int)(data_end - data),
+                           pbi->fragments.ptrs[0],
+                           pbi->decrypt_key))
         vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
                            "Failed to allocate bool decoder 0");
     if (pc->frame_type == KEY_FRAME) {
index 939bc3ecec1b3c3767022e280eec612886ac22b8..c2325ebef826a229b8b005bb5b3fc2297672947c 100644 (file)
@@ -122,6 +122,7 @@ typedef struct VP8D_COMP
     int independent_partitions;
     int frame_corrupt_residual;
 
+    const unsigned char *decrypt_key;
 } VP8D_COMP;
 
 int vp8_decode_frame(VP8D_COMP *cpi);
index 7cda19d32d2eca83c7b16785c52931d4cd621fa6..f3834b063d7410eae3aaa27d6d73d9985a83997a 100644 (file)
@@ -29,6 +29,8 @@
 #define VP8_CAP_ERROR_CONCEALMENT (CONFIG_ERROR_CONCEALMENT ? \
                                     VPX_CODEC_CAP_ERROR_CONCEALMENT : 0)
 
+#define VP8_DECRYPT_KEY_SIZE 32
+
 typedef vpx_codec_stream_info_t  vp8_stream_info_t;
 
 /* Structures for handling memory allocations */
@@ -73,6 +75,7 @@ struct vpx_codec_alg_priv
     int                     dbg_color_b_modes_flag;
     int                     dbg_display_mv_flag;
 #endif
+    unsigned char           decrypt_key[VP8_DECRYPT_KEY_SIZE];
     vpx_image_t             img;
     int                     img_setup;
     struct frame_buffers    yv12_frame_buffers;
@@ -150,6 +153,8 @@ static vpx_codec_err_t vp8_validate_mmaps(const vp8_stream_info_t *si,
     return res;
 }
 
+static const unsigned char fake_decrypt_key[VP8_DECRYPT_KEY_SIZE] = { 0 };
+
 static void vp8_init_ctx(vpx_codec_ctx_t *ctx, const vpx_codec_mmap_t *mmap)
 {
     int i;
@@ -164,6 +169,8 @@ static void vp8_init_ctx(vpx_codec_ctx_t *ctx, const vpx_codec_mmap_t *mmap)
 
     ctx->priv->alg_priv->mmaps[0] = *mmap;
     ctx->priv->alg_priv->si.sz = sizeof(ctx->priv->alg_priv->si);
+    memcpy(ctx->priv->alg_priv->decrypt_key, fake_decrypt_key,
+           VP8_DECRYPT_KEY_SIZE);
     ctx->priv->init_flags = ctx->init_flags;
 
     if (ctx->config.dec)
@@ -262,14 +269,17 @@ static vpx_codec_err_t vp8_destroy(vpx_codec_alg_priv_t *ctx)
     return VPX_CODEC_OK;
 }
 
-static vpx_codec_err_t vp8_peek_si(const uint8_t         *data,
-                                   unsigned int           data_sz,
-                                   vpx_codec_stream_info_t *si)
+static vpx_codec_err_t vp8_peek_si_external(const uint8_t         *data,
+                                            unsigned int           data_sz,
+                                            vpx_codec_stream_info_t *si,
+                                            const unsigned char *decrypt_key)
 {
     vpx_codec_err_t res = VPX_CODEC_OK;
 
     if(data + data_sz <= data)
+    {
         res = VPX_CODEC_INVALID_PARAM;
+    }
     else
     {
         /* Parse uncompresssed part of key frame header.
@@ -278,30 +288,45 @@ static vpx_codec_err_t vp8_peek_si(const uint8_t         *data,
          * 4 bytes:- including image width and height in the lowest 14 bits
          *           of each 2-byte value.
          */
-        si->is_kf = 0;
 
-        if (data_sz >= 10 && !(data[0] & 0x01))  /* I-Frame */
+        const uint8_t data0 = decrypt_byte(data, data, decrypt_key);
+        si->is_kf = 0;
+        if (data_sz >= 10 && !(data0 & 0x01))  /* I-Frame */
         {
-            const uint8_t *c = data + 3;
+            const uint8_t data3 = decrypt_byte(data + 3, data, decrypt_key);
+            const uint8_t data4 = decrypt_byte(data + 4, data, decrypt_key);
+            const uint8_t data5 = decrypt_byte(data + 5, data, decrypt_key);
+            const uint8_t data6 = decrypt_byte(data + 6, data, decrypt_key);
+            const uint8_t data7 = decrypt_byte(data + 7, data, decrypt_key);
+            const uint8_t data8 = decrypt_byte(data + 8, data, decrypt_key);
+            const uint8_t data9 = decrypt_byte(data + 9, data, decrypt_key);
+
             si->is_kf = 1;
 
             /* vet via sync code */
-            if (c[0] != 0x9d || c[1] != 0x01 || c[2] != 0x2a)
+            if (data3 != 0x9d || data4 != 0x01 || data5 != 0x2a)
                 res = VPX_CODEC_UNSUP_BITSTREAM;
 
-            si->w = (c[3] | (c[4] << 8)) & 0x3fff;
-            si->h = (c[5] | (c[6] << 8)) & 0x3fff;
+            si->w = (data6 | (data7 << 8)) & 0x3fff;
+            si->h = (data8 | (data9 << 8)) & 0x3fff;
 
             /*printf("w=%d, h=%d\n", si->w, si->h);*/
             if (!(si->h | si->w))
                 res = VPX_CODEC_UNSUP_BITSTREAM;
         }
         else
+        {
             res = VPX_CODEC_UNSUP_BITSTREAM;
+        }
     }
 
     return res;
+}
 
+static vpx_codec_err_t vp8_peek_si(const uint8_t *data,
+                                   unsigned int data_sz,
+                                   vpx_codec_stream_info_t *si) {
+    return vp8_peek_si_external(data, data_sz, si, fake_decrypt_key);
 }
 
 static vpx_codec_err_t vp8_get_si(vpx_codec_alg_priv_t    *ctx,
@@ -430,8 +455,10 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t  *ctx,
     w = ctx->si.w;
     h = ctx->si.h;
 
-    res = ctx->base.iface->dec.peek_si(ctx->fragments.ptrs[0],
-                                       ctx->fragments.sizes[0], &ctx->si);
+    res = vp8_peek_si_external(ctx->fragments.ptrs[0],
+                               ctx->fragments.sizes[0],
+                               &ctx->si,
+                               ctx->decrypt_key);
 
     if((res == VPX_CODEC_UNSUP_BITSTREAM) && !ctx->si.is_kf)
     {
@@ -505,6 +532,7 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t  *ctx,
             }
 
             res = vp8_create_decoder_instances(&ctx->yv12_frame_buffers, &oxcf);
+            ctx->yv12_frame_buffers.pbi[0]->decrypt_key = ctx->decrypt_key;
         }
 
         ctx->decoder_init = 1;
@@ -926,6 +954,20 @@ static vpx_codec_err_t vp8_get_frame_corrupted(vpx_codec_alg_priv_t *ctx,
 
 }
 
+
+static vpx_codec_err_t vp8_set_decrypt_key(vpx_codec_alg_priv_t *ctx,
+                                           int ctr_id,
+                                           va_list args)
+{
+    const unsigned char *data = va_arg(args, const unsigned char *);
+    if (data == NULL) {
+        return VPX_CODEC_INVALID_PARAM;
+    }
+
+    memcpy(ctx->decrypt_key, data, VP8_DECRYPT_KEY_SIZE);
+    return VPX_CODEC_OK;
+}
+
 vpx_codec_ctrl_fn_map_t vp8_ctf_maps[] =
 {
     {VP8_SET_REFERENCE,             vp8_set_reference},
@@ -938,6 +980,7 @@ vpx_codec_ctrl_fn_map_t vp8_ctf_maps[] =
     {VP8D_GET_LAST_REF_UPDATES,     vp8_get_last_ref_updates},
     {VP8D_GET_FRAME_CORRUPTED,      vp8_get_frame_corrupted},
     {VP8D_GET_LAST_REF_USED,        vp8_get_last_ref_frame},
+    {VP8_SET_DECRYPT_KEY,           vp8_set_decrypt_key},
     { -1, NULL},
 };
 
index e2ec8b2133b5d2512ebae0f998ccf87ec0fa9fa2..ca3d63c8fc1df86a0beefe5d022a7a15239782e8 100644 (file)
@@ -63,6 +63,12 @@ enum vp8_dec_control_id {
    */
   VP8D_GET_LAST_REF_USED,
 
+  /** decryption key to protect encoded data buffer before decoding,
+   *  pointer to 32 byte array which is copied, so the array passed
+   *  does not need to be preserved
+   */
+  VP8_SET_DECRYPT_KEY,
+
   VP8_DECODER_CTRL_ID_MAX
 };
 
@@ -78,6 +84,7 @@ enum vp8_dec_control_id {
 VPX_CTRL_USE_TYPE(VP8D_GET_LAST_REF_UPDATES,   int *)
 VPX_CTRL_USE_TYPE(VP8D_GET_FRAME_CORRUPTED,    int *)
 VPX_CTRL_USE_TYPE(VP8D_GET_LAST_REF_USED,      int *)
+VPX_CTRL_USE_TYPE(VP8_SET_DECRYPT_KEY,         const unsigned char *)
 
 /*! @} - end defgroup vp8_decoder */