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

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

Issue 1818903004: Bitrate controller for VideoToolbox Video Encode Accelerator (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') | media/media.gyp » ('j') | 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"
11 #include "media/base/mac/coremedia_glue.h" 11 #include "media/base/mac/coremedia_glue.h"
12 #include "media/base/mac/corevideo_glue.h" 12 #include "media/base/mac/corevideo_glue.h"
13 #include "media/base/mac/video_frame_mac.h" 13 #include "media/base/mac/video_frame_mac.h"
14 #include "third_party/webrtc/system_wrappers/include/clock.h"
14 15
15 namespace media { 16 namespace media {
16 17
17 namespace { 18 namespace {
18 19
19 // TODO(emircan): Check if we can find the actual system capabilities via 20 // TODO(emircan): Check if we can find the actual system capabilities via
20 // creating VTCompressionSessions with varying requirements. 21 // creating VTCompressionSessions with varying requirements.
21 // See crbug.com/584784. 22 // See crbug.com/584784.
22 const size_t kBitsPerByte = 8; 23 const size_t kBitsPerByte = 8;
23 const size_t kDefaultResolutionWidth = 640; 24 const size_t kDefaultResolutionWidth = 640;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 size_t size) 57 size_t size)
57 : id(id), shm(std::move(shm)), size(size) {} 58 : id(id), shm(std::move(shm)), size(size) {}
58 const int32_t id; 59 const int32_t id;
59 const std::unique_ptr<base::SharedMemory> shm; 60 const std::unique_ptr<base::SharedMemory> shm;
60 const size_t size; 61 const size_t size;
61 62
62 private: 63 private:
63 DISALLOW_IMPLICIT_CONSTRUCTORS(BitstreamBufferRef); 64 DISALLOW_IMPLICIT_CONSTRUCTORS(BitstreamBufferRef);
64 }; 65 };
65 66
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.
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
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
73 // of time.
66 VTVideoEncodeAccelerator::VTVideoEncodeAccelerator() 74 VTVideoEncodeAccelerator::VTVideoEncodeAccelerator()
67 : client_task_runner_(base::ThreadTaskRunnerHandle::Get()), 75 : bitrate_adjuster_(webrtc::Clock::GetRealTimeClock(), .5, .95),
76 client_task_runner_(base::ThreadTaskRunnerHandle::Get()),
68 encoder_thread_("VTEncoderThread"), 77 encoder_thread_("VTEncoderThread"),
69 encoder_task_weak_factory_(this) { 78 encoder_task_weak_factory_(this) {
70 encoder_weak_ptr_ = encoder_task_weak_factory_.GetWeakPtr(); 79 encoder_weak_ptr_ = encoder_task_weak_factory_.GetWeakPtr();
71 } 80 }
72 81
73 VTVideoEncodeAccelerator::~VTVideoEncodeAccelerator() { 82 VTVideoEncodeAccelerator::~VTVideoEncodeAccelerator() {
74 DVLOG(3) << __FUNCTION__; 83 DVLOG(3) << __FUNCTION__;
75 DCHECK(thread_checker_.CalledOnValidThread()); 84 DCHECK(thread_checker_.CalledOnValidThread());
76 85
77 Destroy(); 86 Destroy();
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 media::VideoFrameMetadata::REFERENCE_TIME, &ref_time)) { 275 media::VideoFrameMetadata::REFERENCE_TIME, &ref_time)) {
267 ref_time = base::TimeTicks::Now(); 276 ref_time = base::TimeTicks::Now();
268 } 277 }
269 auto timestamp_cm = CoreMediaGlue::CMTimeMake( 278 auto timestamp_cm = CoreMediaGlue::CMTimeMake(
270 frame->timestamp().InMicroseconds(), USEC_PER_SEC); 279 frame->timestamp().InMicroseconds(), USEC_PER_SEC);
271 // Wrap information we'll need after the frame is encoded in a heap object. 280 // Wrap information we'll need after the frame is encoded in a heap object.
272 // We'll get the pointer back from the VideoToolbox completion callback. 281 // We'll get the pointer back from the VideoToolbox completion callback.
273 std::unique_ptr<InProgressFrameEncode> request( 282 std::unique_ptr<InProgressFrameEncode> request(
274 new InProgressFrameEncode(frame->timestamp(), ref_time)); 283 new InProgressFrameEncode(frame->timestamp(), ref_time));
275 284
285 // Update the bitrate if needed.
286 RequestEncodingParametersChangeTask(bitrate_adjuster_.GetAdjustedBitrateBps(),
287 frame_rate_);
288
276 // 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
277 // successful. Otherwise let it fall out of scope. 290 // successful. Otherwise let it fall out of scope.
278 OSStatus status = videotoolbox_glue_->VTCompressionSessionEncodeFrame( 291 OSStatus status = videotoolbox_glue_->VTCompressionSessionEncodeFrame(
279 compression_session_, pixel_buffer, timestamp_cm, 292 compression_session_, pixel_buffer, timestamp_cm,
280 CoreMediaGlue::CMTime{0, 0, 0, 0}, frame_props, 293 CoreMediaGlue::CMTime{0, 0, 0, 0}, frame_props,
281 reinterpret_cast<void*>(request.get()), nullptr); 294 reinterpret_cast<void*>(request.get()), nullptr);
282 if (status != noErr) { 295 if (status != noErr) {
283 DLOG(ERROR) << " VTCompressionSessionEncodeFrame failed: " << status; 296 DLOG(ERROR) << " VTCompressionSessionEncodeFrame failed: " << status;
284 NotifyError(kPlatformFailureError); 297 NotifyError(kPlatformFailureError);
285 } else { 298 } else {
(...skipping 15 matching lines...) Expand all
301 } 314 }
302 315
303 bitstream_buffer_queue_.push_back(std::move(buffer_ref)); 316 bitstream_buffer_queue_.push_back(std::move(buffer_ref));
304 } 317 }
305 318
306 void VTVideoEncodeAccelerator::RequestEncodingParametersChangeTask( 319 void VTVideoEncodeAccelerator::RequestEncodingParametersChangeTask(
307 uint32_t bitrate, 320 uint32_t bitrate,
308 uint32_t framerate) { 321 uint32_t framerate) {
309 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); 322 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
310 323
311 frame_rate_ = framerate > 1 ? framerate : 1;
312 target_bitrate_ = bitrate > 1 ? bitrate : 1;
313
314 if (!compression_session_) { 324 if (!compression_session_) {
315 NotifyError(kPlatformFailureError); 325 NotifyError(kPlatformFailureError);
316 return; 326 return;
317 } 327 }
318 328
319 media::video_toolbox::SessionPropertySetter session_property_setter( 329 bool rv;
320 compression_session_, videotoolbox_glue_); 330 if (framerate != static_cast<uint32_t>(frame_rate_)) {
321 // TODO(emircan): See crbug.com/425352. 331 frame_rate_ = framerate > 1 ? framerate : 1;
322 bool rv = session_property_setter.Set( 332 media::video_toolbox::SessionPropertySetter session_property_setter(
323 videotoolbox_glue_->kVTCompressionPropertyKey_AverageBitRate(), 333 compression_session_, videotoolbox_glue_);
324 target_bitrate_); 334 rv = session_property_setter.Set(
325 rv &= session_property_setter.Set( 335 videotoolbox_glue_->kVTCompressionPropertyKey_ExpectedFrameRate(),
326 videotoolbox_glue_->kVTCompressionPropertyKey_ExpectedFrameRate(), 336 frame_rate_);
327 frame_rate_); 337 DLOG_IF(ERROR, !rv)
328 rv &= session_property_setter.Set( 338 << "Couldn't change frame rate parameters of encode session.";
329 videotoolbox_glue_->kVTCompressionPropertyKey_DataRateLimits(), 339 }
330 media::video_toolbox::ArrayWithIntegerAndFloat( 340
331 target_bitrate_ / kBitsPerByte, 1.0f)); 341 if (bitrate != static_cast<uint32_t>(adjusted_bitrate_)) {
332 DLOG_IF(ERROR, !rv) << "Couldn't change session encoding parameters."; 342 target_bitrate_ = bitrate > 1 ? bitrate : 1;
343 bitrate_adjuster_.SetTargetBitrateBps(target_bitrate_);
344 adjusted_bitrate_ = 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 }
333 } 357 }
334 358
335 void VTVideoEncodeAccelerator::DestroyTask() { 359 void VTVideoEncodeAccelerator::DestroyTask() {
336 DCHECK(thread_checker_.CalledOnValidThread() || 360 DCHECK(thread_checker_.CalledOnValidThread() ||
337 (encoder_thread_.IsRunning() && 361 (encoder_thread_.IsRunning() &&
338 encoder_thread_task_runner_->BelongsToCurrentThread())); 362 encoder_thread_task_runner_->BelongsToCurrentThread()));
339 363
340 // Cancel all encoder thread callbacks. 364 // Cancel all encoder thread callbacks.
341 encoder_task_weak_factory_.InvalidateWeakPtrs(); 365 encoder_task_weak_factory_.InvalidateWeakPtrs();
342 366
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 sample_attachments, CoreMediaGlue::kCMSampleAttachmentKey_NotSync()); 452 sample_attachments, CoreMediaGlue::kCMSampleAttachmentKey_NotSync());
429 453
430 size_t used_buffer_size = 0; 454 size_t used_buffer_size = 0;
431 const bool copy_rv = media::video_toolbox::CopySampleBufferToAnnexBBuffer( 455 const bool copy_rv = media::video_toolbox::CopySampleBufferToAnnexBBuffer(
432 encode_output->sample_buffer.get(), keyframe, buffer_ref->size, 456 encode_output->sample_buffer.get(), keyframe, buffer_ref->size,
433 reinterpret_cast<char*>(buffer_ref->shm->memory()), &used_buffer_size); 457 reinterpret_cast<char*>(buffer_ref->shm->memory()), &used_buffer_size);
434 if (!copy_rv) { 458 if (!copy_rv) {
435 DLOG(ERROR) << "Cannot copy output from SampleBuffer to AnnexBBuffer."; 459 DLOG(ERROR) << "Cannot copy output from SampleBuffer to AnnexBBuffer.";
436 used_buffer_size = 0; 460 used_buffer_size = 0;
437 } 461 }
462 bitrate_adjuster_.Update(used_buffer_size);
438 463
439 client_task_runner_->PostTask( 464 client_task_runner_->PostTask(
440 FROM_HERE, base::Bind(&Client::BitstreamBufferReady, client_, 465 FROM_HERE, base::Bind(&Client::BitstreamBufferReady, client_,
441 buffer_ref->id, used_buffer_size, keyframe)); 466 buffer_ref->id, used_buffer_size, keyframe));
442 } 467 }
443 468
444 bool VTVideoEncodeAccelerator::ResetCompressionSession() { 469 bool VTVideoEncodeAccelerator::ResetCompressionSession() {
445 DCHECK(thread_checker_.CalledOnValidThread()); 470 DCHECK(thread_checker_.CalledOnValidThread());
446 471
447 DestroyCompressionSession(); 472 DestroyCompressionSession();
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 (encoder_thread_.IsRunning() && 572 (encoder_thread_.IsRunning() &&
548 encoder_thread_task_runner_->BelongsToCurrentThread())); 573 encoder_thread_task_runner_->BelongsToCurrentThread()));
549 574
550 if (compression_session_) { 575 if (compression_session_) {
551 videotoolbox_glue_->VTCompressionSessionInvalidate(compression_session_); 576 videotoolbox_glue_->VTCompressionSessionInvalidate(compression_session_);
552 compression_session_.reset(); 577 compression_session_.reset();
553 } 578 }
554 } 579 }
555 580
556 } // namespace media 581 } // namespace media
OLDNEW
« no previous file with comments | « media/gpu/vt_video_encode_accelerator_mac.h ('k') | media/media.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698