Index: media/gpu/vt_video_encode_accelerator_mac.cc |
diff --git a/media/gpu/vt_video_encode_accelerator_mac.cc b/media/gpu/vt_video_encode_accelerator_mac.cc |
index 4c996261b23f4cc37b77e49f8033ee08b1e078d2..fbe174cffcc077d0cc43c4f2a9d8f58123ca41c7 100644 |
--- a/media/gpu/vt_video_encode_accelerator_mac.cc |
+++ b/media/gpu/vt_video_encode_accelerator_mac.cc |
@@ -11,6 +11,7 @@ |
#include "media/base/mac/coremedia_glue.h" |
#include "media/base/mac/corevideo_glue.h" |
#include "media/base/mac/video_frame_mac.h" |
+#include "third_party/webrtc/system_wrappers/include/clock.h" |
namespace media { |
@@ -63,8 +64,16 @@ struct VTVideoEncodeAccelerator::BitstreamBufferRef { |
DISALLOW_IMPLICIT_CONSTRUCTORS(BitstreamBufferRef); |
}; |
+// .5 is set as a minimum to prevent overcompensating for large temporary |
+// overshoots. We don't want to degrade video quality too badly. |
+// .95 is set to prevent oscillations. When a lower bitrate is set on the |
+// encoder than previously set, its output seems to have a brief period of |
+// drastically reduced bitrate, so we want to avoid that. In steady state |
+// conditions, 0.95 seems to give us better overall bitrate over long periods |
+// of time. |
VTVideoEncodeAccelerator::VTVideoEncodeAccelerator() |
- : client_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
+ : bitrate_adjuster_(webrtc::Clock::GetRealTimeClock(), .5, .95), |
+ client_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
encoder_thread_("VTEncoderThread"), |
encoder_task_weak_factory_(this) { |
encoder_weak_ptr_ = encoder_task_weak_factory_.GetWeakPtr(); |
@@ -273,6 +282,10 @@ void VTVideoEncodeAccelerator::EncodeTask( |
std::unique_ptr<InProgressFrameEncode> request( |
new InProgressFrameEncode(frame->timestamp(), ref_time)); |
+ // Update the bitrate if needed. |
+ RequestEncodingParametersChangeTask(bitrate_adjuster_.GetAdjustedBitrateBps(), |
+ frame_rate_); |
+ |
// We can pass the ownership of |request| to the encode callback if |
// successful. Otherwise let it fall out of scope. |
OSStatus status = videotoolbox_glue_->VTCompressionSessionEncodeFrame( |
@@ -308,28 +321,39 @@ void VTVideoEncodeAccelerator::RequestEncodingParametersChangeTask( |
uint32_t framerate) { |
DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); |
- frame_rate_ = framerate > 1 ? framerate : 1; |
- target_bitrate_ = bitrate > 1 ? bitrate : 1; |
- |
if (!compression_session_) { |
NotifyError(kPlatformFailureError); |
return; |
} |
- media::video_toolbox::SessionPropertySetter session_property_setter( |
- compression_session_, videotoolbox_glue_); |
- // TODO(emircan): See crbug.com/425352. |
- bool rv = session_property_setter.Set( |
- videotoolbox_glue_->kVTCompressionPropertyKey_AverageBitRate(), |
- target_bitrate_); |
- rv &= session_property_setter.Set( |
- videotoolbox_glue_->kVTCompressionPropertyKey_ExpectedFrameRate(), |
- frame_rate_); |
- rv &= session_property_setter.Set( |
- videotoolbox_glue_->kVTCompressionPropertyKey_DataRateLimits(), |
- media::video_toolbox::ArrayWithIntegerAndFloat( |
- target_bitrate_ / kBitsPerByte, 1.0f)); |
- DLOG_IF(ERROR, !rv) << "Couldn't change session encoding parameters."; |
+ bool rv; |
+ if (framerate != static_cast<uint32_t>(frame_rate_)) { |
+ frame_rate_ = framerate > 1 ? framerate : 1; |
+ media::video_toolbox::SessionPropertySetter session_property_setter( |
+ compression_session_, videotoolbox_glue_); |
+ rv = session_property_setter.Set( |
+ videotoolbox_glue_->kVTCompressionPropertyKey_ExpectedFrameRate(), |
+ frame_rate_); |
+ DLOG_IF(ERROR, !rv) |
+ << "Couldn't change frame rate parameters of encode session."; |
+ } |
+ |
+ if (bitrate != static_cast<uint32_t>(adjusted_bitrate_)) { |
+ target_bitrate_ = bitrate > 1 ? bitrate : 1; |
+ bitrate_adjuster_.SetTargetBitrateBps(target_bitrate_); |
+ adjusted_bitrate_ = bitrate_adjuster_.GetAdjustedBitrateBps(); |
+ media::video_toolbox::SessionPropertySetter session_property_setter( |
+ compression_session_, videotoolbox_glue_); |
+ rv = session_property_setter.Set( |
+ videotoolbox_glue_->kVTCompressionPropertyKey_AverageBitRate(), |
+ adjusted_bitrate_); |
+ rv &= session_property_setter.Set( |
+ videotoolbox_glue_->kVTCompressionPropertyKey_DataRateLimits(), |
+ media::video_toolbox::ArrayWithIntegerAndFloat( |
+ adjusted_bitrate_ / kBitsPerByte, 1.0f)); |
+ DLOG_IF(ERROR, !rv) |
+ << "Couldn't change bitrate parameters of encode session."; |
+ } |
} |
void VTVideoEncodeAccelerator::DestroyTask() { |
@@ -435,6 +459,7 @@ void VTVideoEncodeAccelerator::ReturnBitstreamBuffer( |
DLOG(ERROR) << "Cannot copy output from SampleBuffer to AnnexBBuffer."; |
used_buffer_size = 0; |
} |
+ bitrate_adjuster_.Update(used_buffer_size); |
client_task_runner_->PostTask( |
FROM_HERE, base::Bind(&Client::BitstreamBufferReady, client_, |