temporal_layers_->ConfigureBitrates(new_bitrate_kbit, codec_.maxBitrate,
new_framerate, config_);
codec_.maxFramerate = new_framerate;
+ quality_scaler_.ReportFramerate(new_framerate);
// update encoder context
if (vpx_codec_enc_config_set(encoder_, config_)) {
// Creating a wrapper to the image - setting image data to NULL. Actual
// pointer will be set in encode. Setting align to 1, as it is meaningless
// (actual memory is not allocated).
- raw_ = vpx_img_wrap(NULL, IMG_FMT_I420, codec_.width, codec_.height,
+ raw_ = vpx_img_wrap(NULL, VPX_IMG_FMT_I420, codec_.width, codec_.height,
1, NULL);
// populate encoder configuration with default values
if (vpx_codec_enc_config_default(vpx_codec_vp8_cx(), config_, 0)) {
30 : 0;
config_->rc_end_usage = VPX_CBR;
config_->g_pass = VPX_RC_ONE_PASS;
- config_->rc_resize_allowed = inst->codecSpecific.VP8.automaticResizeOn ?
- 1 : 0;
+ // Handle resizing outside of libvpx.
+ config_->rc_resize_allowed = 0;
config_->rc_min_quantizer = 2;
config_->rc_max_quantizer = inst->qpMax;
config_->rc_undershoot_pct = 100;
cpu_speed_ = -12;
#endif
rps_->Init();
+ quality_scaler_.Init(codec_.qpMax);
+ quality_scaler_.ReportFramerate(codec_.maxFramerate);
return InitAndSetControlSettings(inst);
}
vpx_codec_control(encoder_, VP8E_SET_MAX_INTRA_BITRATE_PCT,
rc_max_intra_target_);
inited_ = true;
+
return WEBRTC_VIDEO_CODEC_OK;
}
return (targetPct < minIntraTh) ? minIntraTh: targetPct;
}
-int VP8EncoderImpl::Encode(const I420VideoFrame& input_image,
+int VP8EncoderImpl::Encode(const I420VideoFrame& input_frame,
const CodecSpecificInfo* codec_specific_info,
const std::vector<VideoFrameType>* frame_types) {
- TRACE_EVENT1("webrtc", "VP8::Encode", "timestamp", input_image.timestamp());
+ TRACE_EVENT1("webrtc", "VP8::Encode", "timestamp", input_frame.timestamp());
if (!inited_) {
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
}
- if (input_image.IsZeroSize()) {
+ if (input_frame.IsZeroSize()) {
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
}
if (encoded_complete_callback_ == NULL) {
frame_type = (*frame_types)[0];
}
+ const I420VideoFrame& frame =
+ config_->rc_dropframe_thresh > 0 &&
+ codec_.codecSpecific.VP8.automaticResizeOn
+ ? quality_scaler_.GetScaledFrame(input_frame)
+ : input_frame;
+
// Check for change in frame size.
- if (input_image.width() != codec_.width ||
- input_image.height() != codec_.height) {
- int ret = UpdateCodecFrameSize(input_image);
+ if (frame.width() != codec_.width ||
+ frame.height() != codec_.height) {
+ int ret = UpdateCodecFrameSize(frame);
if (ret < 0) {
return ret;
}
}
// Image in vpx_image_t format.
- // Input image is const. VP8's raw image is not defined as const.
- raw_->planes[PLANE_Y] = const_cast<uint8_t*>(input_image.buffer(kYPlane));
- raw_->planes[PLANE_U] = const_cast<uint8_t*>(input_image.buffer(kUPlane));
- raw_->planes[PLANE_V] = const_cast<uint8_t*>(input_image.buffer(kVPlane));
+ // Input frame is const. VP8's raw frame is not defined as const.
+ raw_->planes[VPX_PLANE_Y] = const_cast<uint8_t*>(frame.buffer(kYPlane));
+ raw_->planes[VPX_PLANE_U] = const_cast<uint8_t*>(frame.buffer(kUPlane));
+ raw_->planes[VPX_PLANE_V] = const_cast<uint8_t*>(frame.buffer(kVPlane));
// TODO(mikhal): Stride should be set in initialization.
- raw_->stride[VPX_PLANE_Y] = input_image.stride(kYPlane);
- raw_->stride[VPX_PLANE_U] = input_image.stride(kUPlane);
- raw_->stride[VPX_PLANE_V] = input_image.stride(kVPlane);
+ raw_->stride[VPX_PLANE_Y] = frame.stride(kYPlane);
+ raw_->stride[VPX_PLANE_U] = frame.stride(kUPlane);
+ raw_->stride[VPX_PLANE_V] = frame.stride(kVPlane);
- int flags = temporal_layers_->EncodeFlags(input_image.timestamp());
+ int flags = temporal_layers_->EncodeFlags(frame.timestamp());
bool send_keyframe = (frame_type == kKeyFrame);
if (send_keyframe) {
codec_specific_info->codecSpecific.VP8.pictureIdRPSI);
}
if (codec_specific_info->codecSpecific.VP8.hasReceivedSLI) {
- sendRefresh = rps_->ReceivedSLI(input_image.timestamp());
+ sendRefresh = rps_->ReceivedSLI(frame.timestamp());
}
}
flags = rps_->EncodeFlags(picture_id_, sendRefresh,
- input_image.timestamp());
+ frame.timestamp());
}
// TODO(holmer): Ideally the duration should be the timestamp diff of this
}
timestamp_ += duration;
- return GetEncodedPartitions(input_image);
+ return GetEncodedPartitions(frame);
}
int VP8EncoderImpl::UpdateCodecFrameSize(const I420VideoFrame& input_image) {
encoded_image_._encodedWidth = codec_.width;
encoded_complete_callback_->Encoded(encoded_image_, &codec_specific,
&frag_info);
+ int qp;
+ vpx_codec_control(encoder_, VP8E_GET_LAST_QUANTIZER_64, &qp);
+ quality_scaler_.ReportEncodedFrame(qp);
+ } else {
+ quality_scaler_.ReportDroppedFrame();
}
return WEBRTC_VIDEO_CODEC_OK;
}