Chromium Code Reviews| Index: media/cast/sender/h264_vt_encoder.cc |
| diff --git a/media/cast/sender/h264_vt_encoder.cc b/media/cast/sender/h264_vt_encoder.cc |
| index 33923488c51daa96b99847893ea713204588837c..d740b8026d1f463bd36346b801f00e16bbb83a68 100644 |
| --- a/media/cast/sender/h264_vt_encoder.cc |
| +++ b/media/cast/sender/h264_vt_encoder.cc |
| @@ -11,6 +11,7 @@ |
| #include "base/bind_helpers.h" |
| #include "base/location.h" |
| #include "base/logging.h" |
| +#include "base/macros.h" |
| #include "media/base/mac/corevideo_glue.h" |
| #include "media/base/mac/video_frame_mac.h" |
| #include "media/cast/sender/video_frame_factory.h" |
| @@ -43,6 +44,21 @@ base::ScopedCFTypeRef<CFDictionaryRef> DictionaryWithKeyValue(CFTypeRef key, |
| &kCFTypeDictionaryValueCallBacks)); |
| } |
| +base::ScopedCFTypeRef<CFArrayRef> ArrayWithIntegers(const std::vector<int>& v) { |
| + std::vector<CFNumberRef> numbers; |
| + numbers.reserve(v.size()); |
| + for (const int i : v) { |
| + numbers.push_back(CFNumberCreate(nullptr, kCFNumberSInt32Type, &i)); |
| + } |
| + base::ScopedCFTypeRef<CFArrayRef> array(CFArrayCreate( |
| + kCFAllocatorDefault, reinterpret_cast<const void**>(&numbers[0]), |
| + numbers.size(), &kCFTypeArrayCallBacks)); |
| + for (CFNumberRef number : numbers) { |
| + CFRelease(number); |
| + } |
| + return array; |
| +} |
| + |
| template <typename NalSizeType> |
| void CopyNalsToAnnexB(char* avcc_buffer, |
| const size_t avcc_size, |
| @@ -257,11 +273,20 @@ bool H264VideoToolboxEncoder::Initialize( |
| kCFBooleanTrue); |
| #endif |
| + // Certain encoders prefer kCVPixelFormatType_422YpCbCr8, which is not |
| + // supported through VideoFrame. We can force 420 formats to be used instead. |
| + const int formats[] = { |
| + kCVPixelFormatType_420YpCbCr8Planar, |
| + CoreVideoGlue::kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange}; |
| + base::ScopedCFTypeRef<CFArrayRef> formats_array = ArrayWithIntegers( |
| + std::vector<int>(formats, formats + arraysize(formats))); |
| + base::ScopedCFTypeRef<CFDictionaryRef> buffer_attributes = |
| + DictionaryWithKeyValue(kCVPixelBufferPixelFormatTypeKey, formats_array); |
| + |
| VTCompressionSessionRef session; |
| OSStatus status = videotoolbox_glue_->VTCompressionSessionCreate( |
| kCFAllocatorDefault, video_config.width, video_config.height, |
| - CoreMediaGlue::kCMVideoCodecType_H264, encoder_spec, |
| - nullptr /* sourceImageBufferAttributes */, |
| + CoreMediaGlue::kCMVideoCodecType_H264, encoder_spec, buffer_attributes, |
| nullptr /* compressedDataAllocator */, |
| &H264VideoToolboxEncoder::CompressionCallback, |
| reinterpret_cast<void*>(this), &session); |
| @@ -309,6 +334,11 @@ void H264VideoToolboxEncoder::ConfigureSession( |
| SetSessionProperty( |
| videotoolbox_glue_->kVTCompressionPropertyKey_YCbCrMatrix(), |
| kCVImageBufferYCbCrMatrix_ITU_R_709_2); |
| + if (video_config.max_number_of_video_buffers_used > 0) { |
| + SetSessionProperty( |
| + videotoolbox_glue_->kVTCompressionPropertyKey_MaxFrameDelayCount(), |
| + video_config.max_number_of_video_buffers_used); |
|
miu
2015/01/21 23:24:27
VideoSenderConfig::max_number_of_video_buffers_use
|
| + } |
| } |
| void H264VideoToolboxEncoder::Teardown() { |
| @@ -404,6 +434,21 @@ H264VideoToolboxEncoder::CreateVideoFrameFactory() { |
| new VideoFrameFactoryCVPixelBufferPoolImpl(pool)); |
| } |
| +void H264VideoToolboxEncoder::EmitFrames() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + |
| + if (!compression_session_) { |
| + DLOG(ERROR) << " compression session is null"; |
| + return; |
| + } |
| + |
| + OSStatus status = videotoolbox_glue_->VTCompressionSessionCompleteFrames( |
| + compression_session_, CoreMediaGlue::CMTime{0, 0, 0, 0}); |
| + if (status != noErr) { |
| + DLOG(ERROR) << " VTCompressionSessionCompleteFrames failed: " << status; |
| + } |
| +} |
| + |
| bool H264VideoToolboxEncoder::SetSessionProperty(CFStringRef key, |
| int32_t value) { |
| base::ScopedCFTypeRef<CFNumberRef> cfvalue( |