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

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

Issue 1882373004: Migrate content/common/gpu/media code to media/gpu (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix several more bot-identified build issues Created 4 years, 8 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
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 "content/common/gpu/media/vt_video_encode_accelerator_mac.h" 5 #include "media/gpu/vt_video_encode_accelerator_mac.h"
6 6
7 #include "base/thread_task_runner_handle.h" 7 #include "base/thread_task_runner_handle.h"
8 #include "media/base/mac/coremedia_glue.h" 8 #include "media/base/mac/coremedia_glue.h"
9 #include "media/base/mac/corevideo_glue.h" 9 #include "media/base/mac/corevideo_glue.h"
10 #include "media/base/mac/video_frame_mac.h" 10 #include "media/base/mac/video_frame_mac.h"
11 11
12 namespace content { 12 namespace media {
13 13
14 namespace { 14 namespace {
15 15
16 // TODO(emircan): Check if we can find the actual system capabilities via 16 // TODO(emircan): Check if we can find the actual system capabilities via
17 // creating VTCompressionSessions with varying requirements. 17 // creating VTCompressionSessions with varying requirements.
18 // See crbug.com/584784. 18 // See crbug.com/584784.
19 const size_t kBitsPerByte = 8; 19 const size_t kBitsPerByte = 8;
20 const size_t kDefaultResolutionWidth = 640; 20 const size_t kDefaultResolutionWidth = 640;
21 const size_t kDefaultResolutionHeight = 480; 21 const size_t kDefaultResolutionHeight = 480;
22 const size_t kMaxFrameRateNumerator = 30; 22 const size_t kMaxFrameRateNumerator = 30;
23 const size_t kMaxFrameRateDenominator = 1; 23 const size_t kMaxFrameRateDenominator = 1;
24 const size_t kMaxResolutionWidth = 4096; 24 const size_t kMaxResolutionWidth = 4096;
25 const size_t kMaxResolutionHeight = 2160; 25 const size_t kMaxResolutionHeight = 2160;
26 const size_t kNumInputBuffers = 3; 26 const size_t kNumInputBuffers = 3;
27 27
28 } // namespace 28 } // namespace
29 29
30 struct VTVideoEncodeAccelerator::InProgressFrameEncode { 30 struct VTVideoEncodeAccelerator::InProgressFrameEncode {
31 InProgressFrameEncode(base::TimeDelta rtp_timestamp, 31 InProgressFrameEncode(base::TimeDelta rtp_timestamp, base::TimeTicks ref_time)
32 base::TimeTicks ref_time)
33 : timestamp(rtp_timestamp), reference_time(ref_time) {} 32 : timestamp(rtp_timestamp), reference_time(ref_time) {}
34 const base::TimeDelta timestamp; 33 const base::TimeDelta timestamp;
35 const base::TimeTicks reference_time; 34 const base::TimeTicks reference_time;
36 35
37 private: 36 private:
38 DISALLOW_IMPLICIT_CONSTRUCTORS(InProgressFrameEncode); 37 DISALLOW_IMPLICIT_CONSTRUCTORS(InProgressFrameEncode);
39 }; 38 };
40 39
41 struct VTVideoEncodeAccelerator::EncodeOutput { 40 struct VTVideoEncodeAccelerator::EncodeOutput {
42 EncodeOutput(VTEncodeInfoFlags info_flags, CMSampleBufferRef sbuf) 41 EncodeOutput(VTEncodeInfoFlags info_flags, CMSampleBufferRef sbuf)
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 << ", initial_bitrate=" << initial_bitrate; 120 << ", initial_bitrate=" << initial_bitrate;
122 DCHECK(thread_checker_.CalledOnValidThread()); 121 DCHECK(thread_checker_.CalledOnValidThread());
123 DCHECK(client); 122 DCHECK(client);
124 123
125 if (media::PIXEL_FORMAT_I420 != format) { 124 if (media::PIXEL_FORMAT_I420 != format) {
126 DLOG(ERROR) << "Input format not supported= " 125 DLOG(ERROR) << "Input format not supported= "
127 << media::VideoPixelFormatToString(format); 126 << media::VideoPixelFormatToString(format);
128 return false; 127 return false;
129 } 128 }
130 if (media::H264PROFILE_BASELINE != output_profile) { 129 if (media::H264PROFILE_BASELINE != output_profile) {
131 DLOG(ERROR) << "Output profile not supported= " 130 DLOG(ERROR) << "Output profile not supported= " << output_profile;
132 << output_profile;
133 return false; 131 return false;
134 } 132 }
135 133
136 videotoolbox_glue_ = VideoToolboxGlue::Get(); 134 videotoolbox_glue_ = VideoToolboxGlue::Get();
137 if (!videotoolbox_glue_) { 135 if (!videotoolbox_glue_) {
138 DLOG(ERROR) << "Failed creating VideoToolbox glue."; 136 DLOG(ERROR) << "Failed creating VideoToolbox glue.";
139 return false; 137 return false;
140 } 138 }
141 139
142 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); 140 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client));
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 217
220 void VTVideoEncodeAccelerator::Destroy() { 218 void VTVideoEncodeAccelerator::Destroy() {
221 DVLOG(3) << __FUNCTION__; 219 DVLOG(3) << __FUNCTION__;
222 DCHECK(thread_checker_.CalledOnValidThread()); 220 DCHECK(thread_checker_.CalledOnValidThread());
223 221
224 // Cancel all callbacks. 222 // Cancel all callbacks.
225 client_ptr_factory_.reset(); 223 client_ptr_factory_.reset();
226 224
227 if (encoder_thread_.IsRunning()) { 225 if (encoder_thread_.IsRunning()) {
228 encoder_thread_task_runner_->PostTask( 226 encoder_thread_task_runner_->PostTask(
229 FROM_HERE, 227 FROM_HERE, base::Bind(&VTVideoEncodeAccelerator::DestroyTask,
230 base::Bind(&VTVideoEncodeAccelerator::DestroyTask, 228 base::Unretained(this)));
231 base::Unretained(this)));
232 encoder_thread_.Stop(); 229 encoder_thread_.Stop();
233 } else { 230 } else {
234 DestroyTask(); 231 DestroyTask();
235 } 232 }
236 } 233 }
237 234
238 void VTVideoEncodeAccelerator::EncodeTask( 235 void VTVideoEncodeAccelerator::EncodeTask(
239 const scoped_refptr<media::VideoFrame>& frame, 236 const scoped_refptr<media::VideoFrame>& frame,
240 bool force_keyframe) { 237 bool force_keyframe) {
241 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); 238 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 client_task_runner_->PostTask( 404 client_task_runner_->PostTask(
408 FROM_HERE, base::Bind(&Client::BitstreamBufferReady, client_, 405 FROM_HERE, base::Bind(&Client::BitstreamBufferReady, client_,
409 buffer_ref->id, 0, false)); 406 buffer_ref->id, 0, false));
410 return; 407 return;
411 } 408 }
412 409
413 auto sample_attachments = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex( 410 auto sample_attachments = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(
414 CoreMediaGlue::CMSampleBufferGetSampleAttachmentsArray( 411 CoreMediaGlue::CMSampleBufferGetSampleAttachmentsArray(
415 encode_output->sample_buffer.get(), true), 412 encode_output->sample_buffer.get(), true),
416 0)); 413 0));
417 const bool keyframe = 414 const bool keyframe = !CFDictionaryContainsKey(
418 !CFDictionaryContainsKey(sample_attachments, 415 sample_attachments, CoreMediaGlue::kCMSampleAttachmentKey_NotSync());
419 CoreMediaGlue::kCMSampleAttachmentKey_NotSync());
420 416
421 size_t used_buffer_size = 0; 417 size_t used_buffer_size = 0;
422 const bool copy_rv = media::video_toolbox::CopySampleBufferToAnnexBBuffer( 418 const bool copy_rv = media::video_toolbox::CopySampleBufferToAnnexBBuffer(
423 encode_output->sample_buffer.get(), keyframe, buffer_ref->size, 419 encode_output->sample_buffer.get(), keyframe, buffer_ref->size,
424 reinterpret_cast<char*>(buffer_ref->shm->memory()), &used_buffer_size); 420 reinterpret_cast<char*>(buffer_ref->shm->memory()), &used_buffer_size);
425 if (!copy_rv) { 421 if (!copy_rv) {
426 DLOG(ERROR) << "Cannot copy output from SampleBuffer to AnnexBBuffer."; 422 DLOG(ERROR) << "Cannot copy output from SampleBuffer to AnnexBBuffer.";
427 used_buffer_size = 0; 423 used_buffer_size = 0;
428 } 424 }
429 425
430 client_task_runner_->PostTask( 426 client_task_runner_->PostTask(
431 FROM_HERE, base::Bind(&Client::BitstreamBufferReady, client_, 427 FROM_HERE, base::Bind(&Client::BitstreamBufferReady, client_,
432 buffer_ref->id, used_buffer_size, keyframe)); 428 buffer_ref->id, used_buffer_size, keyframe));
433 } 429 }
434 430
435 bool VTVideoEncodeAccelerator::ResetCompressionSession() { 431 bool VTVideoEncodeAccelerator::ResetCompressionSession() {
436 DCHECK(thread_checker_.CalledOnValidThread()); 432 DCHECK(thread_checker_.CalledOnValidThread());
437 433
438 DestroyCompressionSession(); 434 DestroyCompressionSession();
439 435
440 CFTypeRef attributes_keys[] = { 436 CFTypeRef attributes_keys[] = {kCVPixelBufferOpenGLCompatibilityKey,
441 kCVPixelBufferOpenGLCompatibilityKey, 437 kCVPixelBufferIOSurfacePropertiesKey,
442 kCVPixelBufferIOSurfacePropertiesKey, 438 kCVPixelBufferPixelFormatTypeKey};
443 kCVPixelBufferPixelFormatTypeKey
444 };
445 const int format[] = { 439 const int format[] = {
446 CoreVideoGlue::kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange}; 440 CoreVideoGlue::kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange};
447 CFTypeRef attributes_values[] = { 441 CFTypeRef attributes_values[] = {
448 kCFBooleanTrue, 442 kCFBooleanTrue,
449 media::video_toolbox::DictionaryWithKeysAndValues(nullptr, nullptr, 0) 443 media::video_toolbox::DictionaryWithKeysAndValues(nullptr, nullptr, 0)
450 .release(), 444 .release(),
451 media::video_toolbox::ArrayWithIntegers(format, arraysize(format)) 445 media::video_toolbox::ArrayWithIntegers(format, arraysize(format))
452 .release()}; 446 .release()};
453 const base::ScopedCFTypeRef<CFDictionaryRef> attributes = 447 const base::ScopedCFTypeRef<CFDictionaryRef> attributes =
454 media::video_toolbox::DictionaryWithKeysAndValues( 448 media::video_toolbox::DictionaryWithKeysAndValues(
(...skipping 16 matching lines...) Expand all
471 465
472 bool VTVideoEncodeAccelerator::CreateCompressionSession( 466 bool VTVideoEncodeAccelerator::CreateCompressionSession(
473 base::ScopedCFTypeRef<CFDictionaryRef> attributes, 467 base::ScopedCFTypeRef<CFDictionaryRef> attributes,
474 const gfx::Size& input_size, 468 const gfx::Size& input_size,
475 bool require_hw_encoding) { 469 bool require_hw_encoding) {
476 DCHECK(thread_checker_.CalledOnValidThread()); 470 DCHECK(thread_checker_.CalledOnValidThread());
477 471
478 std::vector<CFTypeRef> encoder_keys; 472 std::vector<CFTypeRef> encoder_keys;
479 std::vector<CFTypeRef> encoder_values; 473 std::vector<CFTypeRef> encoder_values;
480 if (require_hw_encoding) { 474 if (require_hw_encoding) {
481 encoder_keys.push_back(videotoolbox_glue_ 475 encoder_keys.push_back(
482 ->kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder()); 476 videotoolbox_glue_
477 ->kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncode r());
483 encoder_values.push_back(kCFBooleanTrue); 478 encoder_values.push_back(kCFBooleanTrue);
484 } else { 479 } else {
485 encoder_keys.push_back(videotoolbox_glue_ 480 encoder_keys.push_back(
486 ->kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder()); 481 videotoolbox_glue_
482 ->kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder ());
487 encoder_values.push_back(kCFBooleanTrue); 483 encoder_values.push_back(kCFBooleanTrue);
488 } 484 }
489 base::ScopedCFTypeRef<CFDictionaryRef> encoder_spec = 485 base::ScopedCFTypeRef<CFDictionaryRef> encoder_spec =
490 media::video_toolbox::DictionaryWithKeysAndValues( 486 media::video_toolbox::DictionaryWithKeysAndValues(
491 encoder_keys.data(), encoder_values.data(), encoder_keys.size()); 487 encoder_keys.data(), encoder_values.data(), encoder_keys.size());
492 488
493 // Create the compression session. 489 // Create the compression session.
494 // Note that the encoder object is given to the compression session as the 490 // Note that the encoder object is given to the compression session as the
495 // callback context using a raw pointer. The C API does not allow us to use a 491 // callback context using a raw pointer. The C API does not allow us to use a
496 // smart pointer, nor is this encoder ref counted. However, this is still 492 // smart pointer, nor is this encoder ref counted. However, this is still
497 // safe, because we 1) we own the compression session and 2) we tear it down 493 // safe, because we 1) we own the compression session and 2) we tear it down
498 // safely. When destructing the encoder, the compression session is flushed 494 // safely. When destructing the encoder, the compression session is flushed
499 // and invalidated. Internally, VideoToolbox will join all of its threads 495 // and invalidated. Internally, VideoToolbox will join all of its threads
500 // before returning to the client. Therefore, when control returns to us, we 496 // before returning to the client. Therefore, when control returns to us, we
501 // are guaranteed that the output callback will not execute again. 497 // are guaranteed that the output callback will not execute again.
502 OSStatus status = videotoolbox_glue_->VTCompressionSessionCreate( 498 OSStatus status = videotoolbox_glue_->VTCompressionSessionCreate(
503 kCFAllocatorDefault, 499 kCFAllocatorDefault, input_size.width(), input_size.height(),
504 input_size.width(), 500 CoreMediaGlue::kCMVideoCodecType_H264, encoder_spec, attributes,
505 input_size.height(),
506 CoreMediaGlue::kCMVideoCodecType_H264,
507 encoder_spec,
508 attributes,
509 nullptr /* compressedDataAllocator */, 501 nullptr /* compressedDataAllocator */,
510 &VTVideoEncodeAccelerator::CompressionCallback, 502 &VTVideoEncodeAccelerator::CompressionCallback,
511 reinterpret_cast<void*>(this), 503 reinterpret_cast<void*>(this), compression_session_.InitializeInto());
512 compression_session_.InitializeInto());
513 if (status != noErr) { 504 if (status != noErr) {
514 DLOG(ERROR) << " VTCompressionSessionCreate failed: " << status; 505 DLOG(ERROR) << " VTCompressionSessionCreate failed: " << status;
515 return false; 506 return false;
516 } 507 }
517 DVLOG(3) << " VTCompressionSession created with HW encode: " 508 DVLOG(3) << " VTCompressionSession created with HW encode: "
518 << require_hw_encoding << ", input size=" << input_size.ToString(); 509 << require_hw_encoding << ", input size=" << input_size.ToString();
519 return true; 510 return true;
520 } 511 }
521 512
522 bool VTVideoEncodeAccelerator::ConfigureCompressionSession() { 513 bool VTVideoEncodeAccelerator::ConfigureCompressionSession() {
(...skipping 19 matching lines...) Expand all
542 DCHECK(thread_checker_.CalledOnValidThread() || 533 DCHECK(thread_checker_.CalledOnValidThread() ||
543 (encoder_thread_.IsRunning() && 534 (encoder_thread_.IsRunning() &&
544 encoder_thread_task_runner_->BelongsToCurrentThread())); 535 encoder_thread_task_runner_->BelongsToCurrentThread()));
545 536
546 if (compression_session_) { 537 if (compression_session_) {
547 videotoolbox_glue_->VTCompressionSessionInvalidate(compression_session_); 538 videotoolbox_glue_->VTCompressionSessionInvalidate(compression_session_);
548 compression_session_.reset(); 539 compression_session_.reset();
549 } 540 }
550 } 541 }
551 542
552 } // namespace content 543 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698