From 1eb6e683f26b0ef060d3f78b32cbf5665531c76d Mon Sep 17 00:00:00 2001 From: hkuang Date: Fri, 13 Jun 2014 14:14:02 -0700 Subject: [PATCH] Add superframe support for frame parallel decoding. A superframe is a bunch of frames that bundled as one frame. It is mostly used to combine one or more non-displayable frames and one displayable frame. For frame parallel decoding, libvpx decoder will only support decoding one normal frame or a super frame with superframe index. If an application pass a superframe without superframe index or a chunk of displayable frames without superframe index to libvpx decoder, libvpx will not decode it in frame parallel mode. But libvpx decoder still could decode it in serial mode. Change-Id: I04c9f2c828373d64e880a8c7bcade5307015ce35 --- vp9/vp9_dx_iface.c | 93 +++++++++++++++++++++++++++++++++------------- 1 file changed, 67 insertions(+), 26 deletions(-) diff --git a/vp9/vp9_dx_iface.c b/vp9/vp9_dx_iface.c index 24b44774f..99641f415 100644 --- a/vp9/vp9_dx_iface.c +++ b/vp9/vp9_dx_iface.c @@ -356,7 +356,8 @@ static vpx_codec_err_t decoder_decode(vpx_codec_alg_priv_t *ctx, const uint8_t *data, unsigned int data_sz, void *user_priv, long deadline) { const uint8_t *data_start = data; - const uint8_t *const data_end = data + data_sz; + const uint8_t * const data_end = data + data_sz; + vpx_codec_err_t res; uint32_t frame_sizes[8]; int frame_count; @@ -366,40 +367,80 @@ static vpx_codec_err_t decoder_decode(vpx_codec_alg_priv_t *ctx, parse_superframe_index(data, data_sz, frame_sizes, &frame_count, ctx->decrypt_cb, ctx->decrypt_state); - if (frame_count > 0) { - int i; + if (ctx->frame_parallel_decode) { + // Decode in frame parallel mode. When decoding in this mode, the frame + // passed to the decoder must be either a normal frame or a superframe with + // superframe index so the decoder could get each frame's start position + // in the superframe. + if (frame_count > 0) { + int i; - for (i = 0; i < frame_count; ++i) { - const uint8_t *data_start_copy = data_start; - const uint32_t frame_size = frame_sizes[i]; - vpx_codec_err_t res; - if (data_start < data || - frame_size > (uint32_t)(data_end - data_start)) { - ctx->base.err_detail = "Invalid frame size in index"; - return VPX_CODEC_CORRUPT_FRAME; + for (i = 0; i < frame_count; ++i) { + const uint8_t *data_start_copy = data_start; + const uint32_t frame_size = frame_sizes[i]; + vpx_codec_err_t res; + if (data_start < data + || frame_size > (uint32_t) (data_end - data_start)) { + ctx->base.err_detail = "Invalid frame size in index"; + return VPX_CODEC_CORRUPT_FRAME; + } + + res = decode_one(ctx, &data_start_copy, frame_size, user_priv, + deadline); + if (res != VPX_CODEC_OK) + return res; + + data_start += frame_size; } - - res = decode_one(ctx, &data_start_copy, frame_size, user_priv, deadline); + } else { + res = decode_one(ctx, &data_start, data_sz, user_priv, deadline); if (res != VPX_CODEC_OK) return res; - data_start += frame_size; + // Extra data detected after the frame. + if (data_start < data_end - 1) { + ctx->base.err_detail = "Fail to decode frame in parallel mode"; + return VPX_CODEC_INCAPABLE; + } } } else { - while (data_start < data_end) { - const uint32_t frame_size = (uint32_t)(data_end - data_start); - const vpx_codec_err_t res = decode_one(ctx, &data_start, frame_size, - user_priv, deadline); - if (res != VPX_CODEC_OK) - return res; + // Decode in serial mode. + if (frame_count > 0) { + int i; - // Account for suboptimal termination by the encoder. + for (i = 0; i < frame_count; ++i) { + const uint8_t *data_start_copy = data_start; + const uint32_t frame_size = frame_sizes[i]; + vpx_codec_err_t res; + if (data_start < data + || frame_size > (uint32_t) (data_end - data_start)) { + ctx->base.err_detail = "Invalid frame size in index"; + return VPX_CODEC_CORRUPT_FRAME; + } + + res = decode_one(ctx, &data_start_copy, frame_size, user_priv, + deadline); + if (res != VPX_CODEC_OK) + return res; + + data_start += frame_size; + } + } else { while (data_start < data_end) { - const uint8_t marker = read_marker(ctx->decrypt_cb, ctx->decrypt_state, - data_start); - if (marker) - break; - ++data_start; + const uint32_t frame_size = (uint32_t) (data_end - data_start); + const vpx_codec_err_t res = decode_one(ctx, &data_start, frame_size, + user_priv, deadline); + if (res != VPX_CODEC_OK) + return res; + + // Account for suboptimal termination by the encoder. + while (data_start < data_end) { + const uint8_t marker = read_marker(ctx->decrypt_cb, + ctx->decrypt_state, data_start); + if (marker) + break; + ++data_start; + } } } }