From: Dmitry Kovalev Date: Sat, 16 Mar 2013 01:21:55 +0000 (-0700) Subject: Basic encryption feature for libvpx. X-Git-Tag: v1.3.0~1162^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=26cec5c13f1d9f2911e903ee5089a052adea86f0;p=libvpx Basic encryption feature for libvpx. New decoder control paramter VP8_SET_DECRYPT_KEY to set the decryption key. Change-Id: I6fc1f44d41f74f3b3f702778af1a6f8f5cc9439f --- diff --git a/configure b/configure index 89a1eb11e..ad33c9c1c 100755 --- 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() { diff --git a/test/decode_test_driver.cc b/test/decode_test_driver.cc index 84afe7f84..0db48e4a7 100644 --- a/test/decode_test_driver.cc +++ b/test/decode_test_driver.cc @@ -14,18 +14,12 @@ 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; diff --git a/test/decode_test_driver.h b/test/decode_test_driver.h index 6408bee01..7d31a0895 100644 --- a/test/decode_test_driver.h +++ b/test/decode_test_driver.h @@ -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_; diff --git a/test/encode_test_driver.cc b/test/encode_test_driver.cc index 56339cae0..404aaa290 100644 --- a/test/encode_test_driver.cc +++ b/test/encode_test_driver.cc @@ -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; diff --git a/test/test.mk b/test/test.mk index e0e6d1ee2..a1345b876 100644 --- a/test/test.mk +++ b/test/test.mk @@ -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 diff --git a/test/vp8_boolcoder_test.cc b/test/vp8_boolcoder_test.cc index 4e21be8c5..ab19c3412 100644 --- a/test/vp8_boolcoder_test.cc +++ b/test/vp8_boolcoder_test.cc @@ -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 index 000000000..ea7b92049 --- /dev/null +++ b/test/vp8_decrypt_test.cc @@ -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 +#include +#include +#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 diff --git a/vp8/decoder/dboolhuff.c b/vp8/decoder/dboolhuff.c index cd6d57555..aa7a56a02 100644 --- a/vp8/decoder/dboolhuff.c +++ b/vp8/decoder/dboolhuff.c @@ -13,13 +13,17 @@ 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; } } diff --git a/vp8/decoder/dboolhuff.h b/vp8/decoder/dboolhuff.h index 756821a6e..46a4dd60e 100644 --- a/vp8/decoder/dboolhuff.h +++ b/vp8/decoder/dboolhuff.h @@ -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); diff --git a/vp8/decoder/decodframe.c b/vp8/decoder/decodframe.c index 6f8282a64..7060005a9 100644 --- a/vp8/decoder/decodframe.c +++ b/vp8/decoder/decodframe.c @@ -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) { diff --git a/vp8/decoder/onyxd_int.h b/vp8/decoder/onyxd_int.h index 939bc3ece..c2325ebef 100644 --- a/vp8/decoder/onyxd_int.h +++ b/vp8/decoder/onyxd_int.h @@ -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); diff --git a/vp8/vp8_dx_iface.c b/vp8/vp8_dx_iface.c index 7cda19d32..f3834b063 100644 --- a/vp8/vp8_dx_iface.c +++ b/vp8/vp8_dx_iface.c @@ -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}, }; diff --git a/vpx/vp8dx.h b/vpx/vp8dx.h index e2ec8b213..ca3d63c8f 100644 --- a/vpx/vp8dx.h +++ b/vpx/vp8dx.h @@ -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 */