diff --git a/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.cc b/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.cc index 5f6a231288..ab05191d5c 100644 --- a/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.cc +++ b/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.cc @@ -225,10 +225,18 @@ int H264VideoToolboxEncoder::InitEncode(const VideoCodec* codec_settings, size_t max_payload_size) { RTC_DCHECK(codec_settings); RTC_DCHECK_EQ(codec_settings->codecType, kVideoCodecH264); - // TODO(tkchin): We may need to enforce width/height dimension restrictions - // to match what the encoder supports. - width_ = codec_settings->width; - height_ = codec_settings->height; + { + rtc::CritScope lock(&quality_scaler_crit_); + quality_scaler_.Init(QualityScaler::kLowH264QpThreshold, + QualityScaler::kBadH264QpThreshold, + 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; + } // We can only set average bitrate on the HW encoder. target_bitrate_bps_ = codec_settings->startBitrate; bitrate_adjuster_.SetTargetBitrateBps(target_bitrate_bps_); @@ -239,17 +247,18 @@ int H264VideoToolboxEncoder::InitEncode(const VideoCodec* codec_settings, return ResetCompressionSession(); } +const VideoFrame& H264VideoToolboxEncoder::GetScaledFrameOnEncode( + const VideoFrame& frame) { + rtc::CritScope lock(&quality_scaler_crit_); + quality_scaler_.OnEncodeFrame(frame); + return quality_scaler_.GetScaledFrame(frame); +} + int H264VideoToolboxEncoder::Encode( - const VideoFrame& input_image, + const VideoFrame& frame, const CodecSpecificInfo* codec_specific_info, const std::vector* frame_types) { - if (input_image.IsZeroSize()) { - // It's possible to get zero sizes as a signal to produce keyframes (this - // happens for internal sources). But this shouldn't happen in - // webrtcvideoengine2. - RTC_NOTREACHED(); - return WEBRTC_VIDEO_CODEC_OK; - } + RTC_DCHECK(!frame.IsZeroSize()); if (!callback_ || !compression_session_) { return WEBRTC_VIDEO_CODEC_UNINITIALIZED; } @@ -261,6 +270,16 @@ int H264VideoToolboxEncoder::Encode( } #endif bool is_keyframe_required = false; + const VideoFrame& input_image = GetScaledFrameOnEncode(frame); + + if (input_image.width() != width_ || input_image.height() != height_) { + width_ = input_image.width(); + height_ = input_image.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_); @@ -345,6 +364,11 @@ 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. @@ -357,6 +381,9 @@ int H264VideoToolboxEncoder::SetRates(uint32_t 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; } @@ -491,6 +518,9 @@ 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; } bool is_keyframe = false; @@ -526,6 +556,13 @@ void H264VideoToolboxEncoder::OnEncodedFrame( frame._timeStamp = timestamp; 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); + } + int result = callback_->Encoded(frame, &codec_specific_info, header.get()); if (result != 0) { LOG(LS_ERROR) << "Encode callback failed: " << result; diff --git a/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.h b/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.h index d54fa612c3..5dfcf9f60a 100644 --- a/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.h +++ b/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.h @@ -12,9 +12,12 @@ #ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_H264_VIDEO_TOOLBOX_ENCODER_H_ #define WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_H264_VIDEO_TOOLBOX_ENCODER_H_ +#include "webrtc/base/criticalsection.h" #include "webrtc/common_video/include/bitrate_adjuster.h" #include "webrtc/common_video/rotation.h" #include "webrtc/modules/video_coding/codecs/h264/include/h264.h" +#include "webrtc/modules/video_coding/utility/h264_bitstream_parser.h" +#include "webrtc/modules/video_coding/utility/quality_scaler.h" #if defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) @@ -44,6 +47,7 @@ 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; @@ -66,6 +70,7 @@ class H264VideoToolboxEncoder : public H264Encoder { int ResetCompressionSession(); void ConfigureCompressionSession(); void DestroyCompressionSession(); + const VideoFrame& GetScaledFrameOnEncode(const VideoFrame& frame); void SetBitrateBps(uint32_t bitrate_bps); void SetEncoderBitrateBps(uint32_t bitrate_bps); @@ -76,6 +81,10 @@ class H264VideoToolboxEncoder : public H264Encoder { uint32_t encoder_bitrate_bps_; int32_t width_; int32_t height_; + + rtc::CriticalSection quality_scaler_crit_; + QualityScaler quality_scaler_ GUARDED_BY(quality_scaler_crit_); + H264BitstreamParser h264_bitstream_parser_; }; // H264VideoToolboxEncoder } // namespace webrtc