diff options
Diffstat (limited to 'vp9/vp9_dx_iface.c')
-rw-r--r-- | vp9/vp9_dx_iface.c | 117 |
1 files changed, 94 insertions, 23 deletions
diff --git a/vp9/vp9_dx_iface.c b/vp9/vp9_dx_iface.c index 1cd3b03d2..06b482305 100644 --- a/vp9/vp9_dx_iface.c +++ b/vp9/vp9_dx_iface.c @@ -43,6 +43,8 @@ struct vpx_codec_alg_priv { int dbg_color_b_modes_flag; int dbg_display_mv_flag; #endif + vpx_decrypt_cb decrypt_cb; + void *decrypt_state; vpx_image_t img; int img_setup; int img_avail; @@ -94,9 +96,13 @@ static vpx_codec_err_t decoder_destroy(vpx_codec_alg_priv_t *ctx) { return VPX_CODEC_OK; } -static vpx_codec_err_t decoder_peek_si(const uint8_t *data, - unsigned int data_sz, - vpx_codec_stream_info_t *si) { +static vpx_codec_err_t decoder_peek_si_internal(const uint8_t *data, + unsigned int data_sz, + vpx_codec_stream_info_t *si, + vpx_decrypt_cb decrypt_cb, + void *decrypt_state) { + uint8_t clear_buffer[9]; + if (data_sz <= 8) return VPX_CODEC_UNSUP_BITSTREAM; @@ -106,6 +112,12 @@ static vpx_codec_err_t decoder_peek_si(const uint8_t *data, si->is_kf = 0; si->w = si->h = 0; + if (decrypt_cb) { + data_sz = MIN(sizeof(clear_buffer), data_sz); + decrypt_cb(decrypt_state, data, clear_buffer, data_sz); + data = clear_buffer; + } + { struct vp9_read_bit_buffer rb = { data, data + data_sz, 0, NULL, NULL }; const int frame_marker = vp9_rb_read_literal(&rb, 2); @@ -159,6 +171,12 @@ static vpx_codec_err_t decoder_peek_si(const uint8_t *data, return VPX_CODEC_OK; } +static vpx_codec_err_t decoder_peek_si(const uint8_t *data, + unsigned int data_sz, + vpx_codec_stream_info_t *si) { + return decoder_peek_si_internal(data, data_sz, si, NULL, NULL); +} + static vpx_codec_err_t decoder_get_si(vpx_codec_alg_priv_t *ctx, vpx_codec_stream_info_t *si) { const size_t sz = (si->sz >= sizeof(vp9_stream_info_t)) @@ -264,7 +282,8 @@ static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx, // of the heap. if (!ctx->si.h) { const vpx_codec_err_t res = - ctx->base.iface->dec.peek_si(*data, data_sz, &ctx->si); + decoder_peek_si_internal(*data, data_sz, &ctx->si, ctx->decrypt_cb, + ctx->decrypt_state); if (res != VPX_CODEC_OK) return res; } @@ -278,6 +297,11 @@ static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx, ctx->decoder_init = 1; } + // Set these even if already initialized. The caller may have changed the + // decrypt config between frames. + ctx->pbi->decrypt_cb = ctx->decrypt_cb; + ctx->pbi->decrypt_state = ctx->decrypt_state; + cm = &ctx->pbi->common; if (vp9_receive_compressed_data(ctx->pbi, data_sz, data, deadline)) @@ -296,12 +320,25 @@ static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx, return VPX_CODEC_OK; } +static INLINE uint8_t read_marker(vpx_decrypt_cb decrypt_cb, + void *decrypt_state, + const uint8_t *data) { + if (decrypt_cb) { + uint8_t marker; + decrypt_cb(decrypt_state, data, &marker, 1); + return marker; + } + return *data; +} + static void parse_superframe_index(const uint8_t *data, size_t data_sz, - uint32_t sizes[8], int *count) { + uint32_t sizes[8], int *count, + vpx_decrypt_cb decrypt_cb, + void *decrypt_state) { uint8_t marker; assert(data_sz); - marker = data[data_sz - 1]; + marker = read_marker(decrypt_cb, decrypt_state, data + data_sz - 1); *count = 0; if ((marker & 0xe0) == 0xc0) { @@ -309,11 +346,22 @@ static void parse_superframe_index(const uint8_t *data, size_t data_sz, const uint32_t mag = ((marker >> 3) & 0x3) + 1; const size_t index_sz = 2 + mag * frames; - if (data_sz >= index_sz && data[data_sz - index_sz] == marker) { + uint8_t marker2 = read_marker(decrypt_cb, decrypt_state, + data + data_sz - index_sz); + + if (data_sz >= index_sz && marker2 == marker) { // found a valid superframe index uint32_t i, j; const uint8_t *x = &data[data_sz - index_sz + 1]; + // frames has a maximum of 8 and mag has a maximum of 4. + uint8_t clear_buffer[32]; + assert(sizeof(clear_buffer) >= frames * mag); + if (decrypt_cb) { + decrypt_cb(decrypt_state, x, clear_buffer, frames * mag); + x = clear_buffer; + } + for (i = 0; i < frames; i++) { uint32_t this_sz = 0; @@ -339,23 +387,31 @@ static vpx_codec_err_t decoder_decode(vpx_codec_alg_priv_t *ctx, if (data == NULL || data_sz == 0) return VPX_CODEC_INVALID_PARAM; - parse_superframe_index(data, data_sz, sizes, &frames_this_pts); + parse_superframe_index(data, data_sz, sizes, &frames_this_pts, + ctx->decrypt_cb, ctx->decrypt_state); do { - // Skip over the superframe index, if present - if (data_sz && (*data_start & 0xe0) == 0xc0) { - const uint8_t marker = *data_start; - const uint32_t frames = (marker & 0x7) + 1; - const uint32_t mag = ((marker >> 3) & 0x3) + 1; - const uint32_t index_sz = 2 + mag * frames; - - if (data_sz >= index_sz && data_start[index_sz - 1] == marker) { - data_start += index_sz; - data_sz -= index_sz; - if (data_start < data_end) - continue; - else - break; + if (data_sz) { + uint8_t marker = read_marker(ctx->decrypt_cb, ctx->decrypt_state, + data_start); + // Skip over the superframe index, if present + if ((marker & 0xe0) == 0xc0) { + const uint32_t frames = (marker & 0x7) + 1; + const uint32_t mag = ((marker >> 3) & 0x3) + 1; + const uint32_t index_sz = 2 + mag * frames; + + if (data_sz >= index_sz) { + uint8_t marker2 = read_marker(ctx->decrypt_cb, ctx->decrypt_state, + data_start + index_sz - 1); + if (marker2 == marker) { + data_start += index_sz; + data_sz -= index_sz; + if (data_start < data_end) + continue; + else + break; + } + } } } @@ -381,8 +437,13 @@ static vpx_codec_err_t decoder_decode(vpx_codec_alg_priv_t *ctx, break; // Account for suboptimal termination by the encoder. - while (data_start < data_end && *data_start == 0) + while (data_start < data_end) { + uint8_t marker3 = read_marker(ctx->decrypt_cb, ctx->decrypt_state, + data_start); + if (marker3) + break; data_start++; + } data_sz = (unsigned int)(data_end - data_start); } while (data_start < data_end); @@ -565,6 +626,15 @@ static vpx_codec_err_t ctrl_set_invert_tile_order(vpx_codec_alg_priv_t *ctx, return VPX_CODEC_OK; } +static vpx_codec_err_t ctrl_set_decryptor(vpx_codec_alg_priv_t *ctx, + int ctrl_id, + va_list args) { + vpx_decrypt_init *init = va_arg(args, vpx_decrypt_init *); + ctx->decrypt_cb = init ? init->decrypt_cb : NULL; + ctx->decrypt_state = init ? init->decrypt_state : NULL; + return VPX_CODEC_OK; +} + static vpx_codec_ctrl_fn_map_t decoder_ctrl_maps[] = { {VP8_COPY_REFERENCE, ctrl_copy_reference}, @@ -576,6 +646,7 @@ static vpx_codec_ctrl_fn_map_t decoder_ctrl_maps[] = { {VP8_SET_DBG_COLOR_B_MODES, ctrl_set_dbg_options}, {VP8_SET_DBG_DISPLAY_MV, ctrl_set_dbg_options}, {VP9_INVERT_TILE_DECODE_ORDER, ctrl_set_invert_tile_order}, + {VPXD_SET_DECRYPTOR, ctrl_set_decryptor}, // Getters {VP8D_GET_LAST_REF_UPDATES, ctrl_get_last_ref_updates}, |