Commit 514b8ada authored by Dmitry Kovalev's avatar Dmitry Kovalev
Browse files

Preparation to new frame size encoding.

Just an intermediate change set to simplify merges. Reordering several
uncompressed header bits, code restructuring + minor cleanups.

Change-Id: I28272f520762f8c4e3ad230ae39fff5102ba5c0d
parent 747f76fc
......@@ -727,51 +727,60 @@ static void read_frame_size(VP9_COMMON *cm,
*height = h;
}
static void setup_frame_size(VP9D_COMP *pbi, int scaling_active,
struct vp9_read_bit_buffer *rb) {
// If error concealment is enabled we should only parse the new size
// if we have enough data. Otherwise we will end up with the wrong size.
VP9_COMMON *const pc = &pbi->common;
int display_width = pc->display_width;
int display_height = pc->display_height;
int width = pc->width;
int height = pc->height;
if (scaling_active)
read_frame_size(pc, rb, &display_width, &display_height);
static void setup_display_size(VP9D_COMP *pbi,
struct vp9_read_bit_buffer *rb) {
VP9_COMMON *const cm = &pbi->common;
if (vp9_rb_read_bit(rb)) {
int width, height;
read_frame_size(cm, rb, &width, &height);
cm->display_width = width;
cm->display_height = height;
} else {
cm->display_width = cm->width;
cm->display_height = cm->height;
}
}
read_frame_size(pc, rb, &width, &height);
static void apply_frame_size(VP9D_COMP *pbi, int width, int height) {
VP9_COMMON *cm = &pbi->common;
if (pc->width != width || pc->height != height) {
if (cm->width != width || cm->height != height) {
if (!pbi->initial_width || !pbi->initial_height) {
if (vp9_alloc_frame_buffers(pc, width, height))
vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
if (vp9_alloc_frame_buffers(cm, width, height))
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate frame buffers");
pbi->initial_width = width;
pbi->initial_height = height;
} else {
if (width > pbi->initial_width)
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME,
"Frame width too large");
if (height > pbi->initial_height)
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME,
"Frame height too large");
}
pc->width = width;
pc->height = height;
pc->display_width = scaling_active ? display_width : width;
pc->display_height = scaling_active ? display_height : height;
cm->width = width;
cm->height = height;
vp9_update_frame_size(pc);
vp9_update_frame_size(cm);
}
vp9_realloc_frame_buffer(&pc->yv12_fb[pc->new_fb_idx], pc->width, pc->height,
pc->subsampling_x, pc->subsampling_y,
vp9_realloc_frame_buffer(&cm->yv12_fb[cm->new_fb_idx], cm->width, cm->height,
cm->subsampling_x, cm->subsampling_y,
VP9BORDERINPIXELS);
}
static void setup_frame_size(VP9D_COMP *pbi,
struct vp9_read_bit_buffer *rb) {
VP9_COMMON *const cm = &pbi->common;
int width, height;
read_frame_size(cm, rb, &width, &height);
setup_display_size(pbi, rb);
apply_frame_size(pbi, width, height);
}
static void update_frame_context(FRAME_CONTEXT *fc) {
vp9_copy(fc->pre_coef_probs, fc->coef_probs);
vp9_copy(fc->pre_y_mode_prob, fc->y_mode_prob);
......@@ -921,13 +930,14 @@ static void error_handler(void *data, int bit_offset) {
vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM, \
"Reserved bit must be unset")
size_t read_uncompressed_header(VP9D_COMP *pbi,
struct vp9_read_bit_buffer *rb) {
static size_t read_uncompressed_header(VP9D_COMP *pbi,
struct vp9_read_bit_buffer *rb) {
VP9_COMMON *const cm = &pbi->common;
MACROBLOCKD *const xd = &pbi->mb;
int i;
int scaling_active, i;
cm->last_frame_type = cm->frame_type;
if (vp9_rb_read_literal(rb, 2) != 0x2)
vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
"Invalid frame marker");
......@@ -943,9 +953,10 @@ size_t read_uncompressed_header(VP9D_COMP *pbi,
cm->filter_level = 0;
return 0;
}
cm->frame_type = (FRAME_TYPE) vp9_rb_read_bit(rb);
cm->show_frame = vp9_rb_read_bit(rb);
scaling_active = vp9_rb_read_bit(rb);
cm->error_resilient_mode = vp9_rb_read_bit(rb);
if (cm->frame_type == KEY_FRAME) {
if (vp9_rb_read_literal(rb, 8) != SYNC_CODE_0 ||
......@@ -954,6 +965,7 @@ size_t read_uncompressed_header(VP9D_COMP *pbi,
vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
"Invalid frame sync code");
}
vp9_rb_read_literal(rb, 3); // colorspace
if (cm->version == 1) {
cm->subsampling_x = vp9_rb_read_bit(rb);
......@@ -962,28 +974,15 @@ size_t read_uncompressed_header(VP9D_COMP *pbi,
} else {
cm->subsampling_y = cm->subsampling_x = 1;
}
}
setup_frame_size(pbi, scaling_active, rb);
cm->error_resilient_mode = vp9_rb_read_bit(rb);
if (!cm->error_resilient_mode) {
cm->reset_frame_context = vp9_rb_read_bit(rb);
cm->refresh_frame_context = vp9_rb_read_bit(rb);
cm->frame_parallel_decoding_mode = vp9_rb_read_bit(rb);
} else {
cm->reset_frame_context = 0;
cm->refresh_frame_context = 0;
cm->frame_parallel_decoding_mode = 1;
}
if (cm->frame_type == KEY_FRAME) {
vp9_setup_past_independence(cm, xd);
pbi->refresh_frame_flags = (1 << NUM_REF_FRAMES) - 1;
for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i)
cm->active_ref_idx[i] = cm->new_fb_idx;
setup_frame_size(pbi, rb);
} else {
if (cm->error_resilient_mode)
vp9_setup_past_independence(cm, xd);
......@@ -993,16 +992,19 @@ size_t read_uncompressed_header(VP9D_COMP *pbi,
for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i) {
const int ref = vp9_rb_read_literal(rb, NUM_REF_FRAMES_LG2);
cm->active_ref_idx[i] = cm->ref_frame_map[ref];
vp9_setup_scale_factors(cm, i);
cm->ref_frame_sign_bias[LAST_FRAME + i] = vp9_rb_read_bit(rb);
}
setup_frame_size(pbi, rb);
// Read the sign bias for each reference frame buffer.
cm->allow_comp_inter_inter = 0;
for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i) {
cm->ref_frame_sign_bias[i + 1] = vp9_rb_read_bit(rb);
vp9_setup_scale_factors(cm, i);
cm->allow_comp_inter_inter |= i > 0 &&
cm->ref_frame_sign_bias[i + 1] != cm->ref_frame_sign_bias[1];
}
if (cm->allow_comp_inter_inter) {
// which one is always-on in comp inter-inter?
if (cm->ref_frame_sign_bias[LAST_FRAME] ==
......@@ -1026,6 +1028,16 @@ size_t read_uncompressed_header(VP9D_COMP *pbi,
cm->mcomp_filter_type = read_interp_filter_type(rb);
}
if (!cm->error_resilient_mode) {
cm->reset_frame_context = vp9_rb_read_bit(rb);
cm->refresh_frame_context = vp9_rb_read_bit(rb);
cm->frame_parallel_decoding_mode = vp9_rb_read_bit(rb);
} else {
cm->reset_frame_context = 0;
cm->refresh_frame_context = 0;
cm->frame_parallel_decoding_mode = 1;
}
cm->intra_only = cm->show_frame ? 0 : vp9_rb_read_bit(rb);
cm->frame_context_idx = vp9_rb_read_literal(rb, NUM_FRAME_CONTEXTS_LG2);
cm->clr_type = (YUV_TYPE)vp9_rb_read_bit(rb);
......
......@@ -11,6 +11,10 @@
#ifndef VP9_READ_BIT_BUFFER_
#define VP9_READ_BIT_BUFFER_
#include <limits.h>
#include "vpx/vpx_integer.h"
typedef void (*vp9_rb_error_handler)(void *data, int bit_offset);
struct vp9_read_bit_buffer {
......
......@@ -1293,17 +1293,60 @@ static void write_tile_info(VP9_COMMON *cm, struct vp9_write_bit_buffer *wb) {
vp9_wb_write_bit(wb, cm->log2_tile_rows != 1);
}
void write_uncompressed_header(VP9_COMP *cpi,
struct vp9_write_bit_buffer *wb) {
static int get_refresh_mask(VP9_COMP *cpi) {
// Should the GF or ARF be updated using the transmitted frame or buffer
#if CONFIG_MULTIPLE_ARF
if (!cpi->multi_arf_enabled && cpi->refresh_golden_frame &&
!cpi->refresh_alt_ref_frame) {
#else
if (cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame) {
#endif
// Preserve the previously existing golden frame and update the frame in
// the alt ref slot instead. This is highly specific to the use of
// alt-ref as a forward reference, and this needs to be generalized as
// other uses are implemented (like RTC/temporal scaling)
//
// gld_fb_idx and alt_fb_idx need to be swapped for future frames, but
// that happens in vp9_onyx_if.c:update_reference_frames() so that it can
// be done outside of the recode loop.
return (cpi->refresh_last_frame << cpi->lst_fb_idx) |
(cpi->refresh_golden_frame << cpi->alt_fb_idx);
} else {
int arf_idx = cpi->alt_fb_idx;
#if CONFIG_MULTIPLE_ARF
// Determine which ARF buffer to use to encode this ARF frame.
if (cpi->multi_arf_enabled) {
int sn = cpi->sequence_number;
arf_idx = (cpi->frame_coding_order[sn] < 0) ?
cpi->arf_buffer_idx[sn + 1] :
cpi->arf_buffer_idx[sn];
}
#endif
return (cpi->refresh_last_frame << cpi->lst_fb_idx) |
(cpi->refresh_golden_frame << cpi->gld_fb_idx) |
(cpi->refresh_alt_ref_frame << arf_idx);
}
}
static void write_display_size(VP9_COMP *cpi, struct vp9_write_bit_buffer *wb) {
VP9_COMMON *const cm = &cpi->common;
MACROBLOCKD *const xd = &cpi->mb.e_mbd;
const int scaling_active = cm->width != cm->display_width ||
cm->height != cm->display_height;
vp9_wb_write_bit(wb, scaling_active);
if (scaling_active) {
vp9_wb_write_literal(wb, cm->display_width, 16);
vp9_wb_write_literal(wb, cm->display_height, 16);
}
}
static void write_uncompressed_header(VP9_COMP *cpi,
struct vp9_write_bit_buffer *wb) {
VP9_COMMON *const cm = &cpi->common;
MACROBLOCKD *const xd = &cpi->mb.e_mbd;
// frame marker bits
vp9_wb_write_bit(wb, 1);
vp9_wb_write_bit(wb, 0);
vp9_wb_write_literal(wb, 0x2, 2);
// bitstream version.
// 00 - profile 0. 4:2:0 only
......@@ -1314,7 +1357,7 @@ void write_uncompressed_header(VP9_COMP *cpi,
vp9_wb_write_bit(wb, 0);
vp9_wb_write_bit(wb, cm->frame_type);
vp9_wb_write_bit(wb, cm->show_frame);
vp9_wb_write_bit(wb, scaling_active);
vp9_wb_write_bit(wb, cm->error_resilient_mode);
if (cm->frame_type == KEY_FRAME) {
vp9_wb_write_literal(wb, SYNC_CODE_0, 8);
......@@ -1332,68 +1375,29 @@ void write_uncompressed_header(VP9_COMP *cpi,
vp9_wb_write_bit(wb, cm->subsampling_y);
vp9_wb_write_bit(wb, 0); // has extra plane
}
}
if (scaling_active) {
vp9_wb_write_literal(wb, cm->display_width, 16);
vp9_wb_write_literal(wb, cm->display_height, 16);
}
vp9_wb_write_literal(wb, cm->width, 16);
vp9_wb_write_literal(wb, cm->height, 16);
vp9_wb_write_bit(wb, cm->error_resilient_mode);
if (!cm->error_resilient_mode) {
vp9_wb_write_bit(wb, cm->reset_frame_context);
vp9_wb_write_bit(wb, cm->refresh_frame_context);
vp9_wb_write_bit(wb, cm->frame_parallel_decoding_mode);
}
// frame size
vp9_wb_write_literal(wb, cm->width, 16);
vp9_wb_write_literal(wb, cm->height, 16);
write_display_size(cpi, wb);
} else {
// When there is a key frame all reference buffers are updated using the
// new key frame
// When there is a key frame all reference buffers are updated using the new key frame
if (cm->frame_type != KEY_FRAME) {
int refresh_mask, i;
int i;
int refs[ALLOWED_REFS_PER_FRAME] = {cpi->lst_fb_idx, cpi->gld_fb_idx,
cpi->alt_fb_idx};
// Should the GF or ARF be updated using the transmitted frame or buffer
#if CONFIG_MULTIPLE_ARF
if (!cpi->multi_arf_enabled && cpi->refresh_golden_frame &&
!cpi->refresh_alt_ref_frame) {
#else
if (cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame) {
#endif
// Preserve the previously existing golden frame and update the frame in
// the alt ref slot instead. This is highly specific to the use of
// alt-ref as a forward reference, and this needs to be generalized as
// other uses are implemented (like RTC/temporal scaling)
//
// gld_fb_idx and alt_fb_idx need to be swapped for future frames, but
// that happens in vp9_onyx_if.c:update_reference_frames() so that it can
// be done outside of the recode loop.
refresh_mask = (cpi->refresh_last_frame << cpi->lst_fb_idx) |
(cpi->refresh_golden_frame << cpi->alt_fb_idx);
} else {
int arf_idx = cpi->alt_fb_idx;
#if CONFIG_MULTIPLE_ARF
// Determine which ARF buffer to use to encode this ARF frame.
if (cpi->multi_arf_enabled) {
int sn = cpi->sequence_number;
arf_idx = (cpi->frame_coding_order[sn] < 0) ?
cpi->arf_buffer_idx[sn + 1] :
cpi->arf_buffer_idx[sn];
}
#endif
refresh_mask = (cpi->refresh_last_frame << cpi->lst_fb_idx) |
(cpi->refresh_golden_frame << cpi->gld_fb_idx) |
(cpi->refresh_alt_ref_frame << arf_idx);
vp9_wb_write_literal(wb, get_refresh_mask(cpi), NUM_REF_FRAMES);
for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i) {
vp9_wb_write_literal(wb, refs[i], NUM_REF_FRAMES_LG2);
vp9_wb_write_bit(wb, cm->ref_frame_sign_bias[LAST_FRAME + i]);
}
vp9_wb_write_literal(wb, refresh_mask, NUM_REF_FRAMES);
vp9_wb_write_literal(wb, cpi->lst_fb_idx, NUM_REF_FRAMES_LG2);
vp9_wb_write_literal(wb, cpi->gld_fb_idx, NUM_REF_FRAMES_LG2);
vp9_wb_write_literal(wb, cpi->alt_fb_idx, NUM_REF_FRAMES_LG2);
// Indicate the sign bias for each reference frame buffer.
for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i)
vp9_wb_write_bit(wb, cm->ref_frame_sign_bias[LAST_FRAME + i]);
// frame size
vp9_wb_write_literal(wb, cm->width, 16);
vp9_wb_write_literal(wb, cm->height, 16);
write_display_size(cpi, wb);
// Signal whether to allow high MV precision
vp9_wb_write_bit(wb, xd->allow_high_precision_mv);
......@@ -1403,6 +1407,12 @@ void write_uncompressed_header(VP9_COMP *cpi,
write_interp_filter_type(cm->mcomp_filter_type, wb);
}
if (!cm->error_resilient_mode) {
vp9_wb_write_bit(wb, cm->reset_frame_context);
vp9_wb_write_bit(wb, cm->refresh_frame_context);
vp9_wb_write_bit(wb, cm->frame_parallel_decoding_mode);
}
if (!cm->show_frame)
vp9_wb_write_bit(wb, cm->intra_only);
......@@ -1449,8 +1459,7 @@ void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, unsigned long *size) {
vp9_copy(pc->fc.pre_coef_probs, pc->fc.coef_probs);
vp9_copy(pc->fc.pre_y_mode_prob, pc->fc.y_mode_prob);
vp9_copy(pc->fc.pre_uv_mode_prob, pc->fc.uv_mode_prob);
vp9_copy(cpi->common.fc.pre_partition_prob,
cpi->common.fc.partition_prob[INTER_FRAME]);
vp9_copy(pc->fc.pre_partition_prob, pc->fc.partition_prob[INTER_FRAME]);
pc->fc.pre_nmvc = pc->fc.nmvc;
vp9_copy(pc->fc.pre_switchable_interp_prob, pc->fc.switchable_interp_prob);
vp9_copy(pc->fc.pre_inter_mode_probs, pc->fc.inter_mode_probs);
......@@ -1458,8 +1467,7 @@ void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, unsigned long *size) {
vp9_copy(pc->fc.pre_comp_inter_prob, pc->fc.comp_inter_prob);
vp9_copy(pc->fc.pre_comp_ref_prob, pc->fc.comp_ref_prob);
vp9_copy(pc->fc.pre_single_ref_prob, pc->fc.single_ref_prob);
cpi->common.fc.pre_nmvc = cpi->common.fc.nmvc;
vp9_copy(cpi->common.fc.pre_tx_probs, cpi->common.fc.tx_probs);
vp9_copy(pc->fc.pre_tx_probs, pc->fc.tx_probs);
if (xd->lossless) {
pc->txfm_mode = ONLY_4X4;
......
......@@ -11,6 +11,8 @@
#ifndef VP9_BIT_WRITE_BUFFER_H_
#define VP9_BIT_WRITE_BUFFER_H_
#include <limits.h>
#include "vpx/vpx_integer.h"
struct vp9_write_bit_buffer {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment