codec_enc_.kf_min_dist = 100;
codec_enc_.kf_max_dist = 100;
- vpx_codec_dec_cfg_t dec_cfg = {0};
+ vpx_codec_dec_cfg_t dec_cfg = vpx_codec_dec_cfg_t();
VP9CodecFactory codec_factory;
decoder_ = codec_factory.CreateDecoder(dec_cfg, 0);
}
video.Next();
}
- // Flush encoder and test EOS packet
+ // Flush encoder and test EOS packet.
res = vpx_svc_encode(&svc_, &codec_, NULL, video.pts(),
video.duration(), VPX_DL_GOOD_QUALITY);
stats_size = vpx_svc_get_rc_stats_buffer_size(&svc_);
EXPECT_EQ(1, vpx_svc_is_keyframe(&svc_));
}
- outputs[*frame_received].buf = malloc(frame_size);
+ outputs[*frame_received].buf = malloc(frame_size + 16);
ASSERT_TRUE(outputs[*frame_received].buf != NULL);
memcpy(outputs[*frame_received].buf, vpx_svc_get_buffer(&svc_),
frame_size);
video.Next();
}
- // Flush Encoder
+ // Flush encoder.
res = vpx_svc_encode(&svc_, &codec_, NULL, 0,
video.duration(), VPX_DL_GOOD_QUALITY);
EXPECT_EQ(VPX_CODEC_OK, res);
StoreFrames(n, outputs, &frame_received);
- EXPECT_EQ(frame_received, (size_t)n);
+ EXPECT_EQ(frame_received, static_cast<size_t>(n));
ReleaseEncoder();
}
++decoded_frames;
DxDataIterator dec_iter = decoder_->GetDxData();
- while (dec_iter.Next()) {
+ while (dec_iter.Next() != NULL) {
++received_frames;
}
}
void DropEnhancementLayers(struct vpx_fixed_buf *const inputs,
const int num_super_frames,
- const int remained_layers) {
+ const int remained_layers,
+ const bool is_multiple_frame_context) {
ASSERT_TRUE(inputs != NULL);
ASSERT_GT(num_super_frames, 0);
ASSERT_GT(remained_layers, 0);
uint8_t *frame_data = static_cast<uint8_t *>(inputs[i].buf);
uint8_t *frame_start = frame_data;
for (frame = 0; frame < frame_count; ++frame) {
- // Looking for a visible frame
+ // Looking for a visible frame.
if (frame_data[0] & 0x02) {
++frames_found;
if (frames_found == remained_layers)
}
frame_data += frame_sizes[frame];
}
- ASSERT_LT(frame, frame_count);
- if (frame == frame_count - 1)
+ ASSERT_LT(frame, frame_count) << "Couldn't find a visible frame. "
+ << "remaining_layers: " << remained_layers
+ << " super_frame: " << i
+ << " is_multiple_frame_context: " << is_multiple_frame_context;
+ if (frame == frame_count - 1 && !is_multiple_frame_context)
continue;
frame_data += frame_sizes[frame];
+ // We need to add one more frame for multiple frame context.
+ if (is_multiple_frame_context)
+ ++frame;
uint8_t marker =
static_cast<const uint8_t *>(inputs[i].buf)[inputs[i].sz - 1];
const uint32_t mag = ((marker >> 3) & 0x3) + 1;
const size_t new_index_sz = 2 + mag * (frame + 1);
marker &= 0x0f8;
marker |= frame;
+
+ // Copy existing frame sizes.
+ memmove(frame_data + (is_multiple_frame_context ? 2 : 1),
+ frame_start + inputs[i].sz - index_sz + 1, new_index_sz - 2);
+ if (is_multiple_frame_context) {
+ // Add a one byte frame with flag show_existing frame.
+ *frame_data++ = 0x88 | (remained_layers - 1);
+ }
+ // New marker.
frame_data[0] = marker;
- memcpy(frame_data + 1, frame_start + inputs[i].sz - index_sz + 1,
- new_index_sz - 2);
- frame_data[new_index_sz - 1] = marker;
- inputs[i].sz = frame_data - frame_start + new_index_sz;
+ frame_data += (mag * (frame + 1) + 1);
+
+ if (is_multiple_frame_context) {
+ // 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_context) {
+ // 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];
+ }
+ }
}
}
vpx_fixed_buf outputs[10];
memset(&outputs[0], 0, sizeof(outputs));
Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
- DropEnhancementLayers(&outputs[0], 10, 1);
+ DropEnhancementLayers(&outputs[0], 10, 1, false);
DecodeNFrames(&outputs[0], 10);
FreeBitstreamBuffers(&outputs[0], 10);
}
Pass2EncodeNFrames(&stats_buf, 10, 5, &outputs[0]);
DecodeNFrames(&outputs[0], 10);
- DropEnhancementLayers(&outputs[0], 10, 4);
+ DropEnhancementLayers(&outputs[0], 10, 4, false);
DecodeNFrames(&outputs[0], 10);
- DropEnhancementLayers(&outputs[0], 10, 3);
+ DropEnhancementLayers(&outputs[0], 10, 3, false);
DecodeNFrames(&outputs[0], 10);
- DropEnhancementLayers(&outputs[0], 10, 2);
+ DropEnhancementLayers(&outputs[0], 10, 2, false);
DecodeNFrames(&outputs[0], 10);
- DropEnhancementLayers(&outputs[0], 10, 1);
+ DropEnhancementLayers(&outputs[0], 10, 1, false);
DecodeNFrames(&outputs[0], 10);
FreeBitstreamBuffers(&outputs[0], 10);
memset(&outputs[0], 0, sizeof(outputs));
Pass2EncodeNFrames(&stats_buf, 20, 3, &outputs[0]);
DecodeNFrames(&outputs[0], 20);
- DropEnhancementLayers(&outputs[0], 20, 2);
+ DropEnhancementLayers(&outputs[0], 20, 2, false);
DecodeNFrames(&outputs[0], 20);
- DropEnhancementLayers(&outputs[0], 20, 1);
+ DropEnhancementLayers(&outputs[0], 20, 1, false);
DecodeNFrames(&outputs[0], 20);
FreeBitstreamBuffers(&outputs[0], 20);
}
+ TEST_F(SvcTest, SetMultipleFrameContextOption) {
+ svc_.spatial_layers = 5;
+ vpx_codec_err_t res =
+ vpx_svc_set_options(&svc_, "multi-frame-contexts=1");
+ EXPECT_EQ(VPX_CODEC_OK, res);
+ res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
+ EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
+
+ svc_.spatial_layers = 2;
+ res = vpx_svc_set_options(&svc_, "multi-frame-contexts=1");
+ InitializeEncoder();
+ }
+
+ TEST_F(SvcTest, TwoPassEncode2LayersWithMultipleFrameContext) {
+ // First pass encode
+ std::string stats_buf;
+ Pass1EncodeNFrames(10, 2, &stats_buf);
+
+ // Second pass encode
+ codec_enc_.g_pass = VPX_RC_LAST_PASS;
+ codec_enc_.g_error_resilient = 0;
+ vpx_svc_set_options(&svc_, "auto-alt-refs=1,1 multi-frame-contexts=1");
+ vpx_fixed_buf outputs[10];
+ memset(&outputs[0], 0, sizeof(outputs));
+ Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
+ DropEnhancementLayers(&outputs[0], 10, 2, true);
+ DecodeNFrames(&outputs[0], 10);
+ FreeBitstreamBuffers(&outputs[0], 10);
+ }
+
+ TEST_F(SvcTest, TwoPassEncode2LayersWithMultipleFrameContextDecodeBaselayer) {
+ // First pass encode
+ std::string stats_buf;
+ Pass1EncodeNFrames(10, 2, &stats_buf);
+
+ // Second pass encode
+ codec_enc_.g_pass = VPX_RC_LAST_PASS;
+ codec_enc_.g_error_resilient = 0;
+ vpx_svc_set_options(&svc_, "auto-alt-refs=1,1 multi-frame-contexts=1");
+ vpx_fixed_buf outputs[10];
+ memset(&outputs[0], 0, sizeof(outputs));
+ Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
+ DropEnhancementLayers(&outputs[0], 10, 1, true);
+ DecodeNFrames(&outputs[0], 10);
+ FreeBitstreamBuffers(&outputs[0], 10);
+ }
+
+ TEST_F(SvcTest, TwoPassEncode2SNRLayersWithMultipleFrameContext) {
+ // First pass encode
+ std::string stats_buf;
+ vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1");
+ Pass1EncodeNFrames(10, 2, &stats_buf);
+
+ // Second pass encode
+ codec_enc_.g_pass = VPX_RC_LAST_PASS;
+ codec_enc_.g_error_resilient = 0;
+ vpx_svc_set_options(&svc_, "auto-alt-refs=1,1 scale-factors=1/1,1/1 "
+ "multi-frame-contexts=1");
+ vpx_fixed_buf outputs[10];
+ memset(&outputs[0], 0, sizeof(outputs));
+ Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
+ DropEnhancementLayers(&outputs[0], 10, 2, true);
+ DecodeNFrames(&outputs[0], 10);
+ FreeBitstreamBuffers(&outputs[0], 10);
+ }
+
+ TEST_F(SvcTest, TwoPassEncode3SNRLayersWithMultipleFrameContextDecode321Layer) {
+ // First pass encode
+ std::string stats_buf;
+ vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1,1/1");
+ Pass1EncodeNFrames(10, 3, &stats_buf);
+
+ // Second pass encode
+ codec_enc_.g_pass = VPX_RC_LAST_PASS;
+ codec_enc_.g_error_resilient = 0;
+ vpx_svc_set_options(&svc_, "auto-alt-refs=1,1,1 scale-factors=1/1,1/1,1/1 "
+ "multi-frame-contexts=1");
+ vpx_fixed_buf outputs[10];
+ 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;
+ }
+ DropEnhancementLayers(&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;
+ }
+ DropEnhancementLayers(&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;
+ }
+ DropEnhancementLayers(&outputs_new[0], 10, 1, true);
+ DecodeNFrames(&outputs_new[0], 10);
+
+ FreeBitstreamBuffers(&outputs[0], 10);
+ FreeBitstreamBuffers(&outputs_new[0], 10);
+ }
+
} // namespace
vpx_free(cpi->complexity_map);
cpi->complexity_map = NULL;
+ vpx_free(cpi->nmvcosts[0]);
+ vpx_free(cpi->nmvcosts[1]);
+ cpi->nmvcosts[0] = NULL;
+ cpi->nmvcosts[1] = NULL;
+
+ vpx_free(cpi->nmvcosts_hp[0]);
+ vpx_free(cpi->nmvcosts_hp[1]);
+ cpi->nmvcosts_hp[0] = NULL;
+ cpi->nmvcosts_hp[1] = NULL;
+
+ vpx_free(cpi->nmvsadcosts[0]);
+ vpx_free(cpi->nmvsadcosts[1]);
+ cpi->nmvsadcosts[0] = NULL;
+ cpi->nmvsadcosts[1] = NULL;
+
+ vpx_free(cpi->nmvsadcosts_hp[0]);
+ vpx_free(cpi->nmvsadcosts_hp[1]);
+ cpi->nmvsadcosts_hp[0] = NULL;
+ cpi->nmvsadcosts_hp[1] = NULL;
+
vp9_cyclic_refresh_free(cpi->cyclic_refresh);
cpi->cyclic_refresh = NULL;
// intended for use in a re-code loop in vp9_compress_frame where the
// quantizer value is adjusted between loop iterations.
vp9_copy(cc->nmvjointcost, cpi->mb.nmvjointcost);
- vp9_copy(cc->nmvcosts, cpi->mb.nmvcosts);
- vp9_copy(cc->nmvcosts_hp, cpi->mb.nmvcosts_hp);
+
+ vpx_memcpy(cc->nmvcosts[0], cpi->nmvcosts[0],
+ MV_VALS * sizeof(*cpi->nmvcosts[0]));
+ vpx_memcpy(cc->nmvcosts[1], cpi->nmvcosts[1],
+ MV_VALS * sizeof(*cpi->nmvcosts[1]));
+ vpx_memcpy(cc->nmvcosts_hp[0], cpi->nmvcosts_hp[0],
+ MV_VALS * sizeof(*cpi->nmvcosts_hp[0]));
+ vpx_memcpy(cc->nmvcosts_hp[1], cpi->nmvcosts_hp[1],
+ MV_VALS * sizeof(*cpi->nmvcosts_hp[1]));
vp9_copy(cc->segment_pred_probs, cm->seg.pred_probs);
// Restore key state variables to the snapshot state stored in the
// previous call to vp9_save_coding_context.
vp9_copy(cpi->mb.nmvjointcost, cc->nmvjointcost);
- vp9_copy(cpi->mb.nmvcosts, cc->nmvcosts);
- vp9_copy(cpi->mb.nmvcosts_hp, cc->nmvcosts_hp);
+
+ vpx_memcpy(cpi->nmvcosts[0], cc->nmvcosts[0],
+ MV_VALS * sizeof(*cc->nmvcosts[0]));
+ vpx_memcpy(cpi->nmvcosts[1], cc->nmvcosts[1],
+ MV_VALS * sizeof(*cc->nmvcosts[1]));
+ vpx_memcpy(cpi->nmvcosts_hp[0], cc->nmvcosts_hp[0],
+ MV_VALS * sizeof(*cc->nmvcosts_hp[0]));
+ vpx_memcpy(cpi->nmvcosts_hp[1], cc->nmvcosts_hp[1],
+ MV_VALS * sizeof(*cc->nmvcosts_hp[1]));
vp9_copy(cm->seg.pred_probs, cc->segment_pred_probs);
}
void vp9_new_framerate(VP9_COMP *cpi, double framerate) {
- cpi->oxcf.framerate = framerate < 0.1 ? 30 : framerate;
+ cpi->framerate = framerate < 0.1 ? 30 : framerate;
vp9_rc_update_framerate(cpi);
}
-int64_t vp9_rescale(int64_t val, int64_t num, int denom) {
- int64_t llnum = num;
- int64_t llden = denom;
- int64_t llval = val;
-
- return (llval * llnum / llden);
-}
-
static void set_tile_limits(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
VP9_COMMON *const cm = &cpi->common;
cpi->oxcf = *oxcf;
+ cpi->framerate = oxcf->init_framerate;
cm->profile = oxcf->profile;
cm->bit_depth = oxcf->bit_depth;
// Temporal scalability.
cpi->svc.number_temporal_layers = oxcf->ts_number_layers;
- if ((cpi->svc.number_temporal_layers > 1 &&
- cpi->oxcf.rc_mode == VPX_CBR) ||
- (cpi->svc.number_spatial_layers > 1 &&
- cpi->oxcf.mode == TWO_PASS_SECOND_BEST)) {
+ if ((cpi->svc.number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) ||
+ (cpi->svc.number_spatial_layers > 1 && cpi->oxcf.pass == 2)) {
vp9_init_layer_context(cpi);
}
set_tile_limits(cpi);
}
+static void set_rc_buffer_sizes(RATE_CONTROL *rc,
+ const VP9EncoderConfig *oxcf) {
+ const int64_t bandwidth = oxcf->target_bandwidth;
+ const int64_t starting = oxcf->starting_buffer_level_ms;
+ const int64_t optimal = oxcf->optimal_buffer_level_ms;
+ const int64_t maximum = oxcf->maximum_buffer_size_ms;
+
+ rc->starting_buffer_level = starting * bandwidth / 1000;
+ rc->optimal_buffer_level = (optimal == 0) ? bandwidth / 8
+ : optimal * bandwidth / 1000;
+ rc->maximum_buffer_size = (maximum == 0) ? bandwidth / 8
+ : maximum * bandwidth / 1000;
+}
+
void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) {
VP9_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc;
}
cpi->encode_breakout = cpi->oxcf.encode_breakout;
- // local file playback mode == really big buffer
- if (cpi->oxcf.rc_mode == VPX_VBR) {
- cpi->oxcf.starting_buffer_level_ms = 60000;
- cpi->oxcf.optimal_buffer_level_ms = 60000;
- cpi->oxcf.maximum_buffer_size_ms = 240000;
- }
-
- rc->starting_buffer_level = vp9_rescale(cpi->oxcf.starting_buffer_level_ms,
- cpi->oxcf.target_bandwidth, 1000);
+ set_rc_buffer_sizes(rc, &cpi->oxcf);
- // Set or reset optimal and maximum buffer levels.
- if (cpi->oxcf.optimal_buffer_level_ms == 0)
- rc->optimal_buffer_level = cpi->oxcf.target_bandwidth / 8;
- else
- rc->optimal_buffer_level = vp9_rescale(cpi->oxcf.optimal_buffer_level_ms,
- cpi->oxcf.target_bandwidth, 1000);
-
- if (cpi->oxcf.maximum_buffer_size_ms == 0)
- rc->maximum_buffer_size = cpi->oxcf.target_bandwidth / 8;
- else
- rc->maximum_buffer_size = vp9_rescale(cpi->oxcf.maximum_buffer_size_ms,
- cpi->oxcf.target_bandwidth, 1000);
// Under a configuration change, where maximum_buffer_size may change,
// keep buffer level clipped to the maximum allowed buffer size.
rc->bits_off_target = MIN(rc->bits_off_target, rc->maximum_buffer_size);
rc->buffer_level = MIN(rc->buffer_level, rc->maximum_buffer_size);
// Set up frame rate and related parameters rate control values.
- vp9_new_framerate(cpi, cpi->oxcf.framerate);
+ vp9_new_framerate(cpi, cpi->framerate);
// Set absolute upper and lower quality limits
rc->worst_quality = cpi->oxcf.worst_allowed_q;
vp9_rc_init(&cpi->oxcf, oxcf->pass, &cpi->rc);
cm->current_video_frame = 0;
-
- cpi->gold_is_last = 0;
- cpi->alt_is_last = 0;
- cpi->gold_is_alt = 0;
-
cpi->skippable_frame = 0;
// Create the encoder segmentation map and set all entries to 0
CHECK_MEM_ERROR(cm, cpi->coding_context.last_frame_seg_map_copy,
vpx_calloc(cm->mi_rows * cm->mi_cols, 1));
+ CHECK_MEM_ERROR(cm, cpi->nmvcosts[0],
+ vpx_calloc(MV_VALS, sizeof(*cpi->nmvcosts[0])));
+ CHECK_MEM_ERROR(cm, cpi->nmvcosts[1],
+ vpx_calloc(MV_VALS, sizeof(*cpi->nmvcosts[1])));
+ CHECK_MEM_ERROR(cm, cpi->nmvcosts_hp[0],
+ vpx_calloc(MV_VALS, sizeof(*cpi->nmvcosts_hp[0])));
+ CHECK_MEM_ERROR(cm, cpi->nmvcosts_hp[1],
+ vpx_calloc(MV_VALS, sizeof(*cpi->nmvcosts_hp[1])));
+ CHECK_MEM_ERROR(cm, cpi->nmvsadcosts[0],
+ vpx_calloc(MV_VALS, sizeof(*cpi->nmvsadcosts[0])));
+ CHECK_MEM_ERROR(cm, cpi->nmvsadcosts[1],
+ vpx_calloc(MV_VALS, sizeof(*cpi->nmvsadcosts[1])));
+ CHECK_MEM_ERROR(cm, cpi->nmvsadcosts_hp[0],
+ vpx_calloc(MV_VALS, sizeof(*cpi->nmvsadcosts_hp[0])));
+ CHECK_MEM_ERROR(cm, cpi->nmvsadcosts_hp[1],
+ vpx_calloc(MV_VALS, sizeof(*cpi->nmvsadcosts_hp[1])));
+
for (i = 0; i < (sizeof(cpi->mbgraph_stats) /
sizeof(cpi->mbgraph_stats[0])); i++) {
CHECK_MEM_ERROR(cm, cpi->mbgraph_stats[i].mb_stats,
cpi->first_time_stamp_ever = INT64_MAX;
cal_nmvjointsadcost(cpi->mb.nmvjointsadcost);
- cpi->mb.nmvcost[0] = &cpi->mb.nmvcosts[0][MV_MAX];
- cpi->mb.nmvcost[1] = &cpi->mb.nmvcosts[1][MV_MAX];
- cpi->mb.nmvsadcost[0] = &cpi->mb.nmvsadcosts[0][MV_MAX];
- cpi->mb.nmvsadcost[1] = &cpi->mb.nmvsadcosts[1][MV_MAX];
+ cpi->mb.nmvcost[0] = &cpi->nmvcosts[0][MV_MAX];
+ cpi->mb.nmvcost[1] = &cpi->nmvcosts[1][MV_MAX];
+ cpi->mb.nmvsadcost[0] = &cpi->nmvsadcosts[0][MV_MAX];
+ cpi->mb.nmvsadcost[1] = &cpi->nmvsadcosts[1][MV_MAX];
cal_nmvsadcosts(cpi->mb.nmvsadcost);
- cpi->mb.nmvcost_hp[0] = &cpi->mb.nmvcosts_hp[0][MV_MAX];
- cpi->mb.nmvcost_hp[1] = &cpi->mb.nmvcosts_hp[1][MV_MAX];
- cpi->mb.nmvsadcost_hp[0] = &cpi->mb.nmvsadcosts_hp[0][MV_MAX];
- cpi->mb.nmvsadcost_hp[1] = &cpi->mb.nmvsadcosts_hp[1][MV_MAX];
+ cpi->mb.nmvcost_hp[0] = &cpi->nmvcosts_hp[0][MV_MAX];
+ cpi->mb.nmvcost_hp[1] = &cpi->nmvcosts_hp[1][MV_MAX];
+ cpi->mb.nmvsadcost_hp[0] = &cpi->nmvsadcosts_hp[0][MV_MAX];
+ cpi->mb.nmvsadcost_hp[1] = &cpi->nmvsadcosts_hp[1][MV_MAX];
cal_nmvsadcosts_hp(cpi->mb.nmvsadcost_hp);
#if CONFIG_VP9_TEMPORAL_DENOISING
kf_list = fopen("kf_list.stt", "w");
#endif
- cpi->output_pkt_list = oxcf->output_pkt_list;
-
cpi->allow_encode_breakout = ENCODE_BREAKOUT_ENABLED;
if (oxcf->pass == 1) {
vp9_sub_pixel_avg_variance4x4,
vp9_sad4x4x3, vp9_sad4x4x8, vp9_sad4x4x4d)
- cpi->full_search_sad = vp9_full_search_sad;
- cpi->diamond_search_sad = vp9_diamond_search_sad;
- cpi->refining_search_sad = vp9_refining_search_sad;
-
/* vp9_init_quantizer() is first called here. Add check in
* vp9_frame_init_quantizer() so that vp9_init_quantizer is only
* called later when needed. This will avoid unnecessary calls of
cpi->rc.total_actual_bits, cm->base_qindex,
vp9_convert_qindex_to_q(cm->base_qindex),
(double)vp9_dc_quant(cm->base_qindex, 0) / 4.0,
+ vp9_convert_qindex_to_q(cpi->twopass.active_worst_quality),
cpi->rc.avg_q,
- vp9_convert_qindex_to_q(cpi->rc.ni_av_qi),
vp9_convert_qindex_to_q(cpi->oxcf.cq_level),
cpi->refresh_last_frame, cpi->refresh_golden_frame,
cpi->refresh_alt_ref_frame, cm->frame_type, cpi->rc.gfu_boost,
} while (loop);
}
-static void get_ref_frame_flags(VP9_COMP *cpi) {
- if (cpi->refresh_last_frame & cpi->refresh_golden_frame)
- cpi->gold_is_last = 1;
- else if (cpi->refresh_last_frame ^ cpi->refresh_golden_frame)
- cpi->gold_is_last = 0;
-
- if (cpi->refresh_last_frame & cpi->refresh_alt_ref_frame)
- cpi->alt_is_last = 1;
- else if (cpi->refresh_last_frame ^ cpi->refresh_alt_ref_frame)
- cpi->alt_is_last = 0;
+static int get_ref_frame_flags(const VP9_COMP *cpi) {
+ const int *const map = cpi->common.ref_frame_map;
+ const int gold_is_last = map[cpi->gld_fb_idx] == map[cpi->lst_fb_idx];
+ const int alt_is_last = map[cpi->alt_fb_idx] == map[cpi->lst_fb_idx];
+ const int gold_is_alt = map[cpi->gld_fb_idx] == map[cpi->alt_fb_idx];
+ int flags = VP9_ALT_FLAG | VP9_GOLD_FLAG | VP9_LAST_FLAG;
- if (cpi->refresh_alt_ref_frame & cpi->refresh_golden_frame)
- cpi->gold_is_alt = 1;
- else if (cpi->refresh_alt_ref_frame ^ cpi->refresh_golden_frame)
- cpi->gold_is_alt = 0;
-
- cpi->ref_frame_flags = VP9_ALT_FLAG | VP9_GOLD_FLAG | VP9_LAST_FLAG;
-
- if (cpi->gold_is_last)
- cpi->ref_frame_flags &= ~VP9_GOLD_FLAG;
+ if (gold_is_last)
+ flags &= ~VP9_GOLD_FLAG;
if (cpi->rc.frames_till_gf_update_due == INT_MAX &&
!is_spatial_svc(cpi))
- cpi->ref_frame_flags &= ~VP9_GOLD_FLAG;
+ flags &= ~VP9_GOLD_FLAG;
- if (cpi->alt_is_last)
- cpi->ref_frame_flags &= ~VP9_ALT_FLAG;
+ if (alt_is_last)
+ flags &= ~VP9_ALT_FLAG;
- if (cpi->gold_is_alt)
- cpi->ref_frame_flags &= ~VP9_ALT_FLAG;
+ if (gold_is_alt)
+ flags &= ~VP9_ALT_FLAG;
+
+ return flags;
}
static void set_ext_overrides(VP9_COMP *cpi) {
cm->ref_frame_sign_bias[ALTREF_FRAME] = arf_sign_bias;
}
+static void set_mv_search_params(VP9_COMP *cpi) {
+ const VP9_COMMON *const cm = &cpi->common;
+ const unsigned int max_mv_def = MIN(cm->width, cm->height);
+
+ // Default based on max resolution.
+ cpi->mv_step_param = vp9_init_search_range(max_mv_def);
+
+ if (cpi->sf.mv.auto_mv_step_size) {
+ if (frame_is_intra_only(cm)) {
+ // Initialize max_mv_magnitude for use in the first INTER frame
+ // after a key/intra-only frame.
+ cpi->max_mv_magnitude = max_mv_def;
+ } else {
+ if (cm->show_frame)
+ // Allow mv_steps to correspond to twice the max mv magnitude found
+ // in the previous frame, capped by the default max_mv_magnitude based
+ // on resolution.
+ cpi->mv_step_param =
+ vp9_init_search_range(MIN(max_mv_def, 2 * cpi->max_mv_magnitude));
+ cpi->max_mv_magnitude = 0;
+ }
+ }
+}
+
static void encode_frame_to_data_rate(VP9_COMP *cpi,
size_t *size,
uint8_t *dest,
unsigned int *frame_flags) {
VP9_COMMON *const cm = &cpi->common;
+ struct segmentation *const seg = &cm->seg;
TX_SIZE t;
int q;
int top_index;
int bottom_index;
- const SPEED_FEATURES *const sf = &cpi->sf;
- const unsigned int max_mv_def = MIN(cm->width, cm->height);
- struct segmentation *const seg = &cm->seg;
set_ext_overrides(cpi);
cpi->Source = vp9_scale_if_required(cm, cpi->un_scaled_source,
// Set default state for segment based loop filter update flags.
cm->lf.mode_ref_delta_update = 0;
- // Initialize cpi->mv_step_param to default based on max resolution.
- cpi->mv_step_param = vp9_init_search_range(max_mv_def);
- // Initialize cpi->max_mv_magnitude and cpi->mv_step_param if appropriate.
- if (sf->mv.auto_mv_step_size) {
- if (frame_is_intra_only(cm)) {
- // Initialize max_mv_magnitude for use in the first INTER frame
- // after a key/intra-only frame.
- cpi->max_mv_magnitude = max_mv_def;
- } else {
- if (cm->show_frame)
- // Allow mv_steps to correspond to twice the max mv magnitude found
- // in the previous frame, capped by the default max_mv_magnitude based
- // on resolution.
- cpi->mv_step_param = vp9_init_search_range(MIN(max_mv_def, 2 *
- cpi->max_mv_magnitude));
- cpi->max_mv_magnitude = 0;
- }
- }
+ set_mv_search_params(cpi);
// Set various flags etc to special state if it is a key frame.
if (frame_is_intra_only(cm)) {
cm->reset_frame_context = 2;
}
}
+ if (is_spatial_svc(cpi) && cm->error_resilient_mode == 0) {
+ cm->frame_context_idx = cpi->svc.spatial_layer_id;
+
+ // The probs will be updated based on the frame type of its previous
+ // frame if frame_parallel_decoding_mode is 0. The type may vary for
+ // the frame after a key frame in base layer since we may drop enhancement
+ // layers. So set frame_parallel_decoding_mode to 1 in this case.
+ if (cpi->svc.spatial_layer_id == 0 &&
+ cpi->svc.layer_context[0].last_frame_type == KEY_FRAME)
+ cm->frame_parallel_decoding_mode = 1;
+ else
+ cm->frame_parallel_decoding_mode = 0;
+ }
// Configure experimental use of segmentation for enhanced coding of
// static regions if indicated.
else
cpi->frame_flags &= ~FRAMEFLAGS_ALTREF;
- get_ref_frame_flags(cpi);
+ cpi->ref_frame_flags = get_ref_frame_flags(cpi);
cm->last_frame_type = cm->frame_type;
vp9_rc_postencode_update(cpi, *size);
cm->last_height = cm->height;
// reset to normal state now that we are done.
- if (!cm->show_existing_frame)
- cm->last_show_frame = cm->show_frame;
+ if (!cm->show_existing_frame) {
+ if (is_spatial_svc(cpi) && cm->error_resilient_mode == 0)
+ cm->last_show_frame = 0;
+ else
+ cm->last_show_frame = cm->show_frame;
+ }
if (cm->show_frame) {
vp9_swap_mi_and_prev_mi(cm);
if (cpi->use_svc)
vp9_inc_frame_in_layer(&cpi->svc);
}
+
+ if (is_spatial_svc(cpi))
+ cpi->svc.layer_context[cpi->svc.spatial_layer_id].last_frame_type =
+ cm->frame_type;
}
static void SvcEncode(VP9_COMP *cpi, size_t *size, uint8_t *dest,
cm->seg.update_data;
}
-void adjust_frame_rate(VP9_COMP *cpi) {
+void adjust_frame_rate(VP9_COMP *cpi,
+ const struct lookahead_entry *source) {
int64_t this_duration;
int step = 0;
- if (cpi->source->ts_start == cpi->first_time_stamp_ever) {
- this_duration = cpi->source->ts_end - cpi->source->ts_start;
+ if (source->ts_start == cpi->first_time_stamp_ever) {
+ this_duration = source->ts_end - source->ts_start;
step = 1;
} else {
int64_t last_duration = cpi->last_end_time_stamp_seen
- cpi->last_time_stamp_seen;
- this_duration = cpi->source->ts_end - cpi->last_end_time_stamp_seen;
+ this_duration = source->ts_end - cpi->last_end_time_stamp_seen;
// do a step update if the duration changes by 10%
if (last_duration)
// Average this frame's rate into the last second's average
// frame rate. If we haven't seen 1 second yet, then average
// over the whole interval seen.
- const double interval = MIN((double)(cpi->source->ts_end
+ const double interval = MIN((double)(source->ts_end
- cpi->first_time_stamp_ever), 10000000.0);
- double avg_duration = 10000000.0 / cpi->oxcf.framerate;
+ double avg_duration = 10000000.0 / cpi->framerate;
avg_duration *= (interval - avg_duration + this_duration);
avg_duration /= interval;
vp9_new_framerate(cpi, 10000000.0 / avg_duration);
}
}
- cpi->last_time_stamp_seen = cpi->source->ts_start;
- cpi->last_end_time_stamp_seen = cpi->source->ts_end;
+ cpi->last_time_stamp_seen = source->ts_start;
+ cpi->last_end_time_stamp_seen = source->ts_end;
}
// Returns 0 if this is not an alt ref else the offset of the source frame
return arf_src_index;
}
-static void check_src_altref(VP9_COMP *cpi) {
+static void check_src_altref(VP9_COMP *cpi,
+ const struct lookahead_entry *source) {
RATE_CONTROL *const rc = &cpi->rc;
if (cpi->oxcf.pass == 2) {
(gf_group->update_type[gf_group->index] == OVERLAY_UPDATE);
} else {
rc->is_src_frame_alt_ref = cpi->alt_ref_source &&
- (cpi->source == cpi->alt_ref_source);
+ (source == cpi->alt_ref_source);
}
if (rc->is_src_frame_alt_ref) {
int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
size_t *size, uint8_t *dest,
int64_t *time_stamp, int64_t *time_end, int flush) {
+ const VP9EncoderConfig *const oxcf = &cpi->oxcf;
VP9_COMMON *const cm = &cpi->common;
MACROBLOCKD *const xd = &cpi->mb.e_mbd;
RATE_CONTROL *const rc = &cpi->rc;
struct vpx_usec_timer cmptimer;
YV12_BUFFER_CONFIG *force_src_buffer = NULL;
+ struct lookahead_entry *last_source = NULL;
+ struct lookahead_entry *source = NULL;
MV_REFERENCE_FRAME ref_frame;
int arf_src_index;
- if (!cpi)
- return -1;
-
- if (is_spatial_svc(cpi) && cpi->oxcf.pass == 2) {
+ if (is_spatial_svc(cpi) && oxcf->pass == 2) {
#if CONFIG_SPATIAL_SVC
vp9_svc_lookahead_peek(cpi, cpi->lookahead, 0, 1);
#endif
vpx_usec_timer_start(&cmptimer);
- cpi->source = NULL;
- cpi->last_source = NULL;
-
vp9_set_high_precision_mv(cpi, ALTREF_HIGH_PRECISION_MV);
// Normal defaults
#if CONFIG_SPATIAL_SVC
if (is_spatial_svc(cpi))
- cpi->source = vp9_svc_lookahead_peek(cpi, cpi->lookahead,
- arf_src_index, 0);
+ source = vp9_svc_lookahead_peek(cpi, cpi->lookahead, arf_src_index, 0);
else
#endif
- cpi->source = vp9_lookahead_peek(cpi->lookahead, arf_src_index);
- if (cpi->source != NULL) {
- cpi->alt_ref_source = cpi->source;
+ source = vp9_lookahead_peek(cpi->lookahead, arf_src_index);
+ if (source != NULL) {
+ cpi->alt_ref_source = source;
#if CONFIG_SPATIAL_SVC
if (is_spatial_svc(cpi) && cpi->svc.spatial_layer_id > 0) {
int i;
// Reference a hidden frame from a lower layer
for (i = cpi->svc.spatial_layer_id - 1; i >= 0; --i) {
- if (cpi->oxcf.ss_play_alternate[i]) {
+ if (oxcf->ss_play_alternate[i]) {
cpi->gld_fb_idx = cpi->svc.layer_context[i].alt_ref_idx;
break;
}
cpi->svc.layer_context[cpi->svc.spatial_layer_id].has_alt_frame = 1;
#endif
- if (cpi->oxcf.arnr_max_frames > 0) {
+ if (oxcf->arnr_max_frames > 0) {
// Produce the filtered ARF frame.
vp9_temporal_filter(cpi, arf_src_index);
vp9_extend_frame_borders(&cpi->alt_ref_buffer);
}
}
- if (!cpi->source) {
+ if (!source) {
// Get last frame source.
if (cm->current_video_frame > 0) {
#if CONFIG_SPATIAL_SVC
if (is_spatial_svc(cpi))
- cpi->last_source = vp9_svc_lookahead_peek(cpi, cpi->lookahead, -1, 0);
+ last_source = vp9_svc_lookahead_peek(cpi, cpi->lookahead, -1, 0);
else
#endif
- cpi->last_source = vp9_lookahead_peek(cpi->lookahead, -1);
- if (cpi->last_source == NULL)
+ last_source = vp9_lookahead_peek(cpi->lookahead, -1);
+ if (last_source == NULL)
return -1;
}
// Read in the source frame.
#if CONFIG_SPATIAL_SVC
if (is_spatial_svc(cpi))
- cpi->source = vp9_svc_lookahead_pop(cpi, cpi->lookahead, flush);
+ source = vp9_svc_lookahead_pop(cpi, cpi->lookahead, flush);
else
#endif
- cpi->source = vp9_lookahead_pop(cpi->lookahead, flush);
- if (cpi->source != NULL) {
+ source = vp9_lookahead_pop(cpi->lookahead, flush);
+ if (source != NULL) {
cm->show_frame = 1;
cm->intra_only = 0;
// Check to see if the frame should be encoded as an arf overlay.
- check_src_altref(cpi);
+ check_src_altref(cpi, source);
}
}
- if (cpi->source) {
+ if (source) {
cpi->un_scaled_source = cpi->Source = force_src_buffer ? force_src_buffer
- : &cpi->source->img;
+ : &source->img;
- if (cpi->last_source != NULL) {
- cpi->unscaled_last_source = &cpi->last_source->img;
- } else {
- cpi->unscaled_last_source = NULL;
- }
+ cpi->unscaled_last_source = last_source != NULL ? &last_source->img : NULL;
- *time_stamp = cpi->source->ts_start;
- *time_end = cpi->source->ts_end;
- *frame_flags =
- (cpi->source->flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0;
+ *time_stamp = source->ts_start;
+ *time_end = source->ts_end;
+ *frame_flags = (source->flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0;
} else {
*size = 0;
- if (flush && cpi->oxcf.pass == 1 && !cpi->twopass.first_pass_done) {
+ if (flush && oxcf->pass == 1 && !cpi->twopass.first_pass_done) {
vp9_end_first_pass(cpi); /* get last stats packet */
cpi->twopass.first_pass_done = 1;
}
return -1;
}
- if (cpi->source->ts_start < cpi->first_time_stamp_ever) {
- cpi->first_time_stamp_ever = cpi->source->ts_start;
- cpi->last_end_time_stamp_seen = cpi->source->ts_start;
+ if (source->ts_start < cpi->first_time_stamp_ever) {
+ cpi->first_time_stamp_ever = source->ts_start;
+ cpi->last_end_time_stamp_seen = source->ts_start;
}
// Clear down mmx registers
// adjust frame rates based on timestamps given
if (cm->show_frame) {
- adjust_frame_rate(cpi);
+ adjust_frame_rate(cpi, source);
}
if (cpi->svc.number_temporal_layers > 1 &&
- cpi->oxcf.rc_mode == VPX_CBR) {
+ oxcf->rc_mode == VPX_CBR) {
vp9_update_temporal_layer_framerate(cpi);
vp9_restore_layer_context(cpi);
}
if (!cpi->use_svc && cpi->multi_arf_allowed) {
if (cm->frame_type == KEY_FRAME) {
init_buffer_indices(cpi);
- } else if (cpi->oxcf.pass == 2) {
+ } else if (oxcf->pass == 2) {
const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
cpi->alt_fb_idx = gf_group->arf_ref_idx[gf_group->index];
}
cpi->frame_flags = *frame_flags;
- if (cpi->oxcf.pass == 2 &&
+ if (oxcf->pass == 2 &&
cm->current_video_frame == 0 &&
- cpi->oxcf.allow_spatial_resampling &&
- cpi->oxcf.rc_mode == VPX_VBR) {
+ oxcf->allow_spatial_resampling &&
+ oxcf->rc_mode == VPX_VBR) {
// Internal scaling is triggered on the first frame.
- vp9_set_size_literal(cpi, cpi->oxcf.scaled_frame_width,
- cpi->oxcf.scaled_frame_height);
+ vp9_set_size_literal(cpi, oxcf->scaled_frame_width,
+ oxcf->scaled_frame_height);
}
// Reset the frame pointers to the current frame size
set_ref_ptrs(cm, xd, LAST_FRAME, LAST_FRAME);
- if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
+ if (oxcf->aq_mode == VARIANCE_AQ) {
vp9_vaq_init();
}
- if (cpi->oxcf.pass == 1 &&
+ if (oxcf->pass == 1 &&
(!cpi->use_svc || is_spatial_svc(cpi))) {
- const int lossless = is_lossless_requested(&cpi->oxcf);
+ const int lossless = is_lossless_requested(oxcf);
cpi->mb.fwd_txm4x4 = lossless ? vp9_fwht4x4 : vp9_fdct4x4;
cpi->mb.itxm_add = lossless ? vp9_iwht4x4_add : vp9_idct4x4_add;
- vp9_first_pass(cpi);
- } else if (cpi->oxcf.pass == 2 &&
+ vp9_first_pass(cpi, source);
+ } else if (oxcf->pass == 2 &&
(!cpi->use_svc || is_spatial_svc(cpi))) {
Pass2Encode(cpi, size, dest, frame_flags);
} else if (cpi->use_svc) {
// Save layer specific state.
if ((cpi->svc.number_temporal_layers > 1 &&
- cpi->oxcf.rc_mode == VPX_CBR) ||
- (cpi->svc.number_spatial_layers > 1 && cpi->oxcf.pass == 2)) {
+ oxcf->rc_mode == VPX_CBR) ||
+ (cpi->svc.number_spatial_layers > 1 && oxcf->pass == 2)) {
vp9_save_layer_context(cpi);
}
vpx_usec_timer_mark(&cmptimer);
cpi->time_compress_data += vpx_usec_timer_elapsed(&cmptimer);
- if (cpi->b_calculate_psnr && cpi->oxcf.pass != 1 && cm->show_frame)
+ if (cpi->b_calculate_psnr && oxcf->pass != 1 && cm->show_frame)
generate_psnr_packet(cpi);
#if CONFIG_INTERNAL_STATS
- if (cpi->oxcf.pass != 1) {
+ if (oxcf->pass != 1) {
cpi->bytes += (int)(*size);
if (cm->show_frame) {
cpi->totalp_sq_error += psnr2.sse[0];
cpi->totalp_samples += psnr2.samples[0];
- frame_ssim2 = vp9_calc_ssim(orig, recon, 1, &weight);
+ frame_ssim2 = vp9_calc_ssim(orig, recon, &weight);
cpi->summed_quality += frame_ssim2 * weight;
cpi->summed_weights += weight;
- frame_ssim2 = vp9_calc_ssim(orig, &cm->post_proc_buffer, 1, &weight);
+ frame_ssim2 = vp9_calc_ssim(orig, &cm->post_proc_buffer, &weight);
cpi->summedp_quality += frame_ssim2 * weight;
cpi->summedp_weights += weight;
#include "vp9/vp9_iface_common.h"
struct vp9_extracfg {
- struct vpx_codec_pkt_list *pkt_list;
int cpu_used; // available cpu percentage in 1/16
unsigned int enable_auto_alt_ref;
unsigned int noise_sensitivity;
vp9e_tune_content content;
};
-struct extraconfig_map {
- unsigned int usage;
- struct vp9_extracfg cfg;
-};
-
-static const struct extraconfig_map extracfg_map[] = {
- {
- 0,
- { // NOLINT
- NULL,
- 0, // cpu_used
- 1, // enable_auto_alt_ref
- 0, // noise_sensitivity
- 0, // sharpness
- 0, // static_thresh
- 0, // tile_columns
- 0, // tile_rows
- 7, // arnr_max_frames
- 5, // arnr_strength
- 3, // arnr_type
- VP8_TUNE_PSNR, // tuning
- 10, // cq_level
- 0, // rc_max_intra_bitrate_pct
- 0, // lossless
- 0, // frame_parallel_decoding_mode
- NO_AQ, // aq_mode
- 0, // frame_periodic_delta_q
- BITS_8, // Bit depth
- VP9E_CONTENT_DEFAULT // content
- }
- }
+static struct vp9_extracfg default_extra_cfg = {
+ 0, // cpu_used
+ 1, // enable_auto_alt_ref
+ 0, // noise_sensitivity
+ 0, // sharpness
+ 0, // static_thresh
+ 0, // tile_columns
+ 0, // tile_rows
+ 7, // arnr_max_frames
+ 5, // arnr_strength
+ 3, // arnr_type
+ VP8_TUNE_PSNR, // tuning
+ 10, // cq_level
+ 0, // rc_max_intra_bitrate_pct
+ 0, // lossless
+ 0, // frame_parallel_decoding_mode
+ NO_AQ, // aq_mode
+ 0, // frame_periodic_delta_q
+ BITS_8, // Bit depth
+ VP9E_CONTENT_DEFAULT // content
};
struct vpx_codec_alg_priv {
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->g_error_resilient == 0)
+ ERROR("Multiple frame contexts are not supported for more than 3 layers");
#endif
RANGE_CHECK(cfg, ts_number_layers, 1, VPX_TS_MAX_LAYERS);
VP9EncoderConfig *oxcf,
const vpx_codec_enc_cfg_t *cfg,
const struct vp9_extracfg *extra_cfg) {
+ const int is_vbr = cfg->rc_end_usage == VPX_VBR;
oxcf->profile = cfg->g_profile;
oxcf->width = cfg->g_w;
oxcf->height = cfg->g_h;
oxcf->bit_depth = extra_cfg->bit_depth;
// guess a frame rate if out of whack, use 30
- oxcf->framerate = (double)cfg->g_timebase.den / cfg->g_timebase.num;
- if (oxcf->framerate > 180)
- oxcf->framerate = 30;
+ oxcf->init_framerate = (double)cfg->g_timebase.den / cfg->g_timebase.num;
+ if (oxcf->init_framerate > 180)
+ oxcf->init_framerate = 30;
+
+ oxcf->mode = GOOD;
switch (cfg->g_pass) {
case VPX_RC_ONE_PASS:
- oxcf->mode = ONE_PASS_GOOD;
oxcf->pass = 0;
break;
case VPX_RC_FIRST_PASS:
- oxcf->mode = TWO_PASS_FIRST;
oxcf->pass = 1;
break;
case VPX_RC_LAST_PASS:
- oxcf->mode = TWO_PASS_SECOND_BEST;
oxcf->pass = 2;
break;
}
oxcf->scaled_frame_width = cfg->rc_scaled_width;
oxcf->scaled_frame_height = cfg->rc_scaled_height;
- oxcf->maximum_buffer_size_ms = cfg->rc_buf_sz;
- oxcf->starting_buffer_level_ms = cfg->rc_buf_initial_sz;
- oxcf->optimal_buffer_level_ms = cfg->rc_buf_optimal_sz;
+ oxcf->maximum_buffer_size_ms = is_vbr ? 240000 : cfg->rc_buf_sz;
+ oxcf->starting_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_initial_sz;
+ oxcf->optimal_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_optimal_sz;
oxcf->drop_frames_water_mark = cfg->rc_dropframe_thresh;
oxcf->sharpness = extra_cfg->sharpness;
oxcf->two_pass_stats_in = cfg->rc_twopass_stats_in;
- oxcf->output_pkt_list = extra_cfg->pkt_list;
#if CONFIG_FP_MB_STATS
oxcf->firstpass_mb_stats_in = cfg->rc_firstpass_mb_stats_in;
(void)data;
if (ctx->priv == NULL) {
- int i;
- vpx_codec_enc_cfg_t *cfg;
struct vpx_codec_alg_priv *priv = calloc(1, sizeof(*priv));
if (priv == NULL)
ctx->priv = &priv->base;
ctx->priv->sz = sizeof(*ctx->priv);
- ctx->priv->iface = ctx->iface;
ctx->priv->alg_priv = priv;
ctx->priv->init_flags = ctx->init_flags;
ctx->priv->enc.total_encoders = 1;
ctx->config.enc = &ctx->priv->alg_priv->cfg;
}
- cfg = &ctx->priv->alg_priv->cfg;
-
- // Select the extra vp6 configuration table based on the current
- // usage value. If the current usage value isn't found, use the
- // values for usage case 0.
- for (i = 0;
- extracfg_map[i].usage && extracfg_map[i].usage != cfg->g_usage;
- ++i) {}
-
- priv->extra_cfg = extracfg_map[i].cfg;
- priv->extra_cfg.pkt_list = &priv->pkt_list.head;
+ priv->extra_cfg = default_extra_cfg;
vp9_initialize_enc();
&ctx->priv->alg_priv->cfg,
&ctx->priv->alg_priv->extra_cfg);
cpi = vp9_create_compressor(&ctx->priv->alg_priv->oxcf);
- if (cpi == NULL)
+ if (cpi == NULL) {
res = VPX_CODEC_MEM_ERROR;
- else
+ } else {
+ cpi->output_pkt_list = &priv->pkt_list.head;
ctx->priv->alg_priv->cpi = cpi;
+ }
}
}
return VPX_CODEC_OK;
}
-static void pick_quickcompress_mode(vpx_codec_alg_priv_t *ctx,
+static void pick_quickcompress_mode(vpx_codec_alg_priv_t *ctx,
unsigned long duration,
unsigned long deadline) {
- // Use best quality mode if no deadline is given.
- MODE new_qc = ONE_PASS_BEST;
-
- if (deadline) {
- // Convert duration parameter from stream timebase to microseconds
- const uint64_t duration_us = (uint64_t)duration * 1000000 *
- (uint64_t)ctx->cfg.g_timebase.num /
- (uint64_t)ctx->cfg.g_timebase.den;
-
- // If the deadline is more that the duration this frame is to be shown,
- // use good quality mode. Otherwise use realtime mode.
- new_qc = (deadline > duration_us) ? ONE_PASS_GOOD : REALTIME;
- }
+ MODE new_mode = BEST;
- if (ctx->cfg.g_pass == VPX_RC_FIRST_PASS)
- new_qc = TWO_PASS_FIRST;
- else if (ctx->cfg.g_pass == VPX_RC_LAST_PASS)
- new_qc = (new_qc == ONE_PASS_BEST) ? TWO_PASS_SECOND_BEST
- : TWO_PASS_SECOND_GOOD;
+ switch (ctx->cfg.g_pass) {
+ case VPX_RC_ONE_PASS:
+ if (deadline > 0) {
+ const vpx_codec_enc_cfg_t *const cfg = &ctx->cfg;
+
+ // Convert duration parameter from stream timebase to microseconds.
+ const uint64_t duration_us = (uint64_t)duration * 1000000 *
+ (uint64_t)cfg->g_timebase.num /(uint64_t)cfg->g_timebase.den;
+
+ // If the deadline is more that the duration this frame is to be shown,
+ // use good quality mode. Otherwise use realtime mode.
+ new_mode = (deadline > duration_us) ? GOOD : REALTIME;
+ } else {
+ new_mode = BEST;
+ }
+ break;
+ case VPX_RC_FIRST_PASS:
+ break;
+ case VPX_RC_LAST_PASS:
+ new_mode = deadline > 0 ? GOOD : BEST;
+ break;
+ }
- if (ctx->oxcf.mode != new_qc) {
- ctx->oxcf.mode = new_qc;
+ if (ctx->oxcf.mode != new_mode) {
+ ctx->oxcf.mode = new_mode;
vp9_change_config(ctx->cpi, &ctx->oxcf);
}
}
}
// vp9 uses 10,000,000 ticks/second as time stamp
-#define TICKS_PER_SEC 10000000
+#define TICKS_PER_SEC 10000000LL
static int64_t timebase_units_to_ticks(const vpx_rational_t *timebase,
int64_t n) {
cx_data_sz -= size;
#if CONFIG_SPATIAL_SVC
if (is_spatial_svc(cpi)) {
- vpx_codec_cx_pkt_t pkt = {0};
+ vpx_codec_cx_pkt_t pkt;
int i;
+ vp9_zero(pkt);
pkt.kind = VPX_CODEC_SPATIAL_SVC_LAYER_SIZES;
for (i = 0; i < cpi->svc.number_spatial_layers; ++i) {
pkt.data.layer_sizes[i] = cpi->svc.layer_context[i].layer_size;
encoder_destroy, // vpx_codec_destroy_fn_t
encoder_ctrl_maps, // vpx_codec_ctrl_fn_map_t
{ // NOLINT
- NOT_IMPLEMENTED, // vpx_codec_peek_si_fn_t
- NOT_IMPLEMENTED, // vpx_codec_get_si_fn_t
- NOT_IMPLEMENTED, // vpx_codec_decode_fn_t
- NOT_IMPLEMENTED, // vpx_codec_frame_get_fn_t
- NOT_IMPLEMENTED // vpx_codec_set_fb_fn_t
+ NULL, // vpx_codec_peek_si_fn_t
+ NULL, // vpx_codec_get_si_fn_t
+ NULL, // vpx_codec_decode_fn_t
+ NULL, // vpx_codec_frame_get_fn_t
+ NULL // vpx_codec_set_fb_fn_t
},
{ // NOLINT
1, // 1 cfg map
encoder_encode, // vpx_codec_encode_fn_t
encoder_get_cxdata, // vpx_codec_get_cx_data_fn_t
encoder_set_config, // vpx_codec_enc_config_set_fn_t
- NOT_IMPLEMENTED, // vpx_codec_get_global_headers_fn_t
+ NULL, // vpx_codec_get_global_headers_fn_t
encoder_get_preview, // vpx_codec_get_preview_frame_fn_t
- NOT_IMPLEMENTED // vpx_codec_enc_mr_get_mem_loc_fn_t
+ NULL // vpx_codec_enc_mr_get_mem_loc_fn_t
}
};