OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 * | 9 * |
10 */ | 10 */ |
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
458 kVTCompressionPropertyKey_AllowFrameReordering, | 458 kVTCompressionPropertyKey_AllowFrameReordering, |
459 false); | 459 false); |
460 SetEncoderBitrateBps(target_bitrate_bps_); | 460 SetEncoderBitrateBps(target_bitrate_bps_); |
461 // TODO(tkchin): Look at entropy mode and colorspace matrices. | 461 // TODO(tkchin): Look at entropy mode and colorspace matrices. |
462 // TODO(tkchin): Investigate to see if there's any way to make this work. | 462 // TODO(tkchin): Investigate to see if there's any way to make this work. |
463 // May need it to interop with Android. Currently this call just fails. | 463 // May need it to interop with Android. Currently this call just fails. |
464 // On inspecting encoder output on iOS8, this value is set to 6. | 464 // On inspecting encoder output on iOS8, this value is set to 6. |
465 // internal::SetVTSessionProperty(compression_session_, | 465 // internal::SetVTSessionProperty(compression_session_, |
466 // kVTCompressionPropertyKey_MaxFrameDelayCount, | 466 // kVTCompressionPropertyKey_MaxFrameDelayCount, |
467 // 1); | 467 // 1); |
468 // TODO(tkchin): See if enforcing keyframe frequency is beneficial in any | 468 |
469 // way. | 469 // Set a relatively large value for keyframe emission (7200 frames or |
470 // internal::SetVTSessionProperty( | 470 // 4 minutes). |
471 // compression_session_, | 471 internal::SetVTSessionProperty( |
472 // kVTCompressionPropertyKey_MaxKeyFrameInterval, 240); | 472 compression_session_, |
473 // internal::SetVTSessionProperty( | 473 kVTCompressionPropertyKey_MaxKeyFrameInterval, 7200); |
mflodman
2016/06/02 05:09:35
Good to have the same on both intervals, in case o
| |
474 // compression_session_, | 474 internal::SetVTSessionProperty( |
475 // kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration, 240); | 475 compression_session_, |
476 kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration, 240); | |
476 } | 477 } |
477 | 478 |
478 void H264VideoToolboxEncoder::DestroyCompressionSession() { | 479 void H264VideoToolboxEncoder::DestroyCompressionSession() { |
479 if (compression_session_) { | 480 if (compression_session_) { |
480 VTCompressionSessionInvalidate(compression_session_); | 481 VTCompressionSessionInvalidate(compression_session_); |
481 CFRelease(compression_session_); | 482 CFRelease(compression_session_); |
482 compression_session_ = nullptr; | 483 compression_session_ = nullptr; |
483 } | 484 } |
484 } | 485 } |
485 | 486 |
486 const char* H264VideoToolboxEncoder::ImplementationName() const { | 487 const char* H264VideoToolboxEncoder::ImplementationName() const { |
487 return "VideoToolbox"; | 488 return "VideoToolbox"; |
488 } | 489 } |
489 | 490 |
490 void H264VideoToolboxEncoder::SetBitrateBps(uint32_t bitrate_bps) { | 491 void H264VideoToolboxEncoder::SetBitrateBps(uint32_t bitrate_bps) { |
491 if (encoder_bitrate_bps_ != bitrate_bps) { | 492 if (encoder_bitrate_bps_ != bitrate_bps) { |
492 SetEncoderBitrateBps(bitrate_bps); | 493 SetEncoderBitrateBps(bitrate_bps); |
493 } | 494 } |
494 } | 495 } |
495 | 496 |
496 void H264VideoToolboxEncoder::SetEncoderBitrateBps(uint32_t bitrate_bps) { | 497 void H264VideoToolboxEncoder::SetEncoderBitrateBps(uint32_t bitrate_bps) { |
497 if (compression_session_) { | 498 if (compression_session_) { |
498 internal::SetVTSessionProperty(compression_session_, | 499 internal::SetVTSessionProperty(compression_session_, |
499 kVTCompressionPropertyKey_AverageBitRate, | 500 kVTCompressionPropertyKey_AverageBitRate, |
500 bitrate_bps); | 501 bitrate_bps); |
502 | |
503 // TODO(tkchin): Add a helper method to set array value. | |
504 int64_t bytes_per_second_value = bitrate_bps / 8; | |
505 CFNumberRef bytes_per_second = | |
506 CFNumberCreate(kCFAllocatorDefault, | |
507 kCFNumberSInt64Type, | |
508 &bytes_per_second_value); | |
509 int64_t one_second_value = 1; | |
510 CFNumberRef one_second = | |
511 CFNumberCreate(kCFAllocatorDefault, | |
512 kCFNumberSInt64Type, | |
513 &one_second_value); | |
514 const void* nums[2] = { bytes_per_second, one_second }; | |
515 CFArrayRef data_rate_limits = | |
516 CFArrayCreate(nullptr, nums, 2, &kCFTypeArrayCallBacks); | |
517 OSStatus status = | |
518 VTSessionSetProperty(compression_session_, | |
519 kVTCompressionPropertyKey_DataRateLimits, | |
mflodman
2016/06/02 05:09:35
I didn't see any good documentation around this, b
| |
520 data_rate_limits); | |
521 if (bytes_per_second) { | |
522 CFRelease(bytes_per_second); | |
523 } | |
524 if (one_second) { | |
525 CFRelease(one_second); | |
526 } | |
527 if (data_rate_limits) { | |
528 CFRelease(data_rate_limits); | |
529 } | |
530 if (status != noErr) { | |
531 LOG(LS_ERROR) << "Failed to set data rate limit"; | |
532 } | |
533 | |
501 encoder_bitrate_bps_ = bitrate_bps; | 534 encoder_bitrate_bps_ = bitrate_bps; |
502 } | 535 } |
503 } | 536 } |
504 | 537 |
505 void H264VideoToolboxEncoder::OnEncodedFrame( | 538 void H264VideoToolboxEncoder::OnEncodedFrame( |
506 OSStatus status, | 539 OSStatus status, |
507 VTEncodeInfoFlags info_flags, | 540 VTEncodeInfoFlags info_flags, |
508 CMSampleBufferRef sample_buffer, | 541 CMSampleBufferRef sample_buffer, |
509 CodecSpecificInfo codec_specific_info, | 542 CodecSpecificInfo codec_specific_info, |
510 int32_t width, | 543 int32_t width, |
(...skipping 15 matching lines...) Expand all Loading... | |
526 bool is_keyframe = false; | 559 bool is_keyframe = false; |
527 CFArrayRef attachments = | 560 CFArrayRef attachments = |
528 CMSampleBufferGetSampleAttachmentsArray(sample_buffer, 0); | 561 CMSampleBufferGetSampleAttachmentsArray(sample_buffer, 0); |
529 if (attachments != nullptr && CFArrayGetCount(attachments)) { | 562 if (attachments != nullptr && CFArrayGetCount(attachments)) { |
530 CFDictionaryRef attachment = | 563 CFDictionaryRef attachment = |
531 static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(attachments, 0)); | 564 static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(attachments, 0)); |
532 is_keyframe = | 565 is_keyframe = |
533 !CFDictionaryContainsKey(attachment, kCMSampleAttachmentKey_NotSync); | 566 !CFDictionaryContainsKey(attachment, kCMSampleAttachmentKey_NotSync); |
534 } | 567 } |
535 | 568 |
569 if (is_keyframe) { | |
570 LOG(LS_INFO) << "Generated keyframe"; | |
571 } | |
572 | |
536 // Convert the sample buffer into a buffer suitable for RTP packetization. | 573 // Convert the sample buffer into a buffer suitable for RTP packetization. |
537 // TODO(tkchin): Allocate buffers through a pool. | 574 // TODO(tkchin): Allocate buffers through a pool. |
538 std::unique_ptr<rtc::Buffer> buffer(new rtc::Buffer()); | 575 std::unique_ptr<rtc::Buffer> buffer(new rtc::Buffer()); |
539 std::unique_ptr<webrtc::RTPFragmentationHeader> header; | 576 std::unique_ptr<webrtc::RTPFragmentationHeader> header; |
540 { | 577 { |
541 webrtc::RTPFragmentationHeader* header_raw; | 578 webrtc::RTPFragmentationHeader* header_raw; |
542 bool result = H264CMSampleBufferToAnnexBBuffer(sample_buffer, is_keyframe, | 579 bool result = H264CMSampleBufferToAnnexBBuffer(sample_buffer, is_keyframe, |
543 buffer.get(), &header_raw); | 580 buffer.get(), &header_raw); |
544 header.reset(header_raw); | 581 header.reset(header_raw); |
545 if (!result) { | 582 if (!result) { |
(...skipping 21 matching lines...) Expand all Loading... | |
567 if (result != 0) { | 604 if (result != 0) { |
568 LOG(LS_ERROR) << "Encode callback failed: " << result; | 605 LOG(LS_ERROR) << "Encode callback failed: " << result; |
569 return; | 606 return; |
570 } | 607 } |
571 bitrate_adjuster_.Update(frame._size); | 608 bitrate_adjuster_.Update(frame._size); |
572 } | 609 } |
573 | 610 |
574 } // namespace webrtc | 611 } // namespace webrtc |
575 | 612 |
576 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) | 613 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) |
OLD | NEW |