[spatial svc]Another workaround to avoid using prev_mi
We encode a empty invisible frame in front of the base layer frame to avoid using prev_mi. Since there's a restriction for reference frame scaling factor, we have to make it smaller and smaller gradually until its size is 16x16. Change remerged. Change-Id: I9efab38bba7da86e056fbe8f663e711c5df38449
This commit is contained in:
Родитель
d5130af568
Коммит
68b550f551
127
test/svc_test.cc
127
test/svc_test.cc
|
@ -225,10 +225,9 @@ class SvcTest : public ::testing::Test {
|
|||
EXPECT_EQ(received_frames, n);
|
||||
}
|
||||
|
||||
void DropLayersAndMakeItVP9Comaptible(struct vpx_fixed_buf *const inputs,
|
||||
const int num_super_frames,
|
||||
const int remained_spatial_layers,
|
||||
const bool is_multiple_frame_contexts) {
|
||||
void DropEnhancementLayers(struct vpx_fixed_buf *const inputs,
|
||||
const int num_super_frames,
|
||||
const int remained_spatial_layers) {
|
||||
ASSERT_TRUE(inputs != NULL);
|
||||
ASSERT_GT(num_super_frames, 0);
|
||||
ASSERT_GT(remained_spatial_layers, 0);
|
||||
|
@ -250,45 +249,6 @@ class SvcTest : public ::testing::Test {
|
|||
if (frame_count == 0) {
|
||||
// There's no super frame but only a single frame.
|
||||
ASSERT_EQ(1, remained_spatial_layers);
|
||||
if (is_multiple_frame_contexts) {
|
||||
// Make a new super frame.
|
||||
uint8_t marker = 0xc1;
|
||||
unsigned int mask;
|
||||
int mag;
|
||||
|
||||
// Choose the magnitude.
|
||||
for (mag = 0, mask = 0xff; mag < 4; ++mag) {
|
||||
if (inputs[i].sz < mask)
|
||||
break;
|
||||
mask <<= 8;
|
||||
mask |= 0xff;
|
||||
}
|
||||
marker |= mag << 3;
|
||||
int index_sz = 2 + (mag + 1) * 2;
|
||||
|
||||
inputs[i].buf = realloc(inputs[i].buf, inputs[i].sz + index_sz + 16);
|
||||
ASSERT_TRUE(inputs[i].buf != NULL);
|
||||
uint8_t *frame_data = static_cast<uint8_t*>(inputs[i].buf);
|
||||
frame_data[0] &= ~2; // Set the show_frame flag to 0.
|
||||
frame_data += inputs[i].sz;
|
||||
// Add an one byte frame with show_existing_frame.
|
||||
*frame_data++ = 0x88;
|
||||
|
||||
// Write the super frame index.
|
||||
*frame_data++ = marker;
|
||||
|
||||
frame_sizes[0] = inputs[i].sz;
|
||||
frame_sizes[1] = 1;
|
||||
for (int j = 0; j < 2; ++j) {
|
||||
unsigned int this_sz = frame_sizes[j];
|
||||
for (int k = 0; k <= mag; k++) {
|
||||
*frame_data++ = this_sz & 0xff;
|
||||
this_sz >>= 8;
|
||||
}
|
||||
}
|
||||
*frame_data++ = marker;
|
||||
inputs[i].sz += index_sz + 1;
|
||||
}
|
||||
} else {
|
||||
// Found a super frame.
|
||||
uint8_t *frame_data = static_cast<uint8_t*>(inputs[i].buf);
|
||||
|
@ -304,16 +264,13 @@ class SvcTest : public ::testing::Test {
|
|||
}
|
||||
ASSERT_LT(frame, frame_count) << "Couldn't find a visible frame. "
|
||||
<< "remained_spatial_layers: " << remained_spatial_layers
|
||||
<< " super_frame: " << i
|
||||
<< " is_multiple_frame_context: " << is_multiple_frame_contexts;
|
||||
if (frame == frame_count - 1 && !is_multiple_frame_contexts)
|
||||
<< " super_frame: " << i;
|
||||
if (frame == frame_count - 1)
|
||||
continue;
|
||||
|
||||
frame_data += frame_sizes[frame];
|
||||
|
||||
// We need to add one more frame for multiple frame contexts.
|
||||
if (is_multiple_frame_contexts)
|
||||
++frame;
|
||||
uint8_t marker =
|
||||
static_cast<const uint8_t*>(inputs[i].buf)[inputs[i].sz - 1];
|
||||
const uint32_t mag = ((marker >> 3) & 0x3) + 1;
|
||||
|
@ -323,35 +280,14 @@ class SvcTest : public ::testing::Test {
|
|||
marker |= frame;
|
||||
|
||||
// Copy existing frame sizes.
|
||||
memmove(frame_data + (is_multiple_frame_contexts ? 2 : 1),
|
||||
frame_start + inputs[i].sz - index_sz + 1, new_index_sz - 2);
|
||||
if (is_multiple_frame_contexts) {
|
||||
// Add a one byte frame with flag show_existing_frame.
|
||||
*frame_data++ = 0x88 | (remained_spatial_layers - 1);
|
||||
}
|
||||
memmove(frame_data + 1, frame_start + inputs[i].sz - index_sz + 1,
|
||||
new_index_sz - 2);
|
||||
// New marker.
|
||||
frame_data[0] = marker;
|
||||
frame_data += (mag * (frame + 1) + 1);
|
||||
|
||||
if (is_multiple_frame_contexts) {
|
||||
// Write the frame size for the one byte frame.
|
||||
frame_data -= mag;
|
||||
*frame_data++ = 1;
|
||||
for (uint32_t j = 1; j < mag; ++j) {
|
||||
*frame_data++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
*frame_data++ = marker;
|
||||
inputs[i].sz = frame_data - frame_start;
|
||||
|
||||
if (is_multiple_frame_contexts) {
|
||||
// Change the show frame flag to 0 for all frames.
|
||||
for (int j = 0; j < frame; ++j) {
|
||||
frame_start[0] &= ~2;
|
||||
frame_start += frame_sizes[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -555,7 +491,7 @@ TEST_F(SvcTest, TwoPassEncode2SpatialLayersDecodeBaseLayerOnly) {
|
|||
vpx_fixed_buf outputs[10];
|
||||
memset(&outputs[0], 0, sizeof(outputs));
|
||||
Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
|
||||
DropLayersAndMakeItVP9Comaptible(&outputs[0], 10, 1, false);
|
||||
DropEnhancementLayers(&outputs[0], 10, 1);
|
||||
DecodeNFrames(&outputs[0], 10);
|
||||
FreeBitstreamBuffers(&outputs[0], 10);
|
||||
}
|
||||
|
@ -573,13 +509,13 @@ TEST_F(SvcTest, TwoPassEncode5SpatialLayersDecode54321Layers) {
|
|||
Pass2EncodeNFrames(&stats_buf, 10, 5, &outputs[0]);
|
||||
|
||||
DecodeNFrames(&outputs[0], 10);
|
||||
DropLayersAndMakeItVP9Comaptible(&outputs[0], 10, 4, false);
|
||||
DropEnhancementLayers(&outputs[0], 10, 4);
|
||||
DecodeNFrames(&outputs[0], 10);
|
||||
DropLayersAndMakeItVP9Comaptible(&outputs[0], 10, 3, false);
|
||||
DropEnhancementLayers(&outputs[0], 10, 3);
|
||||
DecodeNFrames(&outputs[0], 10);
|
||||
DropLayersAndMakeItVP9Comaptible(&outputs[0], 10, 2, false);
|
||||
DropEnhancementLayers(&outputs[0], 10, 2);
|
||||
DecodeNFrames(&outputs[0], 10);
|
||||
DropLayersAndMakeItVP9Comaptible(&outputs[0], 10, 1, false);
|
||||
DropEnhancementLayers(&outputs[0], 10, 1);
|
||||
DecodeNFrames(&outputs[0], 10);
|
||||
|
||||
FreeBitstreamBuffers(&outputs[0], 10);
|
||||
|
@ -616,9 +552,9 @@ TEST_F(SvcTest, TwoPassEncode3SNRLayersDecode321Layers) {
|
|||
memset(&outputs[0], 0, sizeof(outputs));
|
||||
Pass2EncodeNFrames(&stats_buf, 20, 3, &outputs[0]);
|
||||
DecodeNFrames(&outputs[0], 20);
|
||||
DropLayersAndMakeItVP9Comaptible(&outputs[0], 20, 2, false);
|
||||
DropEnhancementLayers(&outputs[0], 20, 2);
|
||||
DecodeNFrames(&outputs[0], 20);
|
||||
DropLayersAndMakeItVP9Comaptible(&outputs[0], 20, 1, false);
|
||||
DropEnhancementLayers(&outputs[0], 20, 1);
|
||||
DecodeNFrames(&outputs[0], 20);
|
||||
|
||||
FreeBitstreamBuffers(&outputs[0], 20);
|
||||
|
@ -649,7 +585,6 @@ TEST_F(SvcTest, TwoPassEncode2SpatialLayersWithMultipleFrameContexts) {
|
|||
vpx_fixed_buf outputs[10];
|
||||
memset(&outputs[0], 0, sizeof(outputs));
|
||||
Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
|
||||
DropLayersAndMakeItVP9Comaptible(&outputs[0], 10, 2, true);
|
||||
DecodeNFrames(&outputs[0], 10);
|
||||
FreeBitstreamBuffers(&outputs[0], 10);
|
||||
}
|
||||
|
@ -667,7 +602,7 @@ TEST_F(SvcTest,
|
|||
vpx_fixed_buf outputs[10];
|
||||
memset(&outputs[0], 0, sizeof(outputs));
|
||||
Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
|
||||
DropLayersAndMakeItVP9Comaptible(&outputs[0], 10, 1, true);
|
||||
DropEnhancementLayers(&outputs[0], 10, 1);
|
||||
DecodeNFrames(&outputs[0], 10);
|
||||
FreeBitstreamBuffers(&outputs[0], 10);
|
||||
}
|
||||
|
@ -686,7 +621,6 @@ TEST_F(SvcTest, TwoPassEncode2SNRLayersWithMultipleFrameContexts) {
|
|||
vpx_fixed_buf outputs[10];
|
||||
memset(&outputs[0], 0, sizeof(outputs));
|
||||
Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
|
||||
DropLayersAndMakeItVP9Comaptible(&outputs[0], 10, 2, true);
|
||||
DecodeNFrames(&outputs[0], 10);
|
||||
FreeBitstreamBuffers(&outputs[0], 10);
|
||||
}
|
||||
|
@ -707,32 +641,13 @@ TEST_F(SvcTest,
|
|||
memset(&outputs[0], 0, sizeof(outputs));
|
||||
Pass2EncodeNFrames(&stats_buf, 10, 3, &outputs[0]);
|
||||
|
||||
vpx_fixed_buf outputs_new[10];
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
outputs_new[i].buf = malloc(outputs[i].sz + 16);
|
||||
ASSERT_TRUE(outputs_new[i].buf != NULL);
|
||||
memcpy(outputs_new[i].buf, outputs[i].buf, outputs[i].sz);
|
||||
outputs_new[i].sz = outputs[i].sz;
|
||||
}
|
||||
DropLayersAndMakeItVP9Comaptible(&outputs_new[0], 10, 3, true);
|
||||
DecodeNFrames(&outputs_new[0], 10);
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
memcpy(outputs_new[i].buf, outputs[i].buf, outputs[i].sz);
|
||||
outputs_new[i].sz = outputs[i].sz;
|
||||
}
|
||||
DropLayersAndMakeItVP9Comaptible(&outputs_new[0], 10, 2, true);
|
||||
DecodeNFrames(&outputs_new[0], 10);
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
memcpy(outputs_new[i].buf, outputs[i].buf, outputs[i].sz);
|
||||
outputs_new[i].sz = outputs[i].sz;
|
||||
}
|
||||
DropLayersAndMakeItVP9Comaptible(&outputs_new[0], 10, 1, true);
|
||||
DecodeNFrames(&outputs_new[0], 10);
|
||||
DecodeNFrames(&outputs[0], 10);
|
||||
DropEnhancementLayers(&outputs[0], 10, 2);
|
||||
DecodeNFrames(&outputs[0], 10);
|
||||
DropEnhancementLayers(&outputs[0], 10, 1);
|
||||
DecodeNFrames(&outputs[0], 10);
|
||||
|
||||
FreeBitstreamBuffers(&outputs[0], 10);
|
||||
FreeBitstreamBuffers(&outputs_new[0], 10);
|
||||
}
|
||||
|
||||
TEST_F(SvcTest, TwoPassEncode2TemporalLayers) {
|
||||
|
@ -769,7 +684,6 @@ TEST_F(SvcTest, TwoPassEncode2TemporalLayersWithMultipleFrameContexts) {
|
|||
vpx_fixed_buf outputs[10];
|
||||
memset(&outputs[0], 0, sizeof(outputs));
|
||||
Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
|
||||
DropLayersAndMakeItVP9Comaptible(&outputs[0], 10, 1, true);
|
||||
DecodeNFrames(&outputs[0], 10);
|
||||
FreeBitstreamBuffers(&outputs[0], 10);
|
||||
}
|
||||
|
@ -814,7 +728,6 @@ TEST_F(SvcTest,
|
|||
vpx_fixed_buf outputs[10];
|
||||
memset(&outputs[0], 0, sizeof(outputs));
|
||||
Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
|
||||
DropLayersAndMakeItVP9Comaptible(&outputs[0], 10, 1, true);
|
||||
|
||||
vpx_fixed_buf base_layer[5];
|
||||
for (int i = 0; i < 5; ++i)
|
||||
|
|
|
@ -1013,7 +1013,11 @@ static void write_frame_size_with_refs(VP9_COMP *cpi,
|
|||
((cpi->svc.number_temporal_layers > 1 &&
|
||||
cpi->oxcf.rc_mode == VPX_CBR) ||
|
||||
(cpi->svc.number_spatial_layers > 1 &&
|
||||
cpi->svc.layer_context[cpi->svc.spatial_layer_id].is_key_frame))) {
|
||||
cpi->svc.layer_context[cpi->svc.spatial_layer_id].is_key_frame) ||
|
||||
(is_two_pass_svc(cpi) &&
|
||||
cpi->svc.encode_empty_frame_state == ENCODING &&
|
||||
cpi->svc.layer_context[0].frames_from_key_frame <
|
||||
cpi->svc.number_temporal_layers + 1))) {
|
||||
found = 0;
|
||||
}
|
||||
vp9_wb_write_bit(wb, found);
|
||||
|
@ -1105,8 +1109,7 @@ static void write_uncompressed_header(VP9_COMP *cpi,
|
|||
// will change to show_frame flag to 0, then add an one byte frame with
|
||||
// show_existing_frame flag which tells the decoder which frame we want to
|
||||
// show.
|
||||
if (!cm->show_frame ||
|
||||
(is_two_pass_svc(cpi) && cm->error_resilient_mode == 0))
|
||||
if (!cm->show_frame)
|
||||
vp9_wb_write_bit(wb, cm->intra_only);
|
||||
|
||||
if (!cm->error_resilient_mode)
|
||||
|
|
|
@ -225,6 +225,9 @@ static void dealloc_compressor_data(VP9_COMP *cpi) {
|
|||
}
|
||||
vpx_memset(&cpi->svc.scaled_frames[0], 0,
|
||||
MAX_LAG_BUFFERS * sizeof(cpi->svc.scaled_frames[0]));
|
||||
|
||||
vp9_free_frame_buffer(&cpi->svc.empty_frame.img);
|
||||
vpx_memset(&cpi->svc.empty_frame, 0, sizeof(cpi->svc.empty_frame));
|
||||
}
|
||||
|
||||
static void save_coding_context(VP9_COMP *cpi) {
|
||||
|
@ -2979,7 +2982,9 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
|
|||
}
|
||||
}
|
||||
if (is_two_pass_svc(cpi) && cm->error_resilient_mode == 0) {
|
||||
// Use the last frame context for the empty frame.
|
||||
cm->frame_context_idx =
|
||||
(cpi->svc.encode_empty_frame_state == ENCODING) ? FRAME_CONTEXTS - 1 :
|
||||
cpi->svc.spatial_layer_id * cpi->svc.number_temporal_layers +
|
||||
cpi->svc.temporal_layer_id;
|
||||
|
||||
|
@ -3160,7 +3165,9 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
|
|||
cpi->ref_frame_flags = get_ref_frame_flags(cpi);
|
||||
|
||||
cm->last_frame_type = cm->frame_type;
|
||||
vp9_rc_postencode_update(cpi, *size);
|
||||
|
||||
if (!(is_two_pass_svc(cpi) && cpi->svc.encode_empty_frame_state == ENCODING))
|
||||
vp9_rc_postencode_update(cpi, *size);
|
||||
|
||||
#if 0
|
||||
output_frame_level_debug_stats(cpi);
|
||||
|
@ -3184,12 +3191,8 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
|
|||
cm->last_height = cm->height;
|
||||
|
||||
// reset to normal state now that we are done.
|
||||
if (!cm->show_existing_frame) {
|
||||
if (is_two_pass_svc(cpi) && cm->error_resilient_mode == 0)
|
||||
cm->last_show_frame = 0;
|
||||
else
|
||||
cm->last_show_frame = cm->show_frame;
|
||||
}
|
||||
if (!cm->show_existing_frame)
|
||||
cm->last_show_frame = cm->show_frame;
|
||||
|
||||
if (cm->show_frame) {
|
||||
vp9_swap_mi_and_prev_mi(cm);
|
||||
|
@ -3226,7 +3229,9 @@ static void Pass2Encode(VP9_COMP *cpi, size_t *size,
|
|||
uint8_t *dest, unsigned int *frame_flags) {
|
||||
cpi->allow_encode_breakout = ENCODE_BREAKOUT_ENABLED;
|
||||
encode_frame_to_data_rate(cpi, size, dest, frame_flags);
|
||||
vp9_twopass_postencode_update(cpi);
|
||||
|
||||
if (!(is_two_pass_svc(cpi) && cpi->svc.encode_empty_frame_state == ENCODING))
|
||||
vp9_twopass_postencode_update(cpi);
|
||||
}
|
||||
|
||||
static void init_motion_estimation(VP9_COMP *cpi) {
|
||||
|
@ -3414,6 +3419,9 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
|
|||
if (is_two_pass_svc(cpi)) {
|
||||
#if CONFIG_SPATIAL_SVC
|
||||
vp9_svc_start_frame(cpi);
|
||||
// Use a small empty frame instead of a real frame
|
||||
if (cpi->svc.encode_empty_frame_state == ENCODING)
|
||||
source = &cpi->svc.empty_frame;
|
||||
#endif
|
||||
if (oxcf->pass == 2)
|
||||
vp9_restore_layer_context(cpi);
|
||||
|
@ -3432,6 +3440,11 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
|
|||
|
||||
// Should we encode an arf frame.
|
||||
arf_src_index = get_arf_src_index(cpi);
|
||||
|
||||
// Skip alt frame if we encode the empty frame
|
||||
if (is_two_pass_svc(cpi) && source != NULL)
|
||||
arf_src_index = 0;
|
||||
|
||||
if (arf_src_index) {
|
||||
assert(arf_src_index <= rc->frames_to_key);
|
||||
|
||||
|
@ -3542,7 +3555,10 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
|
|||
|
||||
// For two pass encodes analyse the first pass stats and determine
|
||||
// the bit allocation and other parameters for this frame / group of frames.
|
||||
if ((oxcf->pass == 2) && (!cpi->use_svc || is_two_pass_svc(cpi))) {
|
||||
if ((oxcf->pass == 2) &&
|
||||
(!cpi->use_svc ||
|
||||
(is_two_pass_svc(cpi) &&
|
||||
cpi->svc.encode_empty_frame_state != ENCODING))) {
|
||||
vp9_rc_get_second_pass_params(cpi);
|
||||
}
|
||||
|
||||
|
@ -3771,10 +3787,18 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
|
|||
|
||||
#endif
|
||||
|
||||
if (is_two_pass_svc(cpi) && cm->show_frame) {
|
||||
++cpi->svc.spatial_layer_to_encode;
|
||||
if (cpi->svc.spatial_layer_to_encode >= cpi->svc.number_spatial_layers)
|
||||
cpi->svc.spatial_layer_to_encode = 0;
|
||||
if (is_two_pass_svc(cpi)) {
|
||||
if (cpi->svc.encode_empty_frame_state == ENCODING)
|
||||
cpi->svc.encode_empty_frame_state = ENCODED;
|
||||
|
||||
if (cm->show_frame) {
|
||||
++cpi->svc.spatial_layer_to_encode;
|
||||
if (cpi->svc.spatial_layer_to_encode >= cpi->svc.number_spatial_layers)
|
||||
cpi->svc.spatial_layer_to_encode = 0;
|
||||
|
||||
// May need the empty frame after an visible frame.
|
||||
cpi->svc.encode_empty_frame_state = NEED_TO_ENCODE;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -3865,10 +3889,6 @@ int vp9_set_size_literal(VP9_COMP *cpi, unsigned int width,
|
|||
|
||||
if (width) {
|
||||
cm->width = width;
|
||||
if (cm->width * 5 < cpi->initial_width) {
|
||||
cm->width = cpi->initial_width / 5 + 1;
|
||||
printf("Warning: Desired width too small, changed to %d\n", cm->width);
|
||||
}
|
||||
if (cm->width > cpi->initial_width) {
|
||||
cm->width = cpi->initial_width;
|
||||
printf("Warning: Desired width too large, changed to %d\n", cm->width);
|
||||
|
@ -3877,10 +3897,6 @@ int vp9_set_size_literal(VP9_COMP *cpi, unsigned int width,
|
|||
|
||||
if (height) {
|
||||
cm->height = height;
|
||||
if (cm->height * 5 < cpi->initial_height) {
|
||||
cm->height = cpi->initial_height / 5 + 1;
|
||||
printf("Warning: Desired height too small, changed to %d\n", cm->height);
|
||||
}
|
||||
if (cm->height > cpi->initial_height) {
|
||||
cm->height = cpi->initial_height;
|
||||
printf("Warning: Desired height too large, changed to %d\n", cm->height);
|
||||
|
|
|
@ -2405,6 +2405,9 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
|
|||
cpi->ref_frame_flags &=
|
||||
(~VP9_LAST_FLAG & ~VP9_GOLD_FLAG & ~VP9_ALT_FLAG);
|
||||
lc->frames_from_key_frame = 0;
|
||||
// Reset the empty frame resolution since we have a key frame.
|
||||
cpi->svc.empty_frame_width = cm->width;
|
||||
cpi->svc.empty_frame_height = cm->height;
|
||||
}
|
||||
} else {
|
||||
cm->frame_type = INTER_FRAME;
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include "vp9/encoder/vp9_svc_layercontext.h"
|
||||
#include "vp9/encoder/vp9_extend.h"
|
||||
|
||||
#define SMALL_FRAME_FB_IDX 7
|
||||
|
||||
void vp9_init_layer_context(VP9_COMP *const cpi) {
|
||||
SVC *const svc = &cpi->svc;
|
||||
const VP9EncoderConfig *const oxcf = &cpi->oxcf;
|
||||
|
@ -28,6 +30,25 @@ void vp9_init_layer_context(VP9_COMP *const cpi) {
|
|||
layer_end = svc->number_temporal_layers;
|
||||
} else {
|
||||
layer_end = svc->number_spatial_layers;
|
||||
|
||||
if (cpi->oxcf.error_resilient_mode == 0 && cpi->oxcf.pass == 2) {
|
||||
if (vp9_realloc_frame_buffer(&cpi->svc.empty_frame.img,
|
||||
cpi->common.width, cpi->common.height,
|
||||
cpi->common.subsampling_x,
|
||||
cpi->common.subsampling_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
cpi->common.use_highbitdepth,
|
||||
#endif
|
||||
VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
|
||||
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
|
||||
"Failed to allocate empty frame for multiple frame "
|
||||
"contexts");
|
||||
|
||||
vpx_memset(cpi->svc.empty_frame.img.buffer_alloc, 0x80,
|
||||
cpi->svc.empty_frame.img.buffer_alloc_sz);
|
||||
cpi->svc.empty_frame_width = cpi->common.width;
|
||||
cpi->svc.empty_frame_height = cpi->common.height;
|
||||
}
|
||||
}
|
||||
|
||||
for (layer = 0; layer < layer_end; ++layer) {
|
||||
|
@ -310,6 +331,47 @@ int vp9_svc_start_frame(VP9_COMP *const cpi) {
|
|||
get_layer_resolution(cpi->oxcf.width, cpi->oxcf.height,
|
||||
lc->scaling_factor_num, lc->scaling_factor_den,
|
||||
&width, &height);
|
||||
|
||||
// Workaround for multiple frame contexts. In some frames we can't use prev_mi
|
||||
// since its previous frame could be changed during decoding time. The idea is
|
||||
// we put a empty invisible frame in front of them, then we will not use
|
||||
// prev_mi when encoding these frames.
|
||||
if (cpi->oxcf.error_resilient_mode == 0 && cpi->oxcf.pass == 2 &&
|
||||
cpi->svc.encode_empty_frame_state == NEED_TO_ENCODE) {
|
||||
if ((cpi->svc.number_temporal_layers > 1 &&
|
||||
cpi->svc.temporal_layer_id < cpi->svc.number_temporal_layers - 1) ||
|
||||
(cpi->svc.number_spatial_layers > 1 &&
|
||||
cpi->svc.spatial_layer_id == 0)) {
|
||||
struct lookahead_entry *buf = vp9_lookahead_peek(cpi->lookahead, 0);
|
||||
|
||||
if (buf != NULL) {
|
||||
cpi->svc.empty_frame.ts_start = buf->ts_start;
|
||||
cpi->svc.empty_frame.ts_end = buf->ts_end;
|
||||
cpi->svc.encode_empty_frame_state = ENCODING;
|
||||
cpi->common.show_frame = 0;
|
||||
cpi->ref_frame_flags = 0;
|
||||
cpi->common.frame_type = INTER_FRAME;
|
||||
cpi->lst_fb_idx =
|
||||
cpi->gld_fb_idx = cpi->alt_fb_idx = SMALL_FRAME_FB_IDX;
|
||||
|
||||
// Gradually make the empty frame smaller to save bits. Make it half of
|
||||
// its previous size because of the scaling factor restriction.
|
||||
cpi->svc.empty_frame_width >>= 1;
|
||||
cpi->svc.empty_frame_width = (cpi->svc.empty_frame_width + 1) & ~1;
|
||||
if (cpi->svc.empty_frame_width < 16)
|
||||
cpi->svc.empty_frame_width = 16;
|
||||
|
||||
cpi->svc.empty_frame_height >>= 1;
|
||||
cpi->svc.empty_frame_height = (cpi->svc.empty_frame_height + 1) & ~1;
|
||||
if (cpi->svc.empty_frame_height < 16)
|
||||
cpi->svc.empty_frame_height = 16;
|
||||
|
||||
width = cpi->svc.empty_frame_width;
|
||||
height = cpi->svc.empty_frame_height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vp9_set_size_literal(cpi, width, height) != 0)
|
||||
return VPX_CODEC_INVALID_PARAM;
|
||||
|
||||
|
@ -317,7 +379,6 @@ int vp9_svc_start_frame(VP9_COMP *const cpi) {
|
|||
cpi->oxcf.best_allowed_q = vp9_quantizer_to_qindex(lc->min_q);
|
||||
|
||||
vp9_change_config(cpi, &cpi->oxcf);
|
||||
|
||||
vp9_set_high_precision_mv(cpi, 1);
|
||||
|
||||
cpi->alt_ref_source = get_layer_context(cpi)->alt_ref_source;
|
||||
|
|
|
@ -50,6 +50,16 @@ typedef struct {
|
|||
|
||||
int spatial_layer_to_encode;
|
||||
|
||||
// Workaround for multiple frame contexts
|
||||
enum {
|
||||
ENCODED = 0,
|
||||
ENCODING,
|
||||
NEED_TO_ENCODE
|
||||
}encode_empty_frame_state;
|
||||
struct lookahead_entry empty_frame;
|
||||
int empty_frame_width;
|
||||
int empty_frame_height;
|
||||
|
||||
// Store scaled source frames to be used for temporal filter to generate
|
||||
// a alt ref frame.
|
||||
YV12_BUFFER_CONFIG scaled_frames[MAX_LAG_BUFFERS];
|
||||
|
|
|
@ -719,6 +719,9 @@ void vp9_temporal_filter(VP9_COMP *cpi, int distance) {
|
|||
++frame_used;
|
||||
}
|
||||
}
|
||||
cm->mi = cm->mip + cm->mi_stride + 1;
|
||||
cpi->mb.e_mbd.mi = cm->mi;
|
||||
cpi->mb.e_mbd.mi[0].src_mi = &cpi->mb.e_mbd.mi[0];
|
||||
} else {
|
||||
// ARF is produced at the native frame size and resized when coded.
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
|
|
|
@ -188,11 +188,9 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
|
|||
}
|
||||
if (alt_ref_sum > REF_FRAMES - cfg->ss_number_layers)
|
||||
ERROR("Not enough ref buffers for svc alt ref frames");
|
||||
if ((cfg->ss_number_layers > 3 ||
|
||||
cfg->ss_number_layers * cfg->ts_number_layers > 4) &&
|
||||
if (cfg->ss_number_layers * cfg->ts_number_layers > 3 &&
|
||||
cfg->g_error_resilient == 0)
|
||||
ERROR("Multiple frame context are not supported for more than 3 spatial "
|
||||
"layers or more than 4 spatial x temporal layers");
|
||||
ERROR("Multiple frame context are not supported for more than 3 layers");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -350,7 +350,7 @@ void assign_layer_bitrates(const SvcContext *svc_ctx,
|
|||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < svc_ctx->spatial_layers; ++i) {
|
||||
for (i = 0; i < VPX_SS_MAX_LAYERS; ++i) {
|
||||
if (total > 0) {
|
||||
enc_cfg->ss_target_bitrate[i] = (unsigned int)
|
||||
(enc_cfg->rc_target_bitrate * alloc_ratio[i] / total);
|
||||
|
|
Загрузка…
Ссылка в новой задаче