Update libaom to rev b25610052a1398032320008d69b51d2da94f5928

This commit is contained in:
trav90 2018-10-19 23:00:02 -05:00 • committed by Roy Tam
commit 3d109dd4fc
240 changed files with 16977 additions and 6139 deletions

File diff suppressed because it is too large Load diff

View file

@ -18,12 +18,13 @@ extern "C" {
struct AV1Decoder;
struct aom_read_bit_buffer;
struct ThreadData;
// Reads the middle part of the sequence header OBU (from
// frame_width_bits_minus_1 to enable_restoration) into cm->seq_params (a
// SequenceHeader). Reports errors by calling rb->error_handler() or
// aom_internal_error().
void read_sequence_header(AV1_COMMON *cm, struct aom_read_bit_buffer *rb);
// frame_width_bits_minus_1 to enable_restoration) into seq_params.
// Reports errors by calling rb->error_handler() or aom_internal_error().
void av1_read_sequence_header(AV1_COMMON *cm, struct aom_read_bit_buffer *rb,
SequenceHeader *seq_params);
void av1_read_frame_size(struct aom_read_bit_buffer *rb, int num_bits_width,
int num_bits_height, int *width, int *height);
@ -34,11 +35,14 @@ BITSTREAM_PROFILE av1_read_profile(struct aom_read_bit_buffer *rb);
int av1_check_trailing_bits(struct AV1Decoder *pbi,
struct aom_read_bit_buffer *rb);
int av1_decode_frame_headers_and_setup(struct AV1Decoder *pbi,
struct aom_read_bit_buffer *rb,
const uint8_t *data,
const uint8_t **p_data_end,
int trailing_bits_present);
// On success, returns the frame header size. On failure, calls
// aom_internal_error and does not return.
// TODO(wtc): Figure out and document the p_data_end parameter.
uint32_t av1_decode_frame_headers_and_setup(struct AV1Decoder *pbi,
struct aom_read_bit_buffer *rb,
const uint8_t *data,
const uint8_t **p_data_end,
int trailing_bits_present);
void av1_decode_tg_tiles_and_wrapup(struct AV1Decoder *pbi, const uint8_t *data,
const uint8_t *data_end,
@ -47,8 +51,9 @@ void av1_decode_tg_tiles_and_wrapup(struct AV1Decoder *pbi, const uint8_t *data,
// Implements the color_config() function in the spec. Reports errors by
// calling rb->error_handler() or aom_internal_error().
void av1_read_color_config(AV1_COMMON *cm, struct aom_read_bit_buffer *rb,
int allow_lowbitdepth);
void av1_read_color_config(struct aom_read_bit_buffer *rb,
int allow_lowbitdepth, SequenceHeader *seq_params,
struct aom_internal_error_info *error_info);
// Implements the timing_info() function in the spec. Reports errors by calling
// rb->error_handler().
@ -69,7 +74,7 @@ struct aom_read_bit_buffer *av1_init_read_bit_buffer(
struct AV1Decoder *pbi, struct aom_read_bit_buffer *rb, const uint8_t *data,
const uint8_t *data_end);
void av1_free_mc_tmp_buf(void *td, int use_highbd);
void av1_free_mc_tmp_buf(struct ThreadData *thread_data, int use_highbd);
void av1_set_single_tile_decoding_mode(AV1_COMMON *const cm);

View file

@ -290,7 +290,7 @@ static int read_segment_id(AV1_COMMON *const cm, const MACROBLOCKD *const xd,
av1_neg_deinterleave(coded_id, pred, seg->last_active_segid + 1);
if (segment_id < 0 || segment_id > seg->last_active_segid) {
aom_internal_error(&cm->error, AOM_CODEC_CORRUPT_FRAME,
aom_internal_error(xd->error_info, AOM_CODEC_CORRUPT_FRAME,
"Corrupted segment_ids");
}
return segment_id;
@ -573,7 +573,7 @@ static void read_palette_mode_info(AV1_COMMON *const cm, MACROBLOCKD *const xd,
aom_read_symbol(r, xd->tile_ctx->palette_y_size_cdf[bsize_ctx],
PALETTE_SIZES, ACCT_STR) +
2;
read_palette_colors_y(xd, cm->bit_depth, pmi, r);
read_palette_colors_y(xd, cm->seq_params.bit_depth, pmi, r);
}
}
if (num_planes > 1 && mbmi->uv_mode == UV_DC_PRED &&
@ -587,7 +587,7 @@ static void read_palette_mode_info(AV1_COMMON *const cm, MACROBLOCKD *const xd,
aom_read_symbol(r, xd->tile_ctx->palette_uv_size_cdf[bsize_ctx],
PALETTE_SIZES, ACCT_STR) +
2;
read_palette_colors_uv(xd, cm->bit_depth, pmi, r);
read_palette_colors_uv(xd, cm->seq_params.bit_depth, pmi, r);
}
}
}
@ -1299,7 +1299,7 @@ static void read_inter_block_mode_info(AV1Decoder *const pbi,
}
if (is_compound != is_inter_compound_mode(mbmi->mode)) {
aom_internal_error(&cm->error, AOM_CODEC_CORRUPT_FRAME,
aom_internal_error(xd->error_info, AOM_CODEC_CORRUPT_FRAME,
"Prediction mode %d invalid with ref frame %d %d",
mbmi->mode, mbmi->ref_frame[0], mbmi->ref_frame[1]);
}
@ -1480,8 +1480,9 @@ static void read_inter_block_mode_info(AV1Decoder *const pbi,
}
}
xd->cfl.is_chroma_reference = is_chroma_reference(
mi_row, mi_col, bsize, cm->subsampling_x, cm->subsampling_y);
xd->cfl.is_chroma_reference =
is_chroma_reference(mi_row, mi_col, bsize, cm->seq_params.subsampling_x,
cm->seq_params.subsampling_y);
xd->cfl.store_y = store_cfl_required(cm, xd);
#if DEC_MISMATCH_DEBUG

View file

@ -71,6 +71,7 @@ static void dec_free_mi(AV1_COMMON *cm) {
cm->mip = NULL;
aom_free(cm->mi_grid_base);
cm->mi_grid_base = NULL;
cm->mi_alloc_size = 0;
}
AV1Decoder *av1_decoder_create(BufferPool *const pool) {
@ -81,6 +82,9 @@ AV1Decoder *av1_decoder_create(BufferPool *const pool) {
av1_zero(*pbi);
// The jmp_buf is valid only for the duration of the function that calls
// setjmp(). Therefore, this function must reset the 'setjmp' field to 0
// before it returns.
if (setjmp(cm->error.jmp)) {
cm->error.setjmp = 0;
av1_decoder_remove(pbi);
@ -98,7 +102,7 @@ AV1Decoder *av1_decoder_create(BufferPool *const pool) {
memset(cm->frame_contexts, 0, FRAME_CONTEXTS * sizeof(*cm->frame_contexts));
pbi->need_resync = 1;
once(initialize_dec);
aom_once(initialize_dec);
// Initialize the references to not point to any frame buffers.
memset(&cm->ref_frame_map, -1, sizeof(cm->ref_frame_map));
@ -108,7 +112,7 @@ AV1Decoder *av1_decoder_create(BufferPool *const pool) {
pbi->decoding_first_frame = 1;
pbi->common.buffer_pool = pool;
cm->bit_depth = AOM_BITS_8;
cm->seq_params.bit_depth = AOM_BITS_8;
cm->dequant_bit_depth = AOM_BITS_8;
cm->alloc_mi = av1_dec_alloc_mi;
@ -146,6 +150,12 @@ void av1_dealloc_dec_jobs(struct AV1DecTileMTData *tile_mt_info) {
}
}
void av1_dec_free_cb_buf(AV1Decoder *pbi) {
aom_free(pbi->cb_buffer_base);
pbi->cb_buffer_base = NULL;
pbi->cb_buffer_alloc_size = 0;
}
void av1_decoder_remove(AV1Decoder *pbi) {
int i;
@ -161,7 +171,7 @@ void av1_decoder_remove(AV1Decoder *pbi) {
if (pbi->thread_data) {
for (int worker_idx = 0; worker_idx < pbi->max_threads - 1; worker_idx++) {
DecWorkerData *const thread_data = pbi->thread_data + worker_idx;
const int use_highbd = pbi->common.use_highbitdepth ? 1 : 0;
const int use_highbd = pbi->common.seq_params.use_highbitdepth ? 1 : 0;
av1_free_mc_tmp_buf(thread_data->td, use_highbd);
aom_free(thread_data->td);
}
@ -172,6 +182,20 @@ void av1_decoder_remove(AV1Decoder *pbi) {
AVxWorker *const worker = &pbi->tile_workers[i];
aom_get_worker_interface()->end(worker);
}
#if CONFIG_MULTITHREAD
if (pbi->row_mt_mutex_ != NULL) {
pthread_mutex_destroy(pbi->row_mt_mutex_);
aom_free(pbi->row_mt_mutex_);
}
if (pbi->row_mt_cond_ != NULL) {
pthread_cond_destroy(pbi->row_mt_cond_);
aom_free(pbi->row_mt_cond_);
}
#endif
for (i = 0; i < pbi->allocated_tiles; i++) {
TileDataDec *const tile_data = pbi->tile_data + i;
av1_dec_row_mt_dealloc(&tile_data->dec_row_mt_sync);
}
aom_free(pbi->tile_data);
aom_free(pbi->tile_workers);
@ -181,10 +205,11 @@ void av1_decoder_remove(AV1Decoder *pbi) {
av1_dealloc_dec_jobs(&pbi->tile_mt_info);
}
av1_dec_free_cb_buf(pbi);
#if CONFIG_ACCOUNTING
aom_accounting_clear(&pbi->accounting);
#endif
const int use_highbd = pbi->common.use_highbitdepth ? 1 : 0;
const int use_highbd = pbi->common.seq_params.use_highbitdepth ? 1 : 0;
av1_free_mc_tmp_buf(&pbi->td, use_highbd);
aom_free(pbi);
@ -279,7 +304,7 @@ aom_codec_err_t av1_set_reference_dec(AV1_COMMON *cm, int idx,
ref_buf->y_buffer = sd->y_buffer;
ref_buf->u_buffer = sd->u_buffer;
ref_buf->v_buffer = sd->v_buffer;
ref_buf->use_external_refernce_buffers = 1;
ref_buf->use_external_reference_buffers = 1;
}
}
@ -414,7 +439,10 @@ int av1_receive_compressed_data(AV1Decoder *pbi, size_t size,
// Find a free frame buffer. Return error if can not find any.
cm->new_fb_idx = get_free_fb(cm);
if (cm->new_fb_idx == INVALID_IDX) return AOM_CODEC_MEM_ERROR;
if (cm->new_fb_idx == INVALID_IDX) {
cm->error.error_code = AOM_CODEC_MEM_ERROR;
return 1;
}
// Assign a MV array to the frame buffer.
cm->cur_frame = &pool->frame_bufs[cm->new_fb_idx];
@ -423,6 +451,9 @@ int av1_receive_compressed_data(AV1Decoder *pbi, size_t size,
pbi->cur_buf = &frame_bufs[cm->new_fb_idx];
// The jmp_buf is valid only for the duration of the function that calls
// setjmp(). Therefore, this function must reset the 'setjmp' field to 0
// before it returns.
if (setjmp(cm->error.jmp)) {
const AVxWorkerInterface *const winterface = aom_get_worker_interface();
int i;
@ -474,7 +505,13 @@ int av1_receive_compressed_data(AV1Decoder *pbi, size_t size,
int frame_decoded =
aom_decode_frame_from_obus(pbi, source, source + size, psource);
if (cm->error.error_code != AOM_CODEC_OK) return 1;
if (cm->error.error_code != AOM_CODEC_OK) {
lock_buffer_pool(pool);
decrease_ref_count(cm->new_fb_idx, frame_bufs, pool);
unlock_buffer_pool(pool);
cm->error.setjmp = 0;
return 1;
}
#if TXCOEFF_TIMER
cm->cum_txcoeff_timer += cm->txcoeff_timer;
@ -493,7 +530,10 @@ int av1_receive_compressed_data(AV1Decoder *pbi, size_t size,
pbi->decoding_first_frame = 0;
}
if (cm->error.error_code != AOM_CODEC_OK) return 1;
if (cm->error.error_code != AOM_CODEC_OK) {
cm->error.setjmp = 0;
return 1;
}
aom_clear_system_state();

View file

@ -33,6 +33,20 @@
extern "C" {
#endif
typedef void (*decode_block_visitor_fn_t)(const AV1_COMMON *const cm,
MACROBLOCKD *const xd,
aom_reader *const r, const int plane,
const int row, const int col,
const TX_SIZE tx_size);
typedef void (*predict_inter_block_visitor_fn_t)(AV1_COMMON *const cm,
MACROBLOCKD *const xd,
int mi_row, int mi_col,
BLOCK_SIZE bsize);
typedef void (*cfl_store_inter_block_visitor_fn_t)(AV1_COMMON *const cm,
MACROBLOCKD *const xd);
typedef struct ThreadData {
aom_reader *bit_reader;
DECLARE_ALIGNED(32, MACROBLOCKD, xd);
@ -41,12 +55,54 @@ typedef struct ThreadData {
CB_BUFFER cb_buffer_base;
uint8_t *mc_buf[2];
int32_t mc_buf_size;
decode_block_visitor_fn_t read_coeffs_tx_intra_block_visit;
decode_block_visitor_fn_t predict_and_recon_intra_block_visit;
decode_block_visitor_fn_t read_coeffs_tx_inter_block_visit;
decode_block_visitor_fn_t inverse_tx_inter_block_visit;
predict_inter_block_visitor_fn_t predict_inter_block_visit;
cfl_store_inter_block_visitor_fn_t cfl_store_inter_block_visit;
} ThreadData;
typedef struct AV1DecRowMTJobInfo {
int tile_row;
int tile_col;
int mi_row;
} AV1DecRowMTJobInfo;
typedef struct AV1DecRowMTSyncData {
#if CONFIG_MULTITHREAD
pthread_mutex_t *mutex_;
pthread_cond_t *cond_;
#endif
int allocated_sb_rows;
int *cur_sb_col;
int sync_range;
int mi_rows;
int mi_cols;
int mi_rows_parse_done;
int mi_rows_decode_started;
int num_threads_working;
} AV1DecRowMTSync;
typedef struct AV1DecRowMTInfo {
int tile_rows_start;
int tile_rows_end;
int tile_cols_start;
int tile_cols_end;
int start_tile;
int end_tile;
int mi_rows_parse_done;
int mi_rows_decode_started;
int mi_rows_to_decode;
int row_mt_exit;
} AV1DecRowMTInfo;
typedef struct TileDataDec {
TileInfo tile_info;
aom_reader bit_reader;
DECLARE_ALIGNED(16, FRAME_CONTEXT, tctx);
AV1DecRowMTSync dec_row_mt_sync;
} TileDataDec;
typedef struct TileBufferDec {
@ -139,9 +195,8 @@ typedef struct AV1Decoder {
int acct_enabled;
Accounting accounting;
#endif
size_t uncomp_hdr_size; // Size of the uncompressed header
int tg_size; // Number of tiles in the current tilegroup
int tg_start; // First tile in the current tilegroup
int tg_size; // Number of tiles in the current tilegroup
int tg_start; // First tile in the current tilegroup
int tg_size_bit_offset;
int sequence_header_ready;
#if CONFIG_INSPECTION
@ -162,12 +217,27 @@ typedef struct AV1Decoder {
int tile_count_minus_1;
uint32_t coded_tile_data_size;
unsigned int ext_tile_debug; // for ext-tile software debug & testing
unsigned int row_mt;
EXTERNAL_REFERENCES ext_refs;
size_t tile_list_size;
uint8_t *tile_list_output;
size_t buffer_sz;
CB_BUFFER *cb_buffer_base;
int cb_buffer_alloc_size;
int allocated_row_mt_sync_rows;
#if CONFIG_MULTITHREAD
pthread_mutex_t *row_mt_mutex_;
pthread_cond_t *row_mt_cond_;
#endif
AV1DecRowMTInfo frame_row_mt_info;
} AV1Decoder;
// Returns 0 on success. Sets pbi->common.error.error_code to a nonzero error
// code and returns a nonzero value on failure.
int av1_receive_compressed_data(struct AV1Decoder *pbi, size_t size,
const uint8_t **dest);
@ -192,6 +262,10 @@ struct AV1Decoder *av1_decoder_create(BufferPool *const pool);
void av1_decoder_remove(struct AV1Decoder *pbi);
void av1_dealloc_dec_jobs(struct AV1DecTileMTData *tile_jobs_sync);
void av1_dec_row_mt_dealloc(AV1DecRowMTSync *dec_row_mt_sync);
void av1_dec_free_cb_buf(AV1Decoder *pbi);
static INLINE void decrease_ref_count(int idx, RefCntBuffer *const frame_bufs,
BufferPool *const pool) {
if (idx >= 0) {
@ -207,18 +281,6 @@ static INLINE void decrease_ref_count(int idx, RefCntBuffer *const frame_bufs,
}
}
static INLINE int dec_is_ref_frame_buf(AV1Decoder *const pbi,
RefCntBuffer *frame_buf) {
AV1_COMMON *const cm = &pbi->common;
int i;
for (i = 0; i < INTER_REFS_PER_FRAME; ++i) {
RefBuffer *const ref_frame = &cm->frame_refs[i];
if (ref_frame->idx == INVALID_IDX) continue;
if (frame_buf == &cm->buffer_pool->frame_bufs[ref_frame->idx]) break;
}
return (i < INTER_REFS_PER_FRAME);
}
#define ACCT_STR __func__
static INLINE int av1_read_uniform(aom_reader *r, int n) {
const int l = get_unsigned_bits(n);
@ -238,6 +300,10 @@ void av1_visit_palette(AV1Decoder *const pbi, MACROBLOCKD *const xd, int mi_row,
int mi_col, aom_reader *r, BLOCK_SIZE bsize,
palette_visitor_fn_t visit);
typedef void (*block_visitor_fn_t)(AV1Decoder *const pbi, ThreadData *const td,
int mi_row, int mi_col, aom_reader *r,
PARTITION_TYPE partition, BLOCK_SIZE bsize);
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -320,10 +320,14 @@ uint8_t av1_read_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCKD *const xd,
return cul_level;
}
uint8_t av1_read_coeffs_txb_facade(const AV1_COMMON *const cm,
MACROBLOCKD *const xd, aom_reader *const r,
const int row, const int col,
const int plane, const TX_SIZE tx_size) {
void av1_read_coeffs_txb_facade(const AV1_COMMON *const cm,
MACROBLOCKD *const xd, aom_reader *const r,
const int plane, const int row, const int col,
const TX_SIZE tx_size) {
#if TXCOEFF_TIMER
struct aom_usec_timer timer;
aom_usec_timer_start(&timer);
#endif
MB_MODE_INFO *const mbmi = xd->mi[0];
struct macroblockd_plane *const pd = &xd->plane[plane];
@ -337,5 +341,22 @@ uint8_t av1_read_coeffs_txb_facade(const AV1_COMMON *const cm,
const uint8_t cul_level =
av1_read_coeffs_txb(cm, xd, r, row, col, plane, &txb_ctx, tx_size);
av1_set_contexts(xd, pd, plane, plane_bsize, tx_size, cul_level, col, row);
return cul_level;
if (is_inter_block(mbmi)) {
PLANE_TYPE plane_type = get_plane_type(plane);
// tx_type will be read out in av1_read_coeffs_txb_facade
const TX_TYPE tx_type = av1_get_tx_type(plane_type, xd, row, col, tx_size,
cm->reduced_tx_set_used);
if (plane == 0)
update_txk_array(mbmi->txk_type, mbmi->sb_type, row, col, tx_size,
tx_type);
}
#if TXCOEFF_TIMER
aom_usec_timer_mark(&timer);
const int64_t elapsed_time = aom_usec_timer_elapsed(&timer);
cm->txcoeff_timer += elapsed_time;
++cm->txb_count;
#endif
}

View file

@ -25,8 +25,8 @@ uint8_t av1_read_coeffs_txb(const AV1_COMMON *const cm, MACROBLOCKD *const xd,
const TXB_CTX *const txb_ctx,
const TX_SIZE tx_size);
uint8_t av1_read_coeffs_txb_facade(const AV1_COMMON *const cm,
MACROBLOCKD *const xd, aom_reader *const r,
const int row, const int col,
const int plane, const TX_SIZE tx_size);
void av1_read_coeffs_txb_facade(const AV1_COMMON *const cm,
MACROBLOCKD *const xd, aom_reader *const r,
const int plane, const int row, const int col,
const TX_SIZE tx_size);
#endif // DECODETXB_H_

View file

@ -157,8 +157,8 @@ void av1_frameworker_copy_context(AVxWorker *const dst_worker,
dst_worker_data->pbi->need_resync = src_worker_data->pbi->need_resync;
av1_frameworker_unlock_stats(src_worker);
dst_cm->bit_depth = src_cm->bit_depth;
dst_cm->use_highbitdepth = src_cm->use_highbitdepth;
dst_cm->seq_params.bit_depth = src_cm->seq_params.bit_depth;
dst_cm->seq_params.use_highbitdepth = src_cm->seq_params.use_highbitdepth;
// TODO(zoeliu): To handle parallel decoding
dst_cm->prev_frame =
src_cm->show_existing_frame ? src_cm->prev_frame : src_cm->cur_frame;
@ -166,8 +166,8 @@ void av1_frameworker_copy_context(AVxWorker *const dst_worker,
!src_cm->show_existing_frame ? src_cm->width : src_cm->last_width;
dst_cm->last_height =
!src_cm->show_existing_frame ? src_cm->height : src_cm->last_height;
dst_cm->subsampling_x = src_cm->subsampling_x;
dst_cm->subsampling_y = src_cm->subsampling_y;
dst_cm->seq_params.subsampling_x = src_cm->seq_params.subsampling_x;
dst_cm->seq_params.subsampling_y = src_cm->seq_params.subsampling_y;
dst_cm->frame_type = src_cm->frame_type;
dst_cm->last_show_frame = !src_cm->show_existing_frame
? src_cm->show_frame

View file

@ -39,7 +39,6 @@ typedef struct FrameWorkerData {
const uint8_t *data_end;
size_t data_size;
void *user_priv;
int result;
int worker_id;
int received_frame;

View file

@ -161,6 +161,17 @@ static int is_obu_in_current_operating_point(AV1Decoder *pbi,
return 0;
}
static int byte_alignment(AV1_COMMON *const cm,
struct aom_read_bit_buffer *const rb) {
while (rb->bit_offset & 7) {
if (aom_rb_read_bit(rb)) {
cm->error.error_code = AOM_CODEC_CORRUPT_FRAME;
return -1;
}
}
return 0;
}
static uint32_t read_temporal_delimiter_obu() { return 0; }
// Returns a boolean that indicates success.
@ -173,6 +184,13 @@ static int read_bitstream_level(BitstreamLevel *bl,
return 1;
}
// Returns whether two sequence headers are consistent with each other.
// TODO(huisu,wtc@google.com): make sure the code matches the spec exactly.
static int are_seq_headers_consistent(const SequenceHeader *seq_params_old,
const SequenceHeader *seq_params_new) {
return !memcmp(seq_params_old, seq_params_new, sizeof(SequenceHeader));
}
// On success, sets pbi->sequence_header_ready to 1 and returns the number of
// bytes read from 'rb'.
// On failure, sets pbi->common.error.error_code and returns 0.
@ -184,14 +202,17 @@ static uint32_t read_sequence_header_obu(AV1Decoder *pbi,
// Verify rb has been configured to report errors.
assert(rb->error_handler);
cm->profile = av1_read_profile(rb);
if (cm->profile > PROFILE_2) {
// Use a local variable to store the information as we decode. At the end,
// if no errors have occurred, cm->seq_params is updated.
SequenceHeader sh = cm->seq_params;
SequenceHeader *const seq_params = &sh;
seq_params->profile = av1_read_profile(rb);
if (seq_params->profile > PROFILE_2) {
cm->error.error_code = AOM_CODEC_UNSUP_BITSTREAM;
return 0;
}
SequenceHeader *const seq_params = &cm->seq_params;
// Still picture or not
seq_params->still_picture = aom_rb_read_bit(rb);
seq_params->reduced_still_picture_hdr = aom_rb_read_bit(rb);
@ -252,7 +273,8 @@ static uint32_t read_sequence_header_obu(AV1Decoder *pbi,
(cm->timing_info.equal_picture_interval ||
cm->op_params[i].decoder_model_param_present_flag)) {
cm->op_params[i].bitrate = max_level_bitrate(
cm->profile, major_minor_to_seq_level_idx(seq_params->level[i]),
seq_params->profile,
major_minor_to_seq_level_idx(seq_params->level[i]),
seq_params->tier[i]);
// Level with seq_level_idx = 31 returns a high "dummy" bitrate to pass
// the check
@ -305,30 +327,49 @@ static uint32_t read_sequence_header_obu(AV1Decoder *pbi,
return 0;
}
read_sequence_header(cm, rb);
av1_read_sequence_header(cm, rb, seq_params);
av1_read_color_config(cm, rb, pbi->allow_lowbitdepth);
av1_read_color_config(rb, pbi->allow_lowbitdepth, seq_params, &cm->error);
if (!(seq_params->subsampling_x == 0 && seq_params->subsampling_y == 0) &&
!(seq_params->subsampling_x == 1 && seq_params->subsampling_y == 1) &&
!(seq_params->subsampling_x == 1 && seq_params->subsampling_y == 0)) {
aom_internal_error(&cm->error, AOM_CODEC_UNSUP_BITSTREAM,
"Only 4:4:4, 4:2:2 and 4:2:0 are currently supported, "
"%d %d subsampling is not supported.\n",
seq_params->subsampling_x, seq_params->subsampling_y);
}
cm->film_grain_params_present = aom_rb_read_bit(rb);
seq_params->film_grain_params_present = aom_rb_read_bit(rb);
if (av1_check_trailing_bits(pbi, rb) != 0) {
// cm->error.error_code is already set.
return 0;
}
// If a sequence header has been decoded before, we check if the new
// one is consistent with the old one.
if (pbi->sequence_header_ready) {
if (!are_seq_headers_consistent(&cm->seq_params, seq_params)) {
aom_internal_error(&cm->error, AOM_CODEC_UNSUP_BITSTREAM,
"Inconsistent sequence headers received.");
}
}
cm->seq_params = *seq_params;
pbi->sequence_header_ready = 1;
return ((rb->bit_offset - saved_bit_offset + 7) >> 3);
}
// On success, returns the frame header size. On failure, calls
// aom_internal_error and does not return.
static uint32_t read_frame_header_obu(AV1Decoder *pbi,
struct aom_read_bit_buffer *rb,
const uint8_t *data,
const uint8_t **p_data_end,
int trailing_bits_present) {
av1_decode_frame_headers_and_setup(pbi, rb, data, p_data_end,
trailing_bits_present);
return (uint32_t)(pbi->uncomp_hdr_size);
return av1_decode_frame_headers_and_setup(pbi, rb, data, p_data_end,
trailing_bits_present);
}
static int32_t read_tile_group_header(AV1Decoder *pbi,
@ -353,7 +394,6 @@ static int32_t read_tile_group_header(AV1Decoder *pbi,
aom_internal_error(
&cm->error, AOM_CODEC_UNSUP_BITSTREAM,
"For OBU_FRAME type obu tile_start_and_end_present_flag must be 0");
cm->error.error_code = AOM_CODEC_CORRUPT_FRAME;
return -1;
}
*start_tile =
@ -371,9 +411,12 @@ static uint32_t read_one_tile_group_obu(
int start_tile, end_tile;
int32_t header_size, tg_payload_size;
assert((rb->bit_offset & 7) == 0);
assert(rb->bit_buffer + aom_rb_bytes_read(rb) == data);
header_size = read_tile_group_header(pbi, rb, &start_tile, &end_tile,
tile_start_implicit);
if (header_size == -1) return 0;
if (header_size == -1 || byte_alignment(cm, rb)) return 0;
if (start_tile > end_tile) return header_size;
data += header_size;
av1_decode_tg_tiles_and_wrapup(pbi, data, data_end, p_data_end, start_tile,
@ -386,6 +429,87 @@ static uint32_t read_one_tile_group_obu(
return header_size + tg_payload_size;
}
static void alloc_tile_list_buffer(AV1Decoder *pbi) {
// TODO(yunqing): for now, copy each tile's decoded YUV data directly to the
// output buffer. This needs to be modified according to the application
// requirement.
AV1_COMMON *const cm = &pbi->common;
const int tile_width_in_pixels = cm->tile_width * MI_SIZE;
const int tile_height_in_pixels = cm->tile_height * MI_SIZE;
const int ssy = cm->seq_params.subsampling_y;
const int ssx = cm->seq_params.subsampling_x;
const int num_planes = av1_num_planes(cm);
const size_t yplane_tile_size = tile_height_in_pixels * tile_width_in_pixels;
const size_t uvplane_tile_size =
(num_planes > 1)
? (tile_height_in_pixels >> ssy) * (tile_width_in_pixels >> ssx)
: 0;
const size_t tile_size = (cm->seq_params.use_highbitdepth ? 2 : 1) *
(yplane_tile_size + 2 * uvplane_tile_size);
pbi->tile_list_size = tile_size * (pbi->tile_count_minus_1 + 1);
if (pbi->tile_list_size > pbi->buffer_sz) {
if (pbi->tile_list_output != NULL) aom_free(pbi->tile_list_output);
pbi->tile_list_output = NULL;
pbi->tile_list_output = (uint8_t *)aom_memalign(32, pbi->tile_list_size);
if (pbi->tile_list_output == NULL)
aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR,
"Failed to allocate the tile list output buffer");
pbi->buffer_sz = pbi->tile_list_size;
}
}
static void copy_decoded_tile_to_tile_list_buffer(AV1Decoder *pbi,
uint8_t **output) {
AV1_COMMON *const cm = &pbi->common;
const int tile_width_in_pixels = cm->tile_width * MI_SIZE;
const int tile_height_in_pixels = cm->tile_height * MI_SIZE;
const int ssy = cm->seq_params.subsampling_y;
const int ssx = cm->seq_params.subsampling_x;
const int num_planes = av1_num_planes(cm);
// Copy decoded tile to the tile list output buffer.
YV12_BUFFER_CONFIG *cur_frame = get_frame_new_buffer(cm);
const int mi_row = pbi->dec_tile_row * cm->tile_height;
const int mi_col = pbi->dec_tile_col * cm->tile_width;
const int is_hbd = (cur_frame->flags & YV12_FLAG_HIGHBITDEPTH) ? 1 : 0;
uint8_t *bufs[MAX_MB_PLANE] = { NULL, NULL, NULL };
int strides[MAX_MB_PLANE] = { 0, 0, 0 };
int plane;
for (plane = 0; plane < num_planes; ++plane) {
int shift_x = plane > 0 ? ssx : 0;
int shift_y = plane > 0 ? ssy : 0;
bufs[plane] = cur_frame->buffers[plane];
strides[plane] =
(plane > 0) ? cur_frame->strides[1] : cur_frame->strides[0];
bufs[plane] += mi_row * (MI_SIZE >> shift_y) * strides[plane] +
mi_col * (MI_SIZE >> shift_x);
if (is_hbd) {
bufs[plane] = (uint8_t *)CONVERT_TO_SHORTPTR(bufs[plane]);
strides[plane] *= 2;
}
int w, h;
w = (plane > 0 && shift_x > 0) ? ((tile_width_in_pixels + 1) >> shift_x)
: tile_width_in_pixels;
w *= (1 + is_hbd);
h = (plane > 0 && shift_y > 0) ? ((tile_height_in_pixels + 1) >> shift_y)
: tile_height_in_pixels;
int j;
for (j = 0; j < h; ++j) {
memcpy(*output, bufs[plane], w);
bufs[plane] += strides[plane];
*output += w;
}
}
}
// Only called while large_scale_tile = 1.
static uint32_t read_and_decode_one_tile_list(AV1Decoder *pbi,
struct aom_read_bit_buffer *rb,
@ -404,39 +528,13 @@ static uint32_t read_and_decode_one_tile_list(AV1Decoder *pbi,
pbi->output_frame_width_in_tiles_minus_1 = aom_rb_read_literal(rb, 8);
pbi->output_frame_height_in_tiles_minus_1 = aom_rb_read_literal(rb, 8);
pbi->tile_count_minus_1 = aom_rb_read_literal(rb, 16);
if (pbi->tile_count_minus_1 > 511) {
if (pbi->tile_count_minus_1 > MAX_TILES - 1) {
cm->error.error_code = AOM_CODEC_CORRUPT_FRAME;
return 0;
}
// Allocate output frame buffer for the tile list.
// TODO(yunqing): for now, copy each tile's decoded YUV data directly to the
// output buffer. This needs to be modified according to the application
// requirement.
const int tile_width_in_pixels = cm->tile_width * MI_SIZE;
const int tile_height_in_pixels = cm->tile_height * MI_SIZE;
const int ssy = cm->subsampling_y;
const int ssx = cm->subsampling_x;
const int num_planes = av1_num_planes(cm);
const size_t yplane_tile_size = tile_height_in_pixels * tile_width_in_pixels;
const size_t uvplane_tile_size =
(num_planes > 1)
? (tile_height_in_pixels >> ssy) * (tile_width_in_pixels >> ssx)
: 0;
const size_t tile_size = (cm->use_highbitdepth ? 2 : 1) *
(yplane_tile_size + 2 * uvplane_tile_size);
pbi->tile_list_size = tile_size * (pbi->tile_count_minus_1 + 1);
if (pbi->tile_list_size > pbi->buffer_sz) {
if (pbi->tile_list_output != NULL) aom_free(pbi->tile_list_output);
pbi->tile_list_output = NULL;
pbi->tile_list_output = (uint8_t *)aom_memalign(32, pbi->tile_list_size);
if (pbi->tile_list_output == NULL)
aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR,
"Failed to allocate the tile list output buffer");
pbi->buffer_sz = pbi->tile_list_size;
}
alloc_tile_list_buffer(pbi);
uint32_t tile_list_info_bytes = 4;
tile_list_payload_size += tile_list_info_bytes;
@ -485,45 +583,8 @@ static uint32_t read_and_decode_one_tile_list(AV1Decoder *pbi,
data = *p_data_end;
assert(data <= data_end);
// Copy decoded tile to the tile list output buffer.
YV12_BUFFER_CONFIG *cur_frame = get_frame_new_buffer(cm);
const int mi_row = pbi->dec_tile_row * cm->tile_height;
const int mi_col = pbi->dec_tile_col * cm->tile_width;
const int is_hbd = (cur_frame->flags & YV12_FLAG_HIGHBITDEPTH) ? 1 : 0;
uint8_t *bufs[MAX_MB_PLANE] = { NULL, NULL, NULL };
int strides[MAX_MB_PLANE] = { 0, 0, 0 };
int plane;
for (plane = 0; plane < num_planes; ++plane) {
int shift_x = plane > 0 ? ssx : 0;
int shift_y = plane > 0 ? ssy : 0;
bufs[plane] = cur_frame->buffers[plane];
strides[plane] =
(plane > 0) ? cur_frame->strides[1] : cur_frame->strides[0];
if (is_hbd) {
bufs[plane] = (uint8_t *)CONVERT_TO_SHORTPTR(cur_frame->buffers[plane]);
strides[plane] =
(plane > 0) ? 2 * cur_frame->strides[1] : 2 * cur_frame->strides[0];
}
bufs[plane] += mi_row * (MI_SIZE >> shift_y) * strides[plane] +
mi_col * (MI_SIZE >> shift_x);
int w, h;
w = (plane > 0 && shift_x > 0) ? ((tile_width_in_pixels + 1) >> shift_x)
: tile_width_in_pixels;
w *= (1 + is_hbd);
h = (plane > 0 && shift_y > 0) ? ((tile_height_in_pixels + 1) >> shift_y)
: tile_height_in_pixels;
int j;
for (j = 0; j < h; ++j) {
memcpy(output, bufs[plane], w);
bufs[plane] += strides[plane];
output += w;
}
}
// Copy the decoded tile to the tile list output buffer.
copy_decoded_tile_to_tile_list_buffer(pbi, &output);
}
*frame_decoding_finished = 1;
@ -710,7 +771,6 @@ aom_codec_err_t aom_read_obu_header_and_size(const uint8_t *data,
return AOM_CODEC_OK;
}
#define EXT_TILE_DEBUG 0
// On success, returns a boolean that indicates whether the decoding of the
// current frame is finished. On failure, sets cm->error.error_code and
// returns -1.
@ -720,7 +780,7 @@ int aom_decode_frame_from_obus(struct AV1Decoder *pbi, const uint8_t *data,
AV1_COMMON *const cm = &pbi->common;
int frame_decoding_finished = 0;
int is_first_tg_obu_received = 1;
int frame_header_size = 0;
uint32_t frame_header_size = 0;
int seq_header_received = 0;
size_t seq_header_size = 0;
ObuHeader obu_header;
@ -785,7 +845,7 @@ int aom_decode_frame_from_obus(struct AV1Decoder *pbi, const uint8_t *data,
}
}
av1_init_read_bit_buffer(pbi, &rb, data, data_end);
av1_init_read_bit_buffer(pbi, &rb, data, data + payload_size);
switch (obu_header.type) {
case OBU_TEMPORAL_DELIMITER:
@ -813,21 +873,35 @@ int aom_decode_frame_from_obus(struct AV1Decoder *pbi, const uint8_t *data,
// Only decode first frame header received
if (!pbi->seen_frame_header ||
(cm->large_scale_tile && !pbi->camera_frame_header_ready)) {
pbi->seen_frame_header = 1;
frame_header_size = read_frame_header_obu(
pbi, &rb, data, p_data_end, obu_header.type != OBU_FRAME);
if (cm->large_scale_tile) pbi->camera_frame_header_ready = 1;
pbi->seen_frame_header = 1;
if (!pbi->ext_tile_debug && cm->large_scale_tile)
pbi->camera_frame_header_ready = 1;
} else {
// TODO(wtc): Verify that the frame_header_obu is identical to the
// original frame_header_obu. For now just skip frame_header_size
// bytes in the bit buffer.
if (frame_header_size > payload_size) {
cm->error.error_code = AOM_CODEC_CORRUPT_FRAME;
return -1;
}
assert(rb.bit_offset == 0);
rb.bit_offset = 8 * frame_header_size;
}
decoded_payload_size = frame_header_size;
pbi->frame_header_size = (size_t)frame_header_size;
pbi->frame_header_size = frame_header_size;
if (cm->show_existing_frame) {
if (obu_header.type == OBU_FRAME) {
cm->error.error_code = AOM_CODEC_UNSUP_BITSTREAM;
return -1;
}
frame_decoding_finished = 1;
pbi->seen_frame_header = 0;
break;
}
#if !EXT_TILE_DEBUG
// In large scale tile coding, decode the common camera frame header
// before any tile list OBU.
if (!pbi->ext_tile_debug && pbi->camera_frame_header_ready) {
@ -838,17 +912,18 @@ int aom_decode_frame_from_obus(struct AV1Decoder *pbi, const uint8_t *data,
*p_data_end = data_end;
break;
}
#endif // EXT_TILE_DEBUG
if (obu_header.type != OBU_FRAME) break;
obu_payload_offset = frame_header_size;
// Byte align the reader before reading the tile group.
if (byte_alignment(cm, &rb)) return -1;
AOM_FALLTHROUGH_INTENDED; // fall through to read tile group.
case OBU_TILE_GROUP:
if (!pbi->seen_frame_header) {
cm->error.error_code = AOM_CODEC_CORRUPT_FRAME;
return -1;
}
if ((size_t)(data_end - data) < obu_payload_offset) {
if (obu_payload_offset > payload_size) {
cm->error.error_code = AOM_CODEC_CORRUPT_FRAME;
return -1;
}
@ -904,4 +979,3 @@ int aom_decode_frame_from_obus(struct AV1Decoder *pbi, const uint8_t *data,
return frame_decoding_finished;
}
#undef EXT_TILE_DEBUG