Commit 26cec5c1 authored by Dmitry Kovalev's avatar Dmitry Kovalev

Basic encryption feature for libvpx.

New decoder control paramter VP8_SET_DECRYPT_KEY to set the decryption key.

Change-Id: I6fc1f44d41f74f3b3f702778af1a6f8f5cc9439f
parent 7d855a9f
...@@ -298,6 +298,7 @@ CONFIG_LIST=" ...@@ -298,6 +298,7 @@ CONFIG_LIST="
multi_res_encoding multi_res_encoding
temporal_denoising temporal_denoising
experimental experimental
decrypt
${EXPERIMENT_LIST} ${EXPERIMENT_LIST}
" "
CMDLINE_SELECT=" CMDLINE_SELECT="
...@@ -347,6 +348,7 @@ CMDLINE_SELECT=" ...@@ -347,6 +348,7 @@ CMDLINE_SELECT="
multi_res_encoding multi_res_encoding
temporal_denoising temporal_denoising
experimental experimental
decrypt
" "
process_cmdline() { process_cmdline() {
......
...@@ -14,18 +14,12 @@ ...@@ -14,18 +14,12 @@
namespace libvpx_test { namespace libvpx_test {
#if CONFIG_VP8_DECODER #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; vpx_codec_err_t res_dec;
REGISTER_STATE_CHECK(res_dec = vpx_codec_decode(&decoder_, REGISTER_STATE_CHECK(res_dec = vpx_codec_decode(&decoder_,
cxdata, size, NULL, 0)); cxdata, size, NULL, 0));
ASSERT_EQ(VPX_CODEC_OK, res_dec) << DecodeError(); return res_dec;
} }
void DecoderTest::RunLoop(CompressedVideoSource *video) { void DecoderTest::RunLoop(CompressedVideoSource *video) {
...@@ -34,7 +28,9 @@ void DecoderTest::RunLoop(CompressedVideoSource *video) { ...@@ -34,7 +28,9 @@ void DecoderTest::RunLoop(CompressedVideoSource *video) {
// Decode frames. // Decode frames.
for (video->Begin(); video->cxdata(); video->Next()) { 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(); DxDataIterator dec_iter = decoder.GetDxData();
const vpx_image_t *img = NULL; const vpx_image_t *img = NULL;
......
...@@ -44,13 +44,14 @@ class Decoder { ...@@ -44,13 +44,14 @@ class Decoder {
Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline) Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline)
: cfg_(cfg), deadline_(deadline) { : cfg_(cfg), deadline_(deadline) {
memset(&decoder_, 0, sizeof(decoder_)); memset(&decoder_, 0, sizeof(decoder_));
Init();
} }
~Decoder() { ~Decoder() {
vpx_codec_destroy(&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() { DxDataIterator GetDxData() {
return DxDataIterator(&decoder_); return DxDataIterator(&decoder_);
...@@ -65,12 +66,24 @@ class Decoder { ...@@ -65,12 +66,24 @@ class Decoder {
ASSERT_EQ(VPX_CODEC_OK, res) << DecodeError(); 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 *DecodeError() {
const char *detail = vpx_codec_error_detail(&decoder_); const char *detail = vpx_codec_error_detail(&decoder_);
return detail ? detail : vpx_codec_error(&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_ctx_t decoder_;
vpx_codec_dec_cfg_t cfg_; vpx_codec_dec_cfg_t cfg_;
unsigned int deadline_; unsigned int deadline_;
......
...@@ -160,13 +160,16 @@ void EncoderTest::RunLoop(VideoSource *video) { ...@@ -160,13 +160,16 @@ void EncoderTest::RunLoop(VideoSource *video) {
while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) { while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) {
again = true; again = true;
#if CONFIG_VP8_DECODER
vpx_codec_err_t res_dec;
#endif
switch (pkt->kind) { switch (pkt->kind) {
case VPX_CODEC_CX_FRAME_PKT: case VPX_CODEC_CX_FRAME_PKT:
#if CONFIG_VP8_DECODER #if CONFIG_VP8_DECODER
has_cxdata = true; has_cxdata = true;
decoder.DecodeFrame((const uint8_t*)pkt->data.frame.buf, res_dec = decoder.DecodeFrame((const uint8_t*)pkt->data.frame.buf,
pkt->data.frame.sz); pkt->data.frame.sz);
ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder.DecodeError();
#endif #endif
ASSERT_GE(pkt->data.frame.pts, last_pts_); ASSERT_GE(pkt->data.frame.pts, last_pts_);
last_pts_ = pkt->data.frame.pts; last_pts_ = pkt->data.frame.pts;
......
...@@ -27,6 +27,7 @@ LIBVPX_TEST_SRCS-$(CONFIG_VP8_DECODER) += decode_test_driver.cc ...@@ -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) += decode_test_driver.h
LIBVPX_TEST_SRCS-$(CONFIG_VP8_DECODER) += ivf_video_source.h LIBVPX_TEST_SRCS-$(CONFIG_VP8_DECODER) += ivf_video_source.h
LIBVPX_TEST_SRCS-$(CONFIG_VP8_DECODER) += test_vector_test.cc LIBVPX_TEST_SRCS-$(CONFIG_VP8_DECODER) += test_vector_test.cc
## ##
## WHITE BOX TESTS ## WHITE BOX TESTS
## ##
...@@ -51,6 +52,7 @@ LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += set_roi.cc ...@@ -51,6 +52,7 @@ LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += set_roi.cc
LIBVPX_TEST_SRCS-yes += sixtap_predict_test.cc LIBVPX_TEST_SRCS-yes += sixtap_predict_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += subtract_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_ENCODER) += variance_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_VP8_DECODER) += vp8_decrypt_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += vp8_fdct4x4_test.cc LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += vp8_fdct4x4_test.cc
endif # VP8 endif # VP8
......
...@@ -26,6 +26,20 @@ extern "C" { ...@@ -26,6 +26,20 @@ extern "C" {
namespace { namespace {
const int num_tests = 10; 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 } // namespace
using libvpx_test::ACMRandom; using libvpx_test::ACMRandom;
...@@ -71,7 +85,12 @@ TEST(VP8, TestBitIO) { ...@@ -71,7 +85,12 @@ TEST(VP8, TestBitIO) {
vp8_stop_encode(&bw); vp8_stop_encode(&bw);
BOOL_DECODER br; 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); bit_rnd.Reset(random_seed);
for (int i = 0; i < bits_to_test; ++i) { for (int i = 0; i < bits_to_test; ++i) {
if (bit_method == 2) { if (bit_method == 2) {
......
/*
* 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
...@@ -13,13 +13,17 @@ ...@@ -13,13 +13,17 @@
int vp8dx_start_decode(BOOL_DECODER *br, int vp8dx_start_decode(BOOL_DECODER *br,
const unsigned char *source, 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_end = source+source_sz;
br->user_buffer = source; br->user_buffer = source;
br->value = 0; br->value = 0;
br->count = -8; br->count = -8;
br->range = 255; br->range = 255;
br->origin = origin;
br->key = key;
if (source_sz && !source) if (source_sz && !source)
return 1; return 1;
...@@ -52,7 +56,9 @@ void vp8dx_bool_decoder_fill(BOOL_DECODER *br) ...@@ -52,7 +56,9 @@ void vp8dx_bool_decoder_fill(BOOL_DECODER *br)
while(shift >= loop_end) while(shift >= loop_end)
{ {
count += CHAR_BIT; 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; shift -= CHAR_BIT;
} }
} }
......
...@@ -28,6 +28,18 @@ typedef size_t VP8_BD_VALUE; ...@@ -28,6 +28,18 @@ typedef size_t VP8_BD_VALUE;
Even relatively modest values like 100 would work fine.*/ Even relatively modest values like 100 would work fine.*/
#define VP8_LOTS_OF_BITS (0x40000000) #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 typedef struct
{ {
const unsigned char *user_buffer_end; const unsigned char *user_buffer_end;
...@@ -35,13 +47,17 @@ typedef struct ...@@ -35,13 +47,17 @@ typedef struct
VP8_BD_VALUE value; VP8_BD_VALUE value;
int count; int count;
unsigned int range; unsigned int range;
const unsigned char *origin;
const unsigned char *key;
} BOOL_DECODER; } BOOL_DECODER;
DECLARE_ALIGNED(16, extern const unsigned char, vp8_norm[256]); DECLARE_ALIGNED(16, extern const unsigned char, vp8_norm[256]);
int vp8dx_start_decode(BOOL_DECODER *br, int vp8dx_start_decode(BOOL_DECODER *br,
const unsigned char *source, 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); void vp8dx_bool_decoder_fill(BOOL_DECODER *br);
......
...@@ -893,7 +893,9 @@ static void setup_token_decoder(VP8D_COMP *pbi, ...@@ -893,7 +893,9 @@ static void setup_token_decoder(VP8D_COMP *pbi,
{ {
if (vp8dx_start_decode(bool_decoder, if (vp8dx_start_decode(bool_decoder,
pbi->fragments.ptrs[partition_idx], 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, vpx_internal_error(&pbi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to allocate bool decoder %d", "Failed to allocate bool decoder %d",
partition_idx); partition_idx);
...@@ -980,10 +982,11 @@ static void init_frame(VP8D_COMP *pbi) ...@@ -980,10 +982,11 @@ static void init_frame(VP8D_COMP *pbi)
int vp8_decode_frame(VP8D_COMP *pbi) int vp8_decode_frame(VP8D_COMP *pbi)
{ {
vp8_reader *const bc = & pbi->mbc[8]; vp8_reader *const bc = &pbi->mbc[8];
VP8_COMMON *const pc = & pbi->common; VP8_COMMON *const pc = &pbi->common;
MACROBLOCKD *const xd = & pbi->mb; MACROBLOCKD *const xd = &pbi->mb;
const unsigned char *data = pbi->fragments.ptrs[0]; const unsigned char *data = pbi->fragments.ptrs[0];
const unsigned char *const origin = data;
const unsigned char *data_end = data + pbi->fragments.sizes[0]; const unsigned char *data_end = data + pbi->fragments.sizes[0];
ptrdiff_t first_partition_length_in_bytes; ptrdiff_t first_partition_length_in_bytes;
...@@ -1016,13 +1019,21 @@ int vp8_decode_frame(VP8D_COMP *pbi) ...@@ -1016,13 +1019,21 @@ int vp8_decode_frame(VP8D_COMP *pbi)
} }
else else
{ {
pc->frame_type = (FRAME_TYPE)(data[0] & 1); const unsigned char data0 = decrypt_byte(data + 0, origin,
pc->version = (data[0] >> 1) & 7; pbi->decrypt_key);
pc->show_frame = (data[0] >> 4) & 1; 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 = 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)) || data + first_partition_length_in_bytes < data))
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
"Truncated packet or corrupt partition 0 length"); "Truncated packet or corrupt partition 0 length");
...@@ -1040,7 +1051,13 @@ int vp8_decode_frame(VP8D_COMP *pbi) ...@@ -1040,7 +1051,13 @@ int vp8_decode_frame(VP8D_COMP *pbi)
*/ */
if (!pbi->ec_active || data + 3 < data_end) 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, vpx_internal_error(&pc->error, VPX_CODEC_UNSUP_BITSTREAM,
"Invalid frame sync code"); "Invalid frame sync code");
} }
...@@ -1051,10 +1068,19 @@ int vp8_decode_frame(VP8D_COMP *pbi) ...@@ -1051,10 +1068,19 @@ int vp8_decode_frame(VP8D_COMP *pbi)
*/ */
if (!pbi->ec_active || data + 6 < data_end) if (!pbi->ec_active || data + 6 < data_end)
{ {
pc->Width = (data[3] | (data[4] << 8)) & 0x3fff; const unsigned char data3 = decrypt_byte(data + 3, origin,
pc->horiz_scale = data[4] >> 6; pbi->decrypt_key);
pc->Height = (data[5] | (data[6] << 8)) & 0x3fff; const unsigned char data4 = decrypt_byte(data + 4, origin,
pc->vert_scale = data[6] >> 6; 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; data += 7;
...@@ -1072,7 +1098,11 @@ int vp8_decode_frame(VP8D_COMP *pbi) ...@@ -1072,7 +1098,11 @@ int vp8_decode_frame(VP8D_COMP *pbi)
init_frame(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, vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate bool decoder 0"); "Failed to allocate bool decoder 0");
if (pc->frame_type == KEY_FRAME) { if (pc->frame_type == KEY_FRAME) {
......
...@@ -122,6 +122,7 @@ typedef struct VP8D_COMP ...@@ -122,6 +122,7 @@ typedef struct VP8D_COMP
int independent_partitions; int independent_partitions;
int frame_corrupt_residual; int frame_corrupt_residual;
const unsigned char *decrypt_key;
} VP8D_COMP; } VP8D_COMP;
int vp8_decode_frame(VP8D_COMP *cpi); int vp8_decode_frame(VP8D_COMP *cpi);
......
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#define VP8_CAP_ERROR_CONCEALMENT (CONFIG_ERROR_CONCEALMENT ? \ #define VP8_CAP_ERROR_CONCEALMENT (CONFIG_ERROR_CONCEALMENT ? \
VPX_CODEC_CAP_ERROR_CONCEALMENT : 0) VPX_CODEC_CAP_ERROR_CONCEALMENT : 0)
#define VP8_DECRYPT_KEY_SIZE 32
typedef vpx_codec_stream_info_t vp8_stream_info_t; typedef vpx_codec_stream_info_t vp8_stream_info_t;
/* Structures for handling memory allocations */ /* Structures for handling memory allocations */
...@@ -73,6 +75,7 @@ struct vpx_codec_alg_priv ...@@ -73,6 +75,7 @@ struct vpx_codec_alg_priv
int dbg_color_b_modes_flag; int dbg_color_b_modes_flag;
int dbg_display_mv_flag; int dbg_display_mv_flag;
#endif #endif
unsigned char decrypt_key[VP8_DECRYPT_KEY_SIZE];
vpx_image_t img; vpx_image_t img;
int img_setup; int img_setup;
struct frame_buffers yv12_frame_buffers; struct frame_buffers yv12_frame_buffers;
...@@ -150,6 +153,8 @@ static vpx_codec_err_t vp8_validate_mmaps(const vp8_stream_info_t *si, ...@@ -150,6 +153,8 @@ static vpx_codec_err_t vp8_validate_mmaps(const vp8_stream_info_t *si,
return res; 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) static void vp8_init_ctx(vpx_codec_ctx_t *ctx, const vpx_codec_mmap_t *mmap)
{ {
int i; int i;
...@@ -164,6 +169,8 @@ static void vp8_init_ctx(vpx_codec_ctx_t *ctx, const vpx_codec_mmap_t *mmap) ...@@ -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->mmaps[0] = *mmap;
ctx->priv->alg_priv->si.sz = sizeof(ctx->priv->alg_priv->si); 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; ctx->priv->init_flags = ctx->init_flags;
if (ctx->config.dec) if (ctx->config.dec)
...@@ -262,14 +269,17 @@ static vpx_codec_err_t vp8_destroy(vpx_codec_alg_priv_t *ctx) ...@@ -262,14 +269,17 @@ static vpx_codec_err_t vp8_destroy(vpx_codec_alg_priv_t *ctx)
return VPX_CODEC_OK; return VPX_CODEC_OK;
} }
static vpx_codec_err_t vp8_peek_si(const uint8_t *data, static vpx_codec_err_t vp8_peek_si_external(const uint8_t *data,
unsigned int data_sz, unsigned int data_sz,
vpx_codec_stream_info_t *si) vpx_codec_stream_info_t *si,
const unsigned char *decrypt_key)
{ {
vpx_codec_err_t res = VPX_CODEC_OK; vpx_codec_err_t res = VPX_CODEC_OK;
if(data + data_sz <= data) if(data + data_sz <= data)
{
res = VPX_CODEC_INVALID_PARAM; res = VPX_CODEC_INVALID_PARAM;
}
else else
{ {
/* Parse uncompresssed part of key frame header. /* Parse uncompresssed part of key frame header.
...@@ -278,30 +288,45 @@ static vpx_codec_err_t vp8_peek_si(const uint8_t *data, ...@@ -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 * 4 bytes:- including image width and height in the lowest 14 bits
* of each 2-byte value. * 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; si->is_kf = 1;
/* vet via sync code */ /* 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; res = VPX_CODEC_UNSUP_BITSTREAM;
si->w = (c[3] | (c[4] << 8)) & 0x3fff; si->w = (data6 | (data7 << 8)) & 0x3fff;
si->h = (c[5] | (c[6] << 8)) & 0x3fff; si->h = (data8 | (data9 << 8)) & 0x3fff;
/*printf("w=%d, h=%d\n", si->w, si->h);*/ /*printf("w=%d, h=%d\n", si->w, si->h);*/
if (!(si->h | si->w)) if (!(si->h | si->w))
res = VPX_CODEC_UNSUP_BITSTREAM; res = VPX_CODEC_UNSUP_BITSTREAM;
} }
else else
{
res = VPX_CODEC_UNSUP_BITSTREAM; res = VPX_CODEC_UNSUP_BITSTREAM;
}
} }
return res; 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, 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, ...@@ -430,8 +455,10 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx,
w = ctx->si.w; w = ctx->si.w;
h = ctx->si.h; h = ctx->si.h;
res = ctx->base.iface->dec.peek_si(ctx->fragments.ptrs[0], res = vp8_peek_si_external(ctx->fragments.ptrs[0],
ctx->fragments.sizes[0], &ctx->si); ctx->fragments.sizes[0],
&ctx->si,
ctx->decrypt_key);
if((res == VPX_CODEC_UNSUP_BITSTREAM) && !ctx->si.is_kf) 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, ...@@ -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); 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; ctx->decoder_init = 1;
...@@ -926,6 +954,20 @@ static vpx_codec_err_t vp8_get_frame_corrupted(vpx_codec_alg_priv_t *ctx, ...@@ -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;