Don't buffer encoded frames.

Pass encoded frames to packetizer immediately if encoder is configured
to drop whole superframe.

Bug: webrtc:9950
Change-Id: Iedee9618bb146307efd5a86cb35bf14b5e64b341
Reviewed-on: https://webrtc-review.googlesource.com/c/109002
Commit-Queue: Sergey Silkin <ssilkin@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25771}
This commit is contained in:
Sergey Silkin
2018-11-23 13:59:24 +01:00
committed by Commit Bot
parent 885cf60106
commit 88ce4ef46e
2 changed files with 31 additions and 17 deletions

View File

@ -158,6 +158,8 @@ VP9EncoderImpl::VP9EncoderImpl(const cricket::VideoCodec& codec)
field_trial::IsEnabled("WebRTC-Vp9ExternalRefCtrl")),
trusted_rate_controller_(
field_trial::IsEnabled(kVp9TrustedRateControllerFieldTrial)),
full_superframe_drop_(true),
first_frame_in_picture_(true),
is_flexible_mode_(false) {
memset(&codec_, 0, sizeof(codec_));
memset(&svc_params_, 0, sizeof(vpx_svc_extra_cfg_t));
@ -619,7 +621,8 @@ int VP9EncoderImpl::InitAndSetControlSettings(const VideoCodec* inst) {
// quality flickering and is not compatible with RTP non-flexible mode.
vpx_svc_frame_drop_t svc_drop_frame;
memset(&svc_drop_frame, 0, sizeof(svc_drop_frame));
svc_drop_frame.framedrop_mode = FULL_SUPERFRAME_DROP;
svc_drop_frame.framedrop_mode =
full_superframe_drop_ ? FULL_SUPERFRAME_DROP : CONSTRAINED_LAYER_DROP;
svc_drop_frame.max_consec_drop = std::numeric_limits<int>::max();
for (size_t i = 0; i < num_spatial_layers_; ++i) {
svc_drop_frame.framedrop_thresh[i] = config_->rc_dropframe_thresh;
@ -789,6 +792,8 @@ int VP9EncoderImpl::Encode(const VideoFrame& input_image,
vpx_codec_control(encoder_, VP9E_SET_SVC_REF_FRAME_CONFIG, &ref_config);
}
first_frame_in_picture_ = true;
// TODO(ssilkin): Frame duration should be specified per spatial layer
// since their frame rate can be different. For now calculate frame duration
// based on target frame rate of the highest spatial layer, which frame rate
@ -814,8 +819,10 @@ int VP9EncoderImpl::Encode(const VideoFrame& input_image,
}
timestamp_ += duration;
const bool end_of_picture = true;
DeliverBufferedFrame(end_of_picture);
if (!full_superframe_drop_) {
const bool end_of_picture = true;
DeliverBufferedFrame(end_of_picture);
}
return WEBRTC_VIDEO_CODEC_OK;
}
@ -823,13 +830,12 @@ int VP9EncoderImpl::Encode(const VideoFrame& input_image,
void VP9EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
absl::optional<int>* spatial_idx,
const vpx_codec_cx_pkt& pkt,
uint32_t timestamp,
bool first_frame_in_picture) {
uint32_t timestamp) {
RTC_CHECK(codec_specific != nullptr);
codec_specific->codecType = kVideoCodecVP9;
CodecSpecificInfoVP9* vp9_info = &(codec_specific->codecSpecific.VP9);
vp9_info->first_frame_in_picture = first_frame_in_picture;
vp9_info->first_frame_in_picture = first_frame_in_picture_;
vp9_info->flexible_mode = is_flexible_mode_;
vp9_info->ss_data_available =
(pkt.data.frame.flags & VPX_FRAME_IS_KEY) ? true : false;
@ -860,7 +866,7 @@ void VP9EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
if (pkt.data.frame.flags & VPX_FRAME_IS_KEY) {
pics_since_key_ = 0;
} else if (first_frame_in_picture) {
} else if (first_frame_in_picture_) {
++pics_since_key_;
}
@ -876,7 +882,7 @@ void VP9EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
// if low layer frame is lost) then receiver won't be able to decode next high
// layer frame which uses ILP.
vp9_info->inter_layer_predicted =
first_frame_in_picture ? false : is_inter_layer_pred_allowed;
first_frame_in_picture_ ? false : is_inter_layer_pred_allowed;
// Mark all low spatial layer frames as references (not just frames of
// active low spatial layers) if inter-layer prediction is enabled since
@ -920,6 +926,8 @@ void VP9EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
vp9_info->gof.CopyGofInfoVP9(gof_);
}
}
first_frame_in_picture_ = false;
}
void VP9EncoderImpl::FillReferenceIndices(const vpx_codec_cx_pkt& pkt,
@ -1146,12 +1154,11 @@ int VP9EncoderImpl::GetEncodedLayerFrame(const vpx_codec_cx_pkt* pkt) {
vpx_svc_layer_id_t layer_id = {0};
vpx_codec_control(encoder_, VP9E_GET_SVC_LAYER_ID, &layer_id);
const bool first_frame_in_picture = encoded_image_._length == 0;
// Ensure we don't buffer layers of previous picture (superframe).
RTC_DCHECK(first_frame_in_picture || layer_id.spatial_layer_id > 0);
const bool end_of_picture = false;
DeliverBufferedFrame(end_of_picture);
if (!full_superframe_drop_) {
// Deliver buffered low spatial layer frame.
const bool end_of_picture = false;
DeliverBufferedFrame(end_of_picture);
}
if (pkt->data.frame.sz > encoded_image_._size) {
delete[] encoded_image_._buffer;
@ -1177,7 +1184,7 @@ int VP9EncoderImpl::GetEncodedLayerFrame(const vpx_codec_cx_pkt* pkt) {
memset(&codec_specific_, 0, sizeof(codec_specific_));
absl::optional<int> spatial_index;
PopulateCodecSpecific(&codec_specific_, &spatial_index, *pkt,
input_image_->timestamp(), first_frame_in_picture);
input_image_->timestamp());
encoded_image_.SetSpatialIndex(spatial_index);
if (is_flexible_mode_) {
@ -1201,6 +1208,12 @@ int VP9EncoderImpl::GetEncodedLayerFrame(const vpx_codec_cx_pkt* pkt) {
encoded_image_.qp_ = qp;
encoded_image_.SetColorSpace(input_image_->color_space());
if (full_superframe_drop_) {
const bool end_of_picture = encoded_image_.SpatialIndex().value_or(0) + 1 ==
num_active_spatial_layers_;
DeliverBufferedFrame(end_of_picture);
}
return WEBRTC_VIDEO_CODEC_OK;
}

View File

@ -63,8 +63,7 @@ class VP9EncoderImpl : public VP9Encoder {
void PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
absl::optional<int>* spatial_idx,
const vpx_codec_cx_pkt& pkt,
uint32_t timestamp,
bool first_frame_in_picture);
uint32_t timestamp);
void FillReferenceIndices(const vpx_codec_cx_pkt& pkt,
const size_t pic_num,
const bool inter_layer_predicted,
@ -120,6 +119,8 @@ class VP9EncoderImpl : public VP9Encoder {
InterLayerPredMode inter_layer_pred_;
bool external_ref_control_;
const bool trusted_rate_controller_;
const bool full_superframe_drop_;
bool first_frame_in_picture_;
std::vector<FramerateController> framerate_controller_;