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
This commit is contained in:
parent
374b21b277
commit
1eb6e683f2
@ -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,
|
const uint8_t *data, unsigned int data_sz,
|
||||||
void *user_priv, long deadline) {
|
void *user_priv, long deadline) {
|
||||||
const uint8_t *data_start = data;
|
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];
|
uint32_t frame_sizes[8];
|
||||||
int frame_count;
|
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,
|
parse_superframe_index(data, data_sz, frame_sizes, &frame_count,
|
||||||
ctx->decrypt_cb, ctx->decrypt_state);
|
ctx->decrypt_cb, ctx->decrypt_state);
|
||||||
|
|
||||||
if (frame_count > 0) {
|
if (ctx->frame_parallel_decode) {
|
||||||
int i;
|
// 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) {
|
for (i = 0; i < frame_count; ++i) {
|
||||||
const uint8_t *data_start_copy = data_start;
|
const uint8_t *data_start_copy = data_start;
|
||||||
const uint32_t frame_size = frame_sizes[i];
|
const uint32_t frame_size = frame_sizes[i];
|
||||||
vpx_codec_err_t res;
|
vpx_codec_err_t res;
|
||||||
if (data_start < data ||
|
if (data_start < data
|
||||||
frame_size > (uint32_t)(data_end - data_start)) {
|
|| frame_size > (uint32_t) (data_end - data_start)) {
|
||||||
ctx->base.err_detail = "Invalid frame size in index";
|
ctx->base.err_detail = "Invalid frame size in index";
|
||||||
return VPX_CODEC_CORRUPT_FRAME;
|
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 {
|
||||||
res = decode_one(ctx, &data_start_copy, frame_size, user_priv, deadline);
|
res = decode_one(ctx, &data_start, data_sz, user_priv, deadline);
|
||||||
if (res != VPX_CODEC_OK)
|
if (res != VPX_CODEC_OK)
|
||||||
return res;
|
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 {
|
} else {
|
||||||
while (data_start < data_end) {
|
// Decode in serial mode.
|
||||||
const uint32_t frame_size = (uint32_t)(data_end - data_start);
|
if (frame_count > 0) {
|
||||||
const vpx_codec_err_t res = decode_one(ctx, &data_start, frame_size,
|
int i;
|
||||||
user_priv, deadline);
|
|
||||||
if (res != VPX_CODEC_OK)
|
|
||||||
return res;
|
|
||||||
|
|
||||||
// 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) {
|
while (data_start < data_end) {
|
||||||
const uint8_t marker = read_marker(ctx->decrypt_cb, ctx->decrypt_state,
|
const uint32_t frame_size = (uint32_t) (data_end - data_start);
|
||||||
data_start);
|
const vpx_codec_err_t res = decode_one(ctx, &data_start, frame_size,
|
||||||
if (marker)
|
user_priv, deadline);
|
||||||
break;
|
if (res != VPX_CODEC_OK)
|
||||||
++data_start;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user