Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(101)

Side by Side Diff: media/gpu/vt_video_encode_accelerator_mac.cc

Issue 2000853002: Fix BitrateAdjuster issues in VTVideoEncodeAccelerator (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/gpu/vt_video_encode_accelerator_mac.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/gpu/vt_video_encode_accelerator_mac.h" 5 #include "media/gpu/vt_video_encode_accelerator_mac.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "base/mac/mac_util.h" 9 #include "base/mac/mac_util.h"
10 #include "base/threading/thread_task_runner_handle.h" 10 #include "base/threading/thread_task_runner_handle.h"
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 }; 65 };
66 66
67 // .5 is set as a minimum to prevent overcompensating for large temporary 67 // .5 is set as a minimum to prevent overcompensating for large temporary
68 // overshoots. We don't want to degrade video quality too badly. 68 // overshoots. We don't want to degrade video quality too badly.
69 // .95 is set to prevent oscillations. When a lower bitrate is set on the 69 // .95 is set to prevent oscillations. When a lower bitrate is set on the
70 // encoder than previously set, its output seems to have a brief period of 70 // encoder than previously set, its output seems to have a brief period of
71 // drastically reduced bitrate, so we want to avoid that. In steady state 71 // drastically reduced bitrate, so we want to avoid that. In steady state
72 // conditions, 0.95 seems to give us better overall bitrate over long periods 72 // conditions, 0.95 seems to give us better overall bitrate over long periods
73 // of time. 73 // of time.
74 VTVideoEncodeAccelerator::VTVideoEncodeAccelerator() 74 VTVideoEncodeAccelerator::VTVideoEncodeAccelerator()
75 : bitrate_adjuster_(webrtc::Clock::GetRealTimeClock(), .5, .95), 75 : target_bitrate_(0),
76 bitrate_adjuster_(webrtc::Clock::GetRealTimeClock(), .5, .95),
76 client_task_runner_(base::ThreadTaskRunnerHandle::Get()), 77 client_task_runner_(base::ThreadTaskRunnerHandle::Get()),
77 encoder_thread_("VTEncoderThread"), 78 encoder_thread_("VTEncoderThread"),
78 encoder_task_weak_factory_(this) { 79 encoder_task_weak_factory_(this) {
79 encoder_weak_ptr_ = encoder_task_weak_factory_.GetWeakPtr(); 80 encoder_weak_ptr_ = encoder_task_weak_factory_.GetWeakPtr();
80 } 81 }
81 82
82 VTVideoEncodeAccelerator::~VTVideoEncodeAccelerator() { 83 VTVideoEncodeAccelerator::~VTVideoEncodeAccelerator() {
83 DVLOG(3) << __FUNCTION__; 84 DVLOG(3) << __FUNCTION__;
84 DCHECK(thread_checker_.CalledOnValidThread()); 85 DCHECK(thread_checker_.CalledOnValidThread());
85 86
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 if (!base::mac::IsOSMavericksOrLater()) { 157 if (!base::mac::IsOSMavericksOrLater()) {
157 DLOG(ERROR) << "VideoToolbox hardware encoder is supported on Mac OS 10.9 " 158 DLOG(ERROR) << "VideoToolbox hardware encoder is supported on Mac OS 10.9 "
158 "and later."; 159 "and later.";
159 return false; 160 return false;
160 } 161 }
161 162
162 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); 163 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client));
163 client_ = client_ptr_factory_->GetWeakPtr(); 164 client_ = client_ptr_factory_->GetWeakPtr();
164 input_visible_size_ = input_visible_size; 165 input_visible_size_ = input_visible_size;
165 frame_rate_ = kMaxFrameRateNumerator / kMaxFrameRateDenominator; 166 frame_rate_ = kMaxFrameRateNumerator / kMaxFrameRateDenominator;
166 target_bitrate_ = initial_bitrate; 167 initial_bitrate_ = initial_bitrate;
167 bitstream_buffer_size_ = input_visible_size.GetArea(); 168 bitstream_buffer_size_ = input_visible_size.GetArea();
168 169
169 if (!encoder_thread_.Start()) { 170 if (!encoder_thread_.Start()) {
170 DLOG(ERROR) << "Failed spawning encoder thread."; 171 DLOG(ERROR) << "Failed spawning encoder thread.";
171 return false; 172 return false;
172 } 173 }
173 encoder_thread_task_runner_ = encoder_thread_.task_runner(); 174 encoder_thread_task_runner_ = encoder_thread_.task_runner();
174 175
175 if (!ResetCompressionSession()) { 176 if (!ResetCompressionSession()) {
176 DLOG(ERROR) << "Failed creating compression session."; 177 DLOG(ERROR) << "Failed creating compression session.";
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 ref_time = base::TimeTicks::Now(); 277 ref_time = base::TimeTicks::Now();
277 } 278 }
278 auto timestamp_cm = CoreMediaGlue::CMTimeMake( 279 auto timestamp_cm = CoreMediaGlue::CMTimeMake(
279 frame->timestamp().InMicroseconds(), USEC_PER_SEC); 280 frame->timestamp().InMicroseconds(), USEC_PER_SEC);
280 // Wrap information we'll need after the frame is encoded in a heap object. 281 // Wrap information we'll need after the frame is encoded in a heap object.
281 // We'll get the pointer back from the VideoToolbox completion callback. 282 // We'll get the pointer back from the VideoToolbox completion callback.
282 std::unique_ptr<InProgressFrameEncode> request( 283 std::unique_ptr<InProgressFrameEncode> request(
283 new InProgressFrameEncode(frame->timestamp(), ref_time)); 284 new InProgressFrameEncode(frame->timestamp(), ref_time));
284 285
285 // Update the bitrate if needed. 286 // Update the bitrate if needed.
286 RequestEncodingParametersChangeTask(bitrate_adjuster_.GetAdjustedBitrateBps(), 287 SetAdjustedBitrate(bitrate_adjuster_.GetAdjustedBitrateBps());
287 frame_rate_);
288 288
289 // We can pass the ownership of |request| to the encode callback if 289 // We can pass the ownership of |request| to the encode callback if
290 // successful. Otherwise let it fall out of scope. 290 // successful. Otherwise let it fall out of scope.
291 OSStatus status = videotoolbox_glue_->VTCompressionSessionEncodeFrame( 291 OSStatus status = videotoolbox_glue_->VTCompressionSessionEncodeFrame(
292 compression_session_, pixel_buffer, timestamp_cm, 292 compression_session_, pixel_buffer, timestamp_cm,
293 CoreMediaGlue::CMTime{0, 0, 0, 0}, frame_props, 293 CoreMediaGlue::CMTime{0, 0, 0, 0}, frame_props,
294 reinterpret_cast<void*>(request.get()), nullptr); 294 reinterpret_cast<void*>(request.get()), nullptr);
295 if (status != noErr) { 295 if (status != noErr) {
296 DLOG(ERROR) << " VTCompressionSessionEncodeFrame failed: " << status; 296 DLOG(ERROR) << " VTCompressionSessionEncodeFrame failed: " << status;
297 NotifyError(kPlatformFailureError); 297 NotifyError(kPlatformFailureError);
(...skipping 21 matching lines...) Expand all
319 void VTVideoEncodeAccelerator::RequestEncodingParametersChangeTask( 319 void VTVideoEncodeAccelerator::RequestEncodingParametersChangeTask(
320 uint32_t bitrate, 320 uint32_t bitrate,
321 uint32_t framerate) { 321 uint32_t framerate) {
322 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); 322 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
323 323
324 if (!compression_session_) { 324 if (!compression_session_) {
325 NotifyError(kPlatformFailureError); 325 NotifyError(kPlatformFailureError);
326 return; 326 return;
327 } 327 }
328 328
329 bool rv;
330 if (framerate != static_cast<uint32_t>(frame_rate_)) { 329 if (framerate != static_cast<uint32_t>(frame_rate_)) {
331 frame_rate_ = framerate > 1 ? framerate : 1;
332 media::video_toolbox::SessionPropertySetter session_property_setter( 330 media::video_toolbox::SessionPropertySetter session_property_setter(
333 compression_session_, videotoolbox_glue_); 331 compression_session_, videotoolbox_glue_);
334 rv = session_property_setter.Set( 332 session_property_setter.Set(
335 videotoolbox_glue_->kVTCompressionPropertyKey_ExpectedFrameRate(), 333 videotoolbox_glue_->kVTCompressionPropertyKey_ExpectedFrameRate(),
336 frame_rate_); 334 frame_rate_);
337 DLOG_IF(ERROR, !rv)
338 << "Couldn't change frame rate parameters of encode session.";
339 } 335 }
340 336
341 if (bitrate != static_cast<uint32_t>(adjusted_bitrate_)) { 337 if (bitrate != static_cast<uint32_t>(target_bitrate_) && bitrate > 0) {
342 target_bitrate_ = bitrate > 1 ? bitrate : 1; 338 target_bitrate_ = bitrate;
343 bitrate_adjuster_.SetTargetBitrateBps(target_bitrate_); 339 bitrate_adjuster_.SetTargetBitrateBps(target_bitrate_);
344 adjusted_bitrate_ = bitrate_adjuster_.GetAdjustedBitrateBps(); 340 SetAdjustedBitrate(bitrate_adjuster_.GetAdjustedBitrateBps());
345 media::video_toolbox::SessionPropertySetter session_property_setter(
346 compression_session_, videotoolbox_glue_);
347 rv = session_property_setter.Set(
348 videotoolbox_glue_->kVTCompressionPropertyKey_AverageBitRate(),
349 adjusted_bitrate_);
350 rv &= session_property_setter.Set(
351 videotoolbox_glue_->kVTCompressionPropertyKey_DataRateLimits(),
352 media::video_toolbox::ArrayWithIntegerAndFloat(
353 adjusted_bitrate_ / kBitsPerByte, 1.0f));
354 DLOG_IF(ERROR, !rv)
355 << "Couldn't change bitrate parameters of encode session.";
356 } 341 }
357 } 342 }
358 343
344 void VTVideoEncodeAccelerator::SetAdjustedBitrate(int32_t bitrate) {
345 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
346
347 if (bitrate == encoder_set_bitrate_)
348 return;
349
350 encoder_set_bitrate_ = bitrate;
351 media::video_toolbox::SessionPropertySetter session_property_setter(
352 compression_session_, videotoolbox_glue_);
353 bool rv = session_property_setter.Set(
354 videotoolbox_glue_->kVTCompressionPropertyKey_AverageBitRate(),
355 encoder_set_bitrate_);
356 rv &= session_property_setter.Set(
357 videotoolbox_glue_->kVTCompressionPropertyKey_DataRateLimits(),
358 media::video_toolbox::ArrayWithIntegerAndFloat(
359 encoder_set_bitrate_ / kBitsPerByte, 1.0f));
360 DLOG_IF(ERROR, !rv)
361 << "Couldn't change bitrate parameters of encode session.";
362 }
363
359 void VTVideoEncodeAccelerator::DestroyTask() { 364 void VTVideoEncodeAccelerator::DestroyTask() {
360 DCHECK(thread_checker_.CalledOnValidThread() || 365 DCHECK(thread_checker_.CalledOnValidThread() ||
361 (encoder_thread_.IsRunning() && 366 (encoder_thread_.IsRunning() &&
362 encoder_thread_task_runner_->BelongsToCurrentThread())); 367 encoder_thread_task_runner_->BelongsToCurrentThread()));
363 368
364 // Cancel all encoder thread callbacks. 369 // Cancel all encoder thread callbacks.
365 encoder_task_weak_factory_.InvalidateWeakPtrs(); 370 encoder_task_weak_factory_.InvalidateWeakPtrs();
366 371
367 // This call blocks until all pending frames are flushed out. 372 // This call blocks until all pending frames are flushed out.
368 DestroyCompressionSession(); 373 DestroyCompressionSession();
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 495
491 bool session_rv = 496 bool session_rv =
492 CreateCompressionSession(attributes, input_visible_size_, false); 497 CreateCompressionSession(attributes, input_visible_size_, false);
493 if (!session_rv) { 498 if (!session_rv) {
494 DestroyCompressionSession(); 499 DestroyCompressionSession();
495 return false; 500 return false;
496 } 501 }
497 502
498 const bool configure_rv = ConfigureCompressionSession(); 503 const bool configure_rv = ConfigureCompressionSession();
499 if (configure_rv) 504 if (configure_rv)
500 RequestEncodingParametersChange(target_bitrate_, frame_rate_); 505 RequestEncodingParametersChange(initial_bitrate_, frame_rate_);
501 return configure_rv; 506 return configure_rv;
502 } 507 }
503 508
504 bool VTVideoEncodeAccelerator::CreateCompressionSession( 509 bool VTVideoEncodeAccelerator::CreateCompressionSession(
505 base::ScopedCFTypeRef<CFDictionaryRef> attributes, 510 base::ScopedCFTypeRef<CFDictionaryRef> attributes,
506 const gfx::Size& input_size, 511 const gfx::Size& input_size,
507 bool require_hw_encoding) { 512 bool require_hw_encoding) {
508 DCHECK(thread_checker_.CalledOnValidThread()); 513 DCHECK(thread_checker_.CalledOnValidThread());
509 514
510 std::vector<CFTypeRef> encoder_keys; 515 std::vector<CFTypeRef> encoder_keys;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
572 (encoder_thread_.IsRunning() && 577 (encoder_thread_.IsRunning() &&
573 encoder_thread_task_runner_->BelongsToCurrentThread())); 578 encoder_thread_task_runner_->BelongsToCurrentThread()));
574 579
575 if (compression_session_) { 580 if (compression_session_) {
576 videotoolbox_glue_->VTCompressionSessionInvalidate(compression_session_); 581 videotoolbox_glue_->VTCompressionSessionInvalidate(compression_session_);
577 compression_session_.reset(); 582 compression_session_.reset();
578 } 583 }
579 } 584 }
580 585
581 } // namespace media 586 } // namespace media
OLDNEW
« no previous file with comments | « media/gpu/vt_video_encode_accelerator_mac.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698