Commit 6533ac73 authored by Dmitry Kovalev's avatar Dmitry Kovalev Committed by Gerrit Code Review
Browse files

Merge "Preparation to new frame size encoding." into experimental

parents 6462afe0 514b8ada
......@@ -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 {
......
......@@ -1287,17 +1287,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
......@@ -1308,7 +1351,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);
......@@ -1326,68 +1369,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);
......@@ -1397,6 +1401,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);
......@@ -1443,8 +1453,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);
......@@ -1452,8 +1461,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