Merge "Changing decoder input partition API to input fragments."

This commit is contained in:
John Koleszar
2011-11-04 09:36:27 -07:00
committed by Gerrit Code Review
7 changed files with 221 additions and 232 deletions

View File

@@ -33,7 +33,7 @@ extern "C"
int postprocess; int postprocess;
int max_threads; int max_threads;
int error_concealment; int error_concealment;
int input_partition; int input_fragments;
} VP8D_CONFIG; } VP8D_CONFIG;
typedef enum typedef enum
{ {

View File

@@ -416,49 +416,6 @@ static unsigned int read_partition_size(const unsigned char *cx_size)
return size; return size;
} }
static void setup_token_decoder_partition_input(VP8D_COMP *pbi)
{
vp8_reader *bool_decoder = &pbi->bc2;
int part_idx = 1;
int num_token_partitions;
TOKEN_PARTITION multi_token_partition =
(TOKEN_PARTITION)vp8_read_literal(&pbi->bc, 2);
if (!vp8dx_bool_error(&pbi->bc))
pbi->common.multi_token_partition = multi_token_partition;
num_token_partitions = 1 << pbi->common.multi_token_partition;
if (num_token_partitions + 1 > pbi->num_partitions)
vpx_internal_error(&pbi->common.error, VPX_CODEC_CORRUPT_FRAME,
"Partitions missing");
assert(vp8dx_bool_error(&pbi->bc) ||
multi_token_partition == pbi->common.multi_token_partition);
if (pbi->num_partitions > 2)
{
CHECK_MEM_ERROR(pbi->mbc, vpx_malloc((pbi->num_partitions - 1) *
sizeof(vp8_reader)));
bool_decoder = pbi->mbc;
}
for (; part_idx < pbi->num_partitions; ++part_idx)
{
if (vp8dx_start_decode(bool_decoder,
pbi->partitions[part_idx],
pbi->partition_sizes[part_idx]))
vpx_internal_error(&pbi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to allocate bool decoder %d",
part_idx);
bool_decoder++;
}
#if CONFIG_MULTITHREAD
/* Clamp number of decoder threads */
if (pbi->decoding_thread_count > pbi->num_partitions - 1)
pbi->decoding_thread_count = pbi->num_partitions - 1;
#endif
}
static int read_is_valid(const unsigned char *start, static int read_is_valid(const unsigned char *start,
size_t len, size_t len,
const unsigned char *end) const unsigned char *end)
@@ -466,94 +423,146 @@ static int read_is_valid(const unsigned char *start,
return (start + len > start && start + len <= end); return (start + len > start && start + len <= end);
} }
static unsigned int read_available_partition_size(
VP8D_COMP *pbi,
const unsigned char *token_part_sizes,
const unsigned char *fragment_start,
const unsigned char *first_fragment_end,
const unsigned char *fragment_end,
int i,
int num_part)
{
VP8_COMMON* pc = &pbi->common;
const unsigned char *partition_size_ptr = token_part_sizes + i * 3;
unsigned int partition_size;
ptrdiff_t bytes_left = fragment_end - fragment_start;
/* Calculate the length of this partition. The last partition
* size is implicit. If the partition size can't be read, then
* either use the remaining data in the buffer (for EC mode)
* or throw an error.
*/
if (i < num_part - 1)
{
if (read_is_valid(partition_size_ptr, 3, first_fragment_end))
partition_size = read_partition_size(partition_size_ptr);
else if (pbi->ec_active)
partition_size = bytes_left;
else
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
"Truncated partition size data");
}
else
partition_size = bytes_left;
/* Validate the calculated partition length. If the buffer
* described by the partition can't be fully read, then restrict
* it to the portion that can be (for EC mode) or throw an error.
*/
if (!read_is_valid(fragment_start, partition_size, fragment_end))
{
if (pbi->ec_active)
partition_size = bytes_left;
else
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
"Truncated packet or corrupt partition "
"%d length", i + 1);
}
return partition_size;
}
static void setup_token_decoder(VP8D_COMP *pbi, static void setup_token_decoder(VP8D_COMP *pbi,
const unsigned char *cx_data) const unsigned char* token_part_sizes)
{ {
int num_part; vp8_reader *bool_decoder = &pbi->bc2;
int i; int fragment_idx, partition_idx;
VP8_COMMON *pc = &pbi->common; int num_token_partitions;
const unsigned char *user_data_end = pbi->Source + pbi->source_sz; const unsigned char *first_fragment_end = pbi->fragments[0] +
vp8_reader *bool_decoder; pbi->fragment_sizes[0];
const unsigned char *partition;
/* Parse number of token partitions to use */ TOKEN_PARTITION multi_token_partition =
const TOKEN_PARTITION multi_token_partition =
(TOKEN_PARTITION)vp8_read_literal(&pbi->bc, 2); (TOKEN_PARTITION)vp8_read_literal(&pbi->bc, 2);
/* Only update the multi_token_partition field if we are sure the value if (!vp8dx_bool_error(&pbi->bc))
* is correct. */ pbi->common.multi_token_partition = multi_token_partition;
if (!pbi->ec_active || !vp8dx_bool_error(&pbi->bc)) num_token_partitions = 1 << pbi->common.multi_token_partition;
pc->multi_token_partition = multi_token_partition; if (num_token_partitions > 1)
num_part = 1 << pc->multi_token_partition;
/* Set up pointers to the first partition */
partition = cx_data;
bool_decoder = &pbi->bc2;
if (num_part > 1)
{ {
CHECK_MEM_ERROR(pbi->mbc, vpx_malloc(num_part * sizeof(vp8_reader))); CHECK_MEM_ERROR(pbi->mbc, vpx_malloc(num_token_partitions *
sizeof(vp8_reader)));
bool_decoder = pbi->mbc; bool_decoder = pbi->mbc;
partition += 3 * (num_part - 1);
} }
for (i = 0; i < num_part; i++) /* Check for partitions within the fragments and unpack the fragments
* so that each fragment pointer points to its corresponding partition. */
for (fragment_idx = 0; fragment_idx < pbi->num_fragments; ++fragment_idx)
{ {
const unsigned char *partition_size_ptr = cx_data + i * 3; unsigned int fragment_size = pbi->fragment_sizes[fragment_idx];
ptrdiff_t partition_size, bytes_left; const unsigned char *fragment_end = pbi->fragments[fragment_idx] +
fragment_size;
bytes_left = user_data_end - partition; /* Special case for handling the first partition since we have already
* read its size. */
/* Calculate the length of this partition. The last partition if (fragment_idx == 0)
* size is implicit. If the partition size can't be read, then
* either use the remaining data in the buffer (for EC mode)
* or throw an error.
*/
if (i < num_part - 1)
{ {
if (read_is_valid(partition_size_ptr, 3, user_data_end)) /* Size of first partition + token partition sizes element */
partition_size = read_partition_size(partition_size_ptr); ptrdiff_t ext_first_part_size = token_part_sizes -
else if (pbi->ec_active) pbi->fragments[0] + 3 * (num_token_partitions - 1);
partition_size = bytes_left; fragment_size -= ext_first_part_size;
else if (fragment_size > 0)
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, {
"Truncated partition size data"); pbi->fragment_sizes[0] = ext_first_part_size;
/* The fragment contains an additional partition. Move to
* next. */
fragment_idx++;
pbi->fragments[fragment_idx] = pbi->fragments[0] +
pbi->fragment_sizes[0];
}
} }
else /* Split the chunk into partitions read from the bitstream */
partition_size = bytes_left; while (fragment_size > 0)
/* Validate the calculated partition length. If the buffer
* described by the partition can't be fully read, then restrict
* it to the portion that can be (for EC mode) or throw an error.
*/
if (!read_is_valid(partition, partition_size, user_data_end))
{ {
if (pbi->ec_active) ptrdiff_t partition_size = read_available_partition_size(
partition_size = bytes_left; pbi,
else token_part_sizes,
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, pbi->fragments[fragment_idx],
"Truncated packet or corrupt partition " first_fragment_end,
"%d length", i + 1); fragment_end,
fragment_idx - 1,
num_token_partitions);
pbi->fragment_sizes[fragment_idx] = partition_size;
fragment_size -= partition_size;
assert(fragment_idx <= num_token_partitions);
if (fragment_size > 0)
{
/* The fragment contains an additional partition.
* Move to next. */
fragment_idx++;
pbi->fragments[fragment_idx] =
pbi->fragments[fragment_idx - 1] + partition_size;
}
} }
}
if (vp8dx_start_decode(bool_decoder, partition, partition_size)) pbi->num_fragments = num_token_partitions + 1;
vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate bool decoder %d", i + 1); for (partition_idx = 1; partition_idx < pbi->num_fragments; ++partition_idx)
{
if (vp8dx_start_decode(bool_decoder,
pbi->fragments[partition_idx],
pbi->fragment_sizes[partition_idx]))
vpx_internal_error(&pbi->common.error, VPX_CODEC_MEM_ERROR,
"Failed to allocate bool decoder %d",
partition_idx);
/* Advance to the next partition */
partition += partition_size;
bool_decoder++; bool_decoder++;
} }
#if CONFIG_MULTITHREAD #if CONFIG_MULTITHREAD
/* Clamp number of decoder threads */ /* Clamp number of decoder threads */
if (pbi->decoding_thread_count > num_part - 1) if (pbi->decoding_thread_count > num_token_partitions - 1)
pbi->decoding_thread_count = num_part - 1; pbi->decoding_thread_count = num_token_partitions - 1;
#endif #endif
} }
static void stop_token_decoder(VP8D_COMP *pbi) static void stop_token_decoder(VP8D_COMP *pbi)
{ {
VP8_COMMON *pc = &pbi->common; VP8_COMMON *pc = &pbi->common;
@@ -645,8 +654,8 @@ int vp8_decode_frame(VP8D_COMP *pbi)
vp8_reader *const bc = & pbi->bc; vp8_reader *const bc = & pbi->bc;
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 = (const unsigned char *)pbi->Source; const unsigned char *data = pbi->fragments[0];
const unsigned char *data_end = data + pbi->source_sz; const unsigned char *data_end = data + pbi->fragment_sizes[0];
ptrdiff_t first_partition_length_in_bytes; ptrdiff_t first_partition_length_in_bytes;
int mb_row; int mb_row;
@@ -655,12 +664,6 @@ int vp8_decode_frame(VP8D_COMP *pbi)
int corrupt_tokens = 0; int corrupt_tokens = 0;
int prev_independent_partitions = pbi->independent_partitions; int prev_independent_partitions = pbi->independent_partitions;
if (pbi->input_partition)
{
data = pbi->partitions[0];
data_end = data + pbi->partition_sizes[0];
}
/* start with no corruption of current frame */ /* start with no corruption of current frame */
xd->corrupted = 0; xd->corrupted = 0;
pc->yv12_fb[pc->new_fb_idx].corrupted = 0; pc->yv12_fb[pc->new_fb_idx].corrupted = 0;
@@ -877,14 +880,8 @@ int vp8_decode_frame(VP8D_COMP *pbi)
} }
} }
if (pbi->input_partition) setup_token_decoder(pbi, data + first_partition_length_in_bytes);
{
setup_token_decoder_partition_input(pbi);
}
else
{
setup_token_decoder(pbi, data + first_partition_length_in_bytes);
}
xd->current_bc = &pbi->bc2; xd->current_bc = &pbi->bc2;
/* Read the default quantizers. */ /* Read the default quantizers. */

View File

@@ -108,7 +108,8 @@ VP8D_PTR vp8dx_create_decompressor(VP8D_CONFIG *oxcf)
pbi->decoded_key_frame = 0; pbi->decoded_key_frame = 0;
pbi->input_partition = oxcf->input_partition; pbi->input_fragments = oxcf->input_fragments;
pbi->num_fragments = 0;
/* Independent partitions is activated when a frame updates the /* Independent partitions is activated when a frame updates the
* token probability table to have equal probabilities over the * token probability table to have equal probabilities over the
@@ -319,115 +320,107 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
pbi->common.error.error_code = VPX_CODEC_OK; pbi->common.error.error_code = VPX_CODEC_OK;
if (pbi->input_partition && !(source == NULL && size == 0)) if (pbi->num_fragments == 0)
{ {
/* Store a pointer to this partition and return. We haven't /* New frame, reset fragment pointers and sizes */
vpx_memset(pbi->fragments, 0, sizeof(pbi->fragments));
vpx_memset(pbi->fragment_sizes, 0, sizeof(pbi->fragment_sizes));
}
if (pbi->input_fragments && !(source == NULL && size == 0))
{
/* Store a pointer to this fragment and return. We haven't
* received the complete frame yet, so we will wait with decoding. * received the complete frame yet, so we will wait with decoding.
*/ */
assert(pbi->num_partitions < MAX_PARTITIONS); assert(pbi->num_fragments < MAX_PARTITIONS);
pbi->partitions[pbi->num_partitions] = source; pbi->fragments[pbi->num_fragments] = source;
pbi->partition_sizes[pbi->num_partitions] = size; pbi->fragment_sizes[pbi->num_fragments] = size;
pbi->source_sz += size; pbi->num_fragments++;
pbi->num_partitions++; if (pbi->num_fragments > (1 << EIGHT_PARTITION) + 1)
if (pbi->num_partitions > (1 << EIGHT_PARTITION) + 1)
{ {
pbi->common.error.error_code = VPX_CODEC_UNSUP_BITSTREAM; pbi->common.error.error_code = VPX_CODEC_UNSUP_BITSTREAM;
pbi->common.error.setjmp = 0; pbi->common.error.setjmp = 0;
pbi->num_partitions = 0; pbi->num_fragments = 0;
return -1; return -1;
} }
return 0; return 0;
} }
else
if (!pbi->input_fragments)
{ {
if (!pbi->input_partition) pbi->fragments[0] = source;
pbi->fragment_sizes[0] = size;
pbi->num_fragments = 1;
}
assert(pbi->common.multi_token_partition <= EIGHT_PARTITION);
if (pbi->num_fragments == 0)
{
pbi->num_fragments = 1;
pbi->fragments[0] = NULL;
pbi->fragment_sizes[0] = 0;
}
if (pbi->num_fragments <= 1 && pbi->fragment_sizes[0] == 0)
{
/* This is used to signal that we are missing frames.
* We do not know if the missing frame(s) was supposed to update
* any of the reference buffers, but we act conservative and
* mark only the last buffer as corrupted.
*/
cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
/* If error concealment is disabled we won't signal missing frames
* to the decoder.
*/
if (!pbi->ec_active)
{ {
pbi->Source = source; /* Signal that we have no frame to show. */
pbi->source_sz = size; cm->show_frame = 0;
}
else pbi->num_fragments = 0;
{
assert(pbi->common.multi_token_partition <= EIGHT_PARTITION); /* Nothing more to do. */
if (pbi->num_partitions == 0) return 0;
{
pbi->num_partitions = 1;
pbi->partitions[0] = NULL;
pbi->partition_sizes[0] = 0;
}
while (pbi->num_partitions < (1 << pbi->common.multi_token_partition) + 1)
{
// Reset all missing partitions
pbi->partitions[pbi->num_partitions] =
pbi->partitions[pbi->num_partitions - 1] +
pbi->partition_sizes[pbi->num_partitions - 1];
pbi->partition_sizes[pbi->num_partitions] = 0;
pbi->num_partitions++;
}
} }
}
if (pbi->source_sz == 0) #if HAVE_ARMV7
{ #if CONFIG_RUNTIME_CPU_DETECT
/* This is used to signal that we are missing frames. if (cm->rtcd.flags & HAS_NEON)
* We do not know if the missing frame(s) was supposed to update #endif
* any of the reference buffers, but we act conservative and {
* mark only the last buffer as corrupted. vp8_push_neon(dx_store_reg);
*/ }
cm->yv12_fb[cm->lst_fb_idx].corrupted = 1; #endif
/* If error concealment is disabled we won't signal missing frames to cm->new_fb_idx = get_free_fb (cm);
* the decoder.
*/
if (!pbi->ec_active)
{
/* Signal that we have no frame to show. */
cm->show_frame = 0;
pbi->num_partitions = 0;
/* Nothing more to do. */
return 0;
}
}
if (setjmp(pbi->common.error.jmp))
{
#if HAVE_ARMV7 #if HAVE_ARMV7
#if CONFIG_RUNTIME_CPU_DETECT #if CONFIG_RUNTIME_CPU_DETECT
if (cm->rtcd.flags & HAS_NEON) if (cm->rtcd.flags & HAS_NEON)
#endif #endif
{ {
vp8_push_neon(dx_store_reg); vp8_pop_neon(dx_store_reg);
} }
#endif #endif
pbi->common.error.setjmp = 0;
cm->new_fb_idx = get_free_fb (cm); pbi->num_fragments = 0;
if (setjmp(pbi->common.error.jmp)) /* We do not know if the missing frame(s) was supposed to update
{ * any of the reference buffers, but we act conservative and
#if HAVE_ARMV7 * mark only the last buffer as corrupted.
#if CONFIG_RUNTIME_CPU_DETECT */
if (cm->rtcd.flags & HAS_NEON) cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
#endif
{
vp8_pop_neon(dx_store_reg);
}
#endif
pbi->common.error.setjmp = 0;
pbi->num_partitions = 0; if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
/* We do not know if the missing frame(s) was supposed to update return -1;
* any of the reference buffers, but we act conservative and
* mark only the last buffer as corrupted.
*/
cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
return -1;
}
pbi->common.error.setjmp = 1;
} }
pbi->common.error.setjmp = 1;
retcode = vp8_decode_frame(pbi); retcode = vp8_decode_frame(pbi);
if (retcode < 0) if (retcode < 0)
@@ -442,7 +435,7 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
#endif #endif
pbi->common.error.error_code = VPX_CODEC_ERROR; pbi->common.error.error_code = VPX_CODEC_ERROR;
pbi->common.error.setjmp = 0; pbi->common.error.setjmp = 0;
pbi->num_partitions = 0; pbi->num_fragments = 0;
if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0) if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
cm->fb_idx_ref_cnt[cm->new_fb_idx]--; cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
return retcode; return retcode;
@@ -463,7 +456,7 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
#endif #endif
pbi->common.error.error_code = VPX_CODEC_ERROR; pbi->common.error.error_code = VPX_CODEC_ERROR;
pbi->common.error.setjmp = 0; pbi->common.error.setjmp = 0;
pbi->num_partitions = 0; pbi->num_fragments = 0;
return -1; return -1;
} }
} else } else
@@ -481,7 +474,7 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
#endif #endif
pbi->common.error.error_code = VPX_CODEC_ERROR; pbi->common.error.error_code = VPX_CODEC_ERROR;
pbi->common.error.setjmp = 0; pbi->common.error.setjmp = 0;
pbi->num_partitions = 0; pbi->num_fragments = 0;
return -1; return -1;
} }
@@ -500,7 +493,7 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
/* swap the mode infos to storage for future error concealment */ /* swap the mode infos to storage for future error concealment */
if (pbi->ec_enabled && pbi->common.prev_mi) if (pbi->ec_enabled && pbi->common.prev_mi)
{ {
const MODE_INFO* tmp = pbi->common.prev_mi; MODE_INFO* tmp = pbi->common.prev_mi;
int row, col; int row, col;
pbi->common.prev_mi = pbi->common.mi; pbi->common.prev_mi = pbi->common.mi;
pbi->common.mi = tmp; pbi->common.mi = tmp;
@@ -525,8 +518,7 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
pbi->ready_for_new_data = 0; pbi->ready_for_new_data = 0;
pbi->last_time_stamp = time_stamp; pbi->last_time_stamp = time_stamp;
pbi->num_partitions = 0; pbi->num_fragments = 0;
pbi->source_sz = 0;
#if 0 #if 0
{ {

View File

@@ -54,11 +54,9 @@ typedef struct VP8Decompressor
VP8D_CONFIG oxcf; VP8D_CONFIG oxcf;
const unsigned char *Source; const unsigned char *fragments[MAX_PARTITIONS];
unsigned int source_sz; unsigned int fragment_sizes[MAX_PARTITIONS];
const unsigned char *partitions[MAX_PARTITIONS]; unsigned int num_fragments;
unsigned int partition_sizes[MAX_PARTITIONS];
unsigned int num_partitions;
#if CONFIG_MULTITHREAD #if CONFIG_MULTITHREAD
/* variable for threading */ /* variable for threading */
@@ -112,7 +110,7 @@ typedef struct VP8Decompressor
#endif #endif
int ec_enabled; int ec_enabled;
int ec_active; int ec_active;
int input_partition; int input_fragments;
int decoded_key_frame; int decoded_key_frame;
int independent_partitions; int independent_partitions;
int frame_corrupt_residual; int frame_corrupt_residual;

View File

@@ -398,8 +398,8 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx,
oxcf.max_threads = ctx->cfg.threads; oxcf.max_threads = ctx->cfg.threads;
oxcf.error_concealment = oxcf.error_concealment =
(ctx->base.init_flags & VPX_CODEC_USE_ERROR_CONCEALMENT); (ctx->base.init_flags & VPX_CODEC_USE_ERROR_CONCEALMENT);
oxcf.input_partition = oxcf.input_fragments =
(ctx->base.init_flags & VPX_CODEC_USE_INPUT_PARTITION); (ctx->base.init_flags & VPX_CODEC_USE_INPUT_FRAGMENTS);
optr = vp8dx_create_decompressor(&oxcf); optr = vp8dx_create_decompressor(&oxcf);
@@ -741,7 +741,7 @@ CODEC_INTERFACE(vpx_codec_vp8_dx) =
"WebM Project VP8 Decoder" VERSION_STRING, "WebM Project VP8 Decoder" VERSION_STRING,
VPX_CODEC_INTERNAL_ABI_VERSION, VPX_CODEC_INTERNAL_ABI_VERSION,
VPX_CODEC_CAP_DECODER | VP8_CAP_POSTPROC | VP8_CAP_ERROR_CONCEALMENT | VPX_CODEC_CAP_DECODER | VP8_CAP_POSTPROC | VP8_CAP_ERROR_CONCEALMENT |
VPX_CODEC_CAP_INPUT_PARTITION, VPX_CODEC_CAP_INPUT_FRAGMENTS,
/* vpx_codec_caps_t caps; */ /* vpx_codec_caps_t caps; */
vp8_init, /* vpx_codec_init_fn_t init; */ vp8_init, /* vpx_codec_init_fn_t init; */
vp8_destroy, /* vpx_codec_destroy_fn_t destroy; */ vp8_destroy, /* vpx_codec_destroy_fn_t destroy; */

View File

@@ -39,8 +39,8 @@ vpx_codec_err_t vpx_codec_dec_init_ver(vpx_codec_ctx_t *ctx,
else if ((flags & VPX_CODEC_USE_ERROR_CONCEALMENT) && else if ((flags & VPX_CODEC_USE_ERROR_CONCEALMENT) &&
!(iface->caps & VPX_CODEC_CAP_ERROR_CONCEALMENT)) !(iface->caps & VPX_CODEC_CAP_ERROR_CONCEALMENT))
res = VPX_CODEC_INCAPABLE; res = VPX_CODEC_INCAPABLE;
else if ((flags & VPX_CODEC_USE_INPUT_PARTITION) && else if ((flags & VPX_CODEC_USE_INPUT_FRAGMENTS) &&
!(iface->caps & VPX_CODEC_CAP_INPUT_PARTITION)) !(iface->caps & VPX_CODEC_CAP_INPUT_FRAGMENTS))
res = VPX_CODEC_INCAPABLE; res = VPX_CODEC_INCAPABLE;
else if (!(iface->caps & VPX_CODEC_CAP_DECODER)) else if (!(iface->caps & VPX_CODEC_CAP_DECODER))
res = VPX_CODEC_INCAPABLE; res = VPX_CODEC_INCAPABLE;

View File

@@ -55,8 +55,8 @@ extern "C" {
#define VPX_CODEC_CAP_POSTPROC 0x40000 /**< Can postprocess decoded frame */ #define VPX_CODEC_CAP_POSTPROC 0x40000 /**< Can postprocess decoded frame */
#define VPX_CODEC_CAP_ERROR_CONCEALMENT 0x80000 /**< Can conceal errors due to #define VPX_CODEC_CAP_ERROR_CONCEALMENT 0x80000 /**< Can conceal errors due to
packet loss */ packet loss */
#define VPX_CODEC_CAP_INPUT_PARTITION 0x100000 /**< Can receive encoded frames #define VPX_CODEC_CAP_INPUT_FRAGMENTS 0x100000 /**< Can receive encoded frames
one partition at a time */ one fragment at a time */
/*! \brief Initialization-time Feature Enabling /*! \brief Initialization-time Feature Enabling
* *
@@ -68,9 +68,9 @@ extern "C" {
#define VPX_CODEC_USE_POSTPROC 0x10000 /**< Postprocess decoded frame */ #define VPX_CODEC_USE_POSTPROC 0x10000 /**< Postprocess decoded frame */
#define VPX_CODEC_USE_ERROR_CONCEALMENT 0x20000 /**< Conceal errors in decoded #define VPX_CODEC_USE_ERROR_CONCEALMENT 0x20000 /**< Conceal errors in decoded
frames */ frames */
#define VPX_CODEC_USE_INPUT_PARTITION 0x40000 /**< The input frame should be #define VPX_CODEC_USE_INPUT_FRAGMENTS 0x40000 /**< The input frame should be
passed to the decoder one passed to the decoder one
partition at a time */ fragment at a time */
/*!\brief Stream properties /*!\brief Stream properties
* *
@@ -189,11 +189,13 @@ extern "C" {
* generated, as appropriate. Encoded data \ref MUST be passed in DTS (decode * generated, as appropriate. Encoded data \ref MUST be passed in DTS (decode
* time stamp) order. Frames produced will always be in PTS (presentation * time stamp) order. Frames produced will always be in PTS (presentation
* time stamp) order. * time stamp) order.
* If the decoder is configured with VPX_CODEC_USE_INPUT_PARTITION enabled, * If the decoder is configured with VPX_CODEC_USE_INPUT_FRAGMENTS enabled,
* data and data_sz must contain at most one encoded partition. When no more * data and data_sz can contain a fragment of the encoded frame. Fragment #n
* data is available, this function should be called with NULL as data and 0 * must contain at least partition #n, but can also contain subsequent
* as data_sz. The memory passed to this function must be available until * partitions (#n+1 - #n+i), and if so, fragments #n+1, .., #n+i must be
* the frame has been decoded. * empty. When no more data is available, this function should be called
* with NULL as data and 0 as data_sz. The memory passed to this function
* must be available until the frame has been decoded.
* *
* \param[in] ctx Pointer to this instance's context * \param[in] ctx Pointer to this instance's context
* \param[in] data Pointer to this block of new coded data. If * \param[in] data Pointer to this block of new coded data. If