Move usage of QualityScaler to ViEEncoder.
This brings QualityScaler much more in line with OveruseFrameDetector. The two classes are conceptually similar, and should be used in the same way. The biggest changes in this CL are: - Quality scaling is now only done in ViEEncoder and not in each encoder implementation separately. - QualityScaler now checks the average QP asynchronously, instead of having to be polled on each frame. - QualityScaler is no longer responsible for actually scaling the frames, but has a callback to ViEEncoder that it uses to express it's desire for lower resolution. BUG=webrtc:6495 Review-Url: https://codereview.webrtc.org/2398963003 Cr-Commit-Position: refs/heads/master@{#15286}
This commit is contained in:
@ -46,7 +46,6 @@ class H264VideoToolboxEncoder : public H264Encoder {
|
||||
|
||||
int RegisterEncodeCompleteCallback(EncodedImageCallback* callback) override;
|
||||
|
||||
void OnDroppedFrame() override;
|
||||
int SetChannelParameters(uint32_t packet_loss, int64_t rtt) override;
|
||||
|
||||
int SetRates(uint32_t new_bitrate_kbit, uint32_t frame_rate) override;
|
||||
@ -67,6 +66,8 @@ class H264VideoToolboxEncoder : public H264Encoder {
|
||||
uint32_t timestamp,
|
||||
VideoRotation rotation);
|
||||
|
||||
ScalingSettings GetScalingSettings() const override;
|
||||
|
||||
private:
|
||||
int ResetCompressionSession();
|
||||
void ConfigureCompressionSession();
|
||||
@ -85,10 +86,7 @@ class H264VideoToolboxEncoder : public H264Encoder {
|
||||
int32_t height_;
|
||||
const CFStringRef profile_;
|
||||
|
||||
rtc::CriticalSection quality_scaler_crit_;
|
||||
QualityScaler quality_scaler_ GUARDED_BY(quality_scaler_crit_);
|
||||
H264BitstreamParser h264_bitstream_parser_;
|
||||
bool enable_scaling_;
|
||||
std::vector<uint8_t> nv12_scale_buffer_;
|
||||
}; // H264VideoToolboxEncoder
|
||||
|
||||
|
||||
@ -360,18 +360,9 @@ int H264VideoToolboxEncoder::InitEncode(const VideoCodec* codec_settings,
|
||||
size_t max_payload_size) {
|
||||
RTC_DCHECK(codec_settings);
|
||||
RTC_DCHECK_EQ(codec_settings->codecType, kVideoCodecH264);
|
||||
{
|
||||
rtc::CritScope lock(&quality_scaler_crit_);
|
||||
quality_scaler_.Init(internal::kLowH264QpThreshold,
|
||||
internal::kHighH264QpThreshold,
|
||||
codec_settings->startBitrate, codec_settings->width,
|
||||
codec_settings->height, codec_settings->maxFramerate);
|
||||
QualityScaler::Resolution res = quality_scaler_.GetScaledResolution();
|
||||
// TODO(tkchin): We may need to enforce width/height dimension restrictions
|
||||
// to match what the encoder supports.
|
||||
width_ = res.width;
|
||||
height_ = res.height;
|
||||
}
|
||||
|
||||
width_ = codec_settings->width;
|
||||
height_ = codec_settings->height;
|
||||
// We can only set average bitrate on the HW encoder.
|
||||
target_bitrate_bps_ = codec_settings->startBitrate;
|
||||
bitrate_adjuster_.SetTargetBitrateBps(target_bitrate_bps_);
|
||||
@ -386,6 +377,9 @@ int H264VideoToolboxEncoder::Encode(
|
||||
const VideoFrame& frame,
|
||||
const CodecSpecificInfo* codec_specific_info,
|
||||
const std::vector<FrameType>* frame_types) {
|
||||
// |input_frame| size should always match codec settings.
|
||||
RTC_DCHECK_EQ(frame.width(), width_);
|
||||
RTC_DCHECK_EQ(frame.height(), height_);
|
||||
RTC_DCHECK(!frame.IsZeroSize());
|
||||
if (!callback_ || !compression_session_) {
|
||||
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
||||
@ -399,18 +393,6 @@ int H264VideoToolboxEncoder::Encode(
|
||||
#endif
|
||||
bool is_keyframe_required = false;
|
||||
|
||||
quality_scaler_.OnEncodeFrame(frame.width(), frame.height());
|
||||
const QualityScaler::Resolution scaled_res =
|
||||
quality_scaler_.GetScaledResolution();
|
||||
|
||||
if (scaled_res.width != width_ || scaled_res.height != height_) {
|
||||
width_ = scaled_res.width;
|
||||
height_ = scaled_res.height;
|
||||
int ret = ResetCompressionSession();
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Get a pixel buffer from the pool and copy frame data over.
|
||||
CVPixelBufferPoolRef pixel_buffer_pool =
|
||||
VTCompressionSessionGetPixelBufferPool(compression_session_);
|
||||
@ -457,11 +439,8 @@ int H264VideoToolboxEncoder::Encode(
|
||||
if (!pixel_buffer) {
|
||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
||||
}
|
||||
// TODO(magjed): Optimize by merging scaling and NV12 pixel buffer
|
||||
// conversion once libyuv::MergeUVPlanes is available.
|
||||
rtc::scoped_refptr<VideoFrameBuffer> scaled_i420_buffer =
|
||||
quality_scaler_.GetScaledBuffer(frame.video_frame_buffer());
|
||||
if (!internal::CopyVideoFrameToPixelBuffer(scaled_i420_buffer,
|
||||
RTC_DCHECK(pixel_buffer);
|
||||
if (!internal::CopyVideoFrameToPixelBuffer(frame.video_frame_buffer(),
|
||||
pixel_buffer)) {
|
||||
LOG(LS_ERROR) << "Failed to copy frame data.";
|
||||
CVBufferRelease(pixel_buffer);
|
||||
@ -517,11 +496,6 @@ int H264VideoToolboxEncoder::RegisterEncodeCompleteCallback(
|
||||
return WEBRTC_VIDEO_CODEC_OK;
|
||||
}
|
||||
|
||||
void H264VideoToolboxEncoder::OnDroppedFrame() {
|
||||
rtc::CritScope lock(&quality_scaler_crit_);
|
||||
quality_scaler_.ReportDroppedFrame();
|
||||
}
|
||||
|
||||
int H264VideoToolboxEncoder::SetChannelParameters(uint32_t packet_loss,
|
||||
int64_t rtt) {
|
||||
// Encoder doesn't know anything about packet loss or rtt so just return.
|
||||
@ -533,10 +507,6 @@ int H264VideoToolboxEncoder::SetRates(uint32_t new_bitrate_kbit,
|
||||
target_bitrate_bps_ = 1000 * new_bitrate_kbit;
|
||||
bitrate_adjuster_.SetTargetBitrateBps(target_bitrate_bps_);
|
||||
SetBitrateBps(bitrate_adjuster_.GetAdjustedBitrateBps());
|
||||
|
||||
rtc::CritScope lock(&quality_scaler_crit_);
|
||||
quality_scaler_.ReportFramerate(frame_rate);
|
||||
|
||||
return WEBRTC_VIDEO_CODEC_OK;
|
||||
}
|
||||
|
||||
@ -709,8 +679,6 @@ void H264VideoToolboxEncoder::OnEncodedFrame(
|
||||
}
|
||||
if (info_flags & kVTEncodeInfo_FrameDropped) {
|
||||
LOG(LS_INFO) << "H264 encode dropped frame.";
|
||||
rtc::CritScope lock(&quality_scaler_crit_);
|
||||
quality_scaler_.ReportDroppedFrame();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -752,20 +720,20 @@ void H264VideoToolboxEncoder::OnEncodedFrame(
|
||||
frame.rotation_ = rotation;
|
||||
|
||||
h264_bitstream_parser_.ParseBitstream(buffer->data(), buffer->size());
|
||||
int qp;
|
||||
if (h264_bitstream_parser_.GetLastSliceQp(&qp)) {
|
||||
rtc::CritScope lock(&quality_scaler_crit_);
|
||||
quality_scaler_.ReportQP(qp);
|
||||
frame.qp_ = qp;
|
||||
}
|
||||
h264_bitstream_parser_.GetLastSliceQp(&frame.qp_);
|
||||
|
||||
EncodedImageCallback::Result result =
|
||||
EncodedImageCallback::Result res =
|
||||
callback_->OnEncodedImage(frame, &codec_specific_info, header.get());
|
||||
if (result.error != EncodedImageCallback::Result::OK) {
|
||||
LOG(LS_ERROR) << "Encode callback failed: " << result.error;
|
||||
if (res.error != EncodedImageCallback::Result::OK) {
|
||||
LOG(LS_ERROR) << "Encode callback failed: " << res.error;
|
||||
return;
|
||||
}
|
||||
bitrate_adjuster_.Update(frame._size);
|
||||
}
|
||||
|
||||
VideoEncoder::ScalingSettings H264VideoToolboxEncoder::GetScalingSettings()
|
||||
const {
|
||||
return VideoEncoder::ScalingSettings(true, internal::kLowH264QpThreshold,
|
||||
internal::kHighH264QpThreshold);
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
||||
Reference in New Issue
Block a user