Changing decoder input partition API to input fragments.
Adding support for several partitions within one input fragment. This is necessary to fully support all possible packetization combinations in the VP8 RTP profile. Several partitions can be transmitted in the same packet, and they can only be split by reading the partition lengths from the bitstream. Change-Id: If7d7ea331cc78cb7efd74c4a976b720c9a655463
This commit is contained in:
parent
9bf3bc9a72
commit
1427205215
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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. */
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
|
@ -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; */
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user