OLD | NEW |
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 24 matching lines...) Expand all Loading... |
35 InProgressFrameEncode(base::TimeDelta rtp_timestamp, base::TimeTicks ref_time) | 35 InProgressFrameEncode(base::TimeDelta rtp_timestamp, base::TimeTicks ref_time) |
36 : timestamp(rtp_timestamp), reference_time(ref_time) {} | 36 : timestamp(rtp_timestamp), reference_time(ref_time) {} |
37 const base::TimeDelta timestamp; | 37 const base::TimeDelta timestamp; |
38 const base::TimeTicks reference_time; | 38 const base::TimeTicks reference_time; |
39 | 39 |
40 private: | 40 private: |
41 DISALLOW_IMPLICIT_CONSTRUCTORS(InProgressFrameEncode); | 41 DISALLOW_IMPLICIT_CONSTRUCTORS(InProgressFrameEncode); |
42 }; | 42 }; |
43 | 43 |
44 struct VTVideoEncodeAccelerator::EncodeOutput { | 44 struct VTVideoEncodeAccelerator::EncodeOutput { |
45 EncodeOutput(VTEncodeInfoFlags info_flags, CMSampleBufferRef sbuf) | 45 EncodeOutput(VTEncodeInfoFlags info_flags, |
46 : info(info_flags), sample_buffer(sbuf, base::scoped_policy::RETAIN) {} | 46 CMSampleBufferRef sbuf, |
| 47 base::TimeDelta timestamp) |
| 48 : info(info_flags), |
| 49 sample_buffer(sbuf, base::scoped_policy::RETAIN), |
| 50 capture_timestamp(timestamp) {} |
47 const VTEncodeInfoFlags info; | 51 const VTEncodeInfoFlags info; |
48 const base::ScopedCFTypeRef<CMSampleBufferRef> sample_buffer; | 52 const base::ScopedCFTypeRef<CMSampleBufferRef> sample_buffer; |
| 53 const base::TimeDelta capture_timestamp; |
49 | 54 |
50 private: | 55 private: |
51 DISALLOW_IMPLICIT_CONSTRUCTORS(EncodeOutput); | 56 DISALLOW_IMPLICIT_CONSTRUCTORS(EncodeOutput); |
52 }; | 57 }; |
53 | 58 |
54 struct VTVideoEncodeAccelerator::BitstreamBufferRef { | 59 struct VTVideoEncodeAccelerator::BitstreamBufferRef { |
55 BitstreamBufferRef(int32_t id, | 60 BitstreamBufferRef(int32_t id, |
56 std::unique_ptr<base::SharedMemory> shm, | 61 std::unique_ptr<base::SharedMemory> shm, |
57 size_t size) | 62 size_t size) |
58 : id(id), shm(std::move(shm)), size(size) {} | 63 : id(id), shm(std::move(shm)), size(size) {} |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 OSStatus status, | 391 OSStatus status, |
387 VTEncodeInfoFlags info, | 392 VTEncodeInfoFlags info, |
388 CMSampleBufferRef sbuf) { | 393 CMSampleBufferRef sbuf) { |
389 // This function may be called asynchronously, on a different thread from the | 394 // This function may be called asynchronously, on a different thread from the |
390 // one that calls VTCompressionSessionEncodeFrame. | 395 // one that calls VTCompressionSessionEncodeFrame. |
391 DVLOG(3) << __FUNCTION__; | 396 DVLOG(3) << __FUNCTION__; |
392 | 397 |
393 auto encoder = reinterpret_cast<VTVideoEncodeAccelerator*>(encoder_opaque); | 398 auto encoder = reinterpret_cast<VTVideoEncodeAccelerator*>(encoder_opaque); |
394 DCHECK(encoder); | 399 DCHECK(encoder); |
395 | 400 |
396 // Release InProgressFrameEncode, since we don't have support to return | 401 // InProgressFrameEncode holds timestamp information of the encoded frame. |
397 // timestamps at this point. | 402 std::unique_ptr<InProgressFrameEncode> frame_info( |
398 std::unique_ptr<InProgressFrameEncode> request( | |
399 reinterpret_cast<InProgressFrameEncode*>(request_opaque)); | 403 reinterpret_cast<InProgressFrameEncode*>(request_opaque)); |
400 request.reset(); | |
401 | 404 |
402 // EncodeOutput holds onto CMSampleBufferRef when posting task between | 405 // EncodeOutput holds onto CMSampleBufferRef when posting task between |
403 // threads. | 406 // threads. |
404 std::unique_ptr<EncodeOutput> encode_output(new EncodeOutput(info, sbuf)); | 407 std::unique_ptr<EncodeOutput> encode_output( |
| 408 new EncodeOutput(info, sbuf, frame_info->timestamp)); |
405 | 409 |
406 // This method is NOT called on |encoder_thread_|, so we still need to | 410 // This method is NOT called on |encoder_thread_|, so we still need to |
407 // post a task back to it to do work. | 411 // post a task back to it to do work. |
408 encoder->encoder_thread_task_runner_->PostTask( | 412 encoder->encoder_thread_task_runner_->PostTask( |
409 FROM_HERE, base::Bind(&VTVideoEncodeAccelerator::CompressionCallbackTask, | 413 FROM_HERE, base::Bind(&VTVideoEncodeAccelerator::CompressionCallbackTask, |
410 encoder->encoder_weak_ptr_, status, | 414 encoder->encoder_weak_ptr_, status, |
411 base::Passed(&encode_output))); | 415 base::Passed(&encode_output))); |
412 } | 416 } |
413 | 417 |
414 void VTVideoEncodeAccelerator::CompressionCallbackTask( | 418 void VTVideoEncodeAccelerator::CompressionCallbackTask( |
(...skipping 24 matching lines...) Expand all Loading... |
439 std::unique_ptr<EncodeOutput> encode_output, | 443 std::unique_ptr<EncodeOutput> encode_output, |
440 std::unique_ptr<VTVideoEncodeAccelerator::BitstreamBufferRef> buffer_ref) { | 444 std::unique_ptr<VTVideoEncodeAccelerator::BitstreamBufferRef> buffer_ref) { |
441 DVLOG(3) << __FUNCTION__; | 445 DVLOG(3) << __FUNCTION__; |
442 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 446 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); |
443 | 447 |
444 if (encode_output->info & VideoToolboxGlue::kVTEncodeInfo_FrameDropped) { | 448 if (encode_output->info & VideoToolboxGlue::kVTEncodeInfo_FrameDropped) { |
445 DVLOG(2) << " frame dropped"; | 449 DVLOG(2) << " frame dropped"; |
446 client_task_runner_->PostTask( | 450 client_task_runner_->PostTask( |
447 FROM_HERE, | 451 FROM_HERE, |
448 base::Bind(&Client::BitstreamBufferReady, client_, buffer_ref->id, 0, | 452 base::Bind(&Client::BitstreamBufferReady, client_, buffer_ref->id, 0, |
449 false, base::Time::Now() - base::Time())); | 453 false, encode_output->capture_timestamp)); |
450 return; | 454 return; |
451 } | 455 } |
452 | 456 |
453 auto sample_attachments = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex( | 457 auto sample_attachments = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex( |
454 CoreMediaGlue::CMSampleBufferGetSampleAttachmentsArray( | 458 CoreMediaGlue::CMSampleBufferGetSampleAttachmentsArray( |
455 encode_output->sample_buffer.get(), true), | 459 encode_output->sample_buffer.get(), true), |
456 0)); | 460 0)); |
457 const bool keyframe = !CFDictionaryContainsKey( | 461 const bool keyframe = !CFDictionaryContainsKey( |
458 sample_attachments, CoreMediaGlue::kCMSampleAttachmentKey_NotSync()); | 462 sample_attachments, CoreMediaGlue::kCMSampleAttachmentKey_NotSync()); |
459 | 463 |
460 size_t used_buffer_size = 0; | 464 size_t used_buffer_size = 0; |
461 const bool copy_rv = media::video_toolbox::CopySampleBufferToAnnexBBuffer( | 465 const bool copy_rv = media::video_toolbox::CopySampleBufferToAnnexBBuffer( |
462 encode_output->sample_buffer.get(), keyframe, buffer_ref->size, | 466 encode_output->sample_buffer.get(), keyframe, buffer_ref->size, |
463 reinterpret_cast<char*>(buffer_ref->shm->memory()), &used_buffer_size); | 467 reinterpret_cast<char*>(buffer_ref->shm->memory()), &used_buffer_size); |
464 if (!copy_rv) { | 468 if (!copy_rv) { |
465 DLOG(ERROR) << "Cannot copy output from SampleBuffer to AnnexBBuffer."; | 469 DLOG(ERROR) << "Cannot copy output from SampleBuffer to AnnexBBuffer."; |
466 used_buffer_size = 0; | 470 used_buffer_size = 0; |
467 } | 471 } |
468 bitrate_adjuster_.Update(used_buffer_size); | 472 bitrate_adjuster_.Update(used_buffer_size); |
469 | 473 |
470 client_task_runner_->PostTask( | 474 client_task_runner_->PostTask( |
471 FROM_HERE, | 475 FROM_HERE, |
472 base::Bind(&Client::BitstreamBufferReady, client_, buffer_ref->id, | 476 base::Bind(&Client::BitstreamBufferReady, client_, buffer_ref->id, |
473 used_buffer_size, keyframe, base::Time::Now() - base::Time())); | 477 used_buffer_size, keyframe, encode_output->capture_timestamp)); |
474 } | 478 } |
475 | 479 |
476 bool VTVideoEncodeAccelerator::ResetCompressionSession() { | 480 bool VTVideoEncodeAccelerator::ResetCompressionSession() { |
477 DCHECK(thread_checker_.CalledOnValidThread()); | 481 DCHECK(thread_checker_.CalledOnValidThread()); |
478 | 482 |
479 DestroyCompressionSession(); | 483 DestroyCompressionSession(); |
480 | 484 |
481 CFTypeRef attributes_keys[] = {kCVPixelBufferOpenGLCompatibilityKey, | 485 CFTypeRef attributes_keys[] = {kCVPixelBufferOpenGLCompatibilityKey, |
482 kCVPixelBufferIOSurfacePropertiesKey, | 486 kCVPixelBufferIOSurfacePropertiesKey, |
483 kCVPixelBufferPixelFormatTypeKey}; | 487 kCVPixelBufferPixelFormatTypeKey}; |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
579 (encoder_thread_.IsRunning() && | 583 (encoder_thread_.IsRunning() && |
580 encoder_thread_task_runner_->BelongsToCurrentThread())); | 584 encoder_thread_task_runner_->BelongsToCurrentThread())); |
581 | 585 |
582 if (compression_session_) { | 586 if (compression_session_) { |
583 videotoolbox_glue_->VTCompressionSessionInvalidate(compression_session_); | 587 videotoolbox_glue_->VTCompressionSessionInvalidate(compression_session_); |
584 compression_session_.reset(); | 588 compression_session_.reset(); |
585 } | 589 } |
586 } | 590 } |
587 | 591 |
588 } // namespace media | 592 } // namespace media |
OLD | NEW |