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 17 matching lines...) Expand all Loading... |
28 inline CFDictionaryRef CreateCFDictionary(CFTypeRef* keys, | 28 inline CFDictionaryRef CreateCFDictionary(CFTypeRef* keys, |
29 CFTypeRef* values, | 29 CFTypeRef* values, |
30 size_t size) { | 30 size_t size) { |
31 return CFDictionaryCreate(kCFAllocatorDefault, keys, values, size, | 31 return CFDictionaryCreate(kCFAllocatorDefault, keys, values, size, |
32 &kCFTypeDictionaryKeyCallBacks, | 32 &kCFTypeDictionaryKeyCallBacks, |
33 &kCFTypeDictionaryValueCallBacks); | 33 &kCFTypeDictionaryValueCallBacks); |
34 } | 34 } |
35 | 35 |
36 // Copies characters from a CFStringRef into a std::string. | 36 // Copies characters from a CFStringRef into a std::string. |
37 std::string CFStringToString(const CFStringRef cf_string) { | 37 std::string CFStringToString(const CFStringRef cf_string) { |
38 DCHECK(cf_string); | 38 RTC_DCHECK(cf_string); |
39 std::string std_string; | 39 std::string std_string; |
40 // Get the size needed for UTF8 plus terminating character. | 40 // Get the size needed for UTF8 plus terminating character. |
41 size_t buffer_size = | 41 size_t buffer_size = |
42 CFStringGetMaximumSizeForEncoding(CFStringGetLength(cf_string), | 42 CFStringGetMaximumSizeForEncoding(CFStringGetLength(cf_string), |
43 kCFStringEncodingUTF8) + | 43 kCFStringEncodingUTF8) + |
44 1; | 44 1; |
45 rtc::scoped_ptr<char[]> buffer(new char[buffer_size]); | 45 rtc::scoped_ptr<char[]> buffer(new char[buffer_size]); |
46 if (CFStringGetCString(cf_string, buffer.get(), buffer_size, | 46 if (CFStringGetCString(cf_string, buffer.get(), buffer_size, |
47 kCFStringEncodingUTF8)) { | 47 kCFStringEncodingUTF8)) { |
48 // Copy over the characters. | 48 // Copy over the characters. |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 int32_t height; | 116 int32_t height; |
117 int64_t render_time_ms; | 117 int64_t render_time_ms; |
118 uint32_t timestamp; | 118 uint32_t timestamp; |
119 }; | 119 }; |
120 | 120 |
121 // We receive I420Frames as input, but we need to feed CVPixelBuffers into the | 121 // We receive I420Frames as input, but we need to feed CVPixelBuffers into the |
122 // encoder. This performs the copy and format conversion. | 122 // encoder. This performs the copy and format conversion. |
123 // TODO(tkchin): See if encoder will accept i420 frames and compare performance. | 123 // TODO(tkchin): See if encoder will accept i420 frames and compare performance. |
124 bool CopyVideoFrameToPixelBuffer(const webrtc::VideoFrame& frame, | 124 bool CopyVideoFrameToPixelBuffer(const webrtc::VideoFrame& frame, |
125 CVPixelBufferRef pixel_buffer) { | 125 CVPixelBufferRef pixel_buffer) { |
126 DCHECK(pixel_buffer); | 126 RTC_DCHECK(pixel_buffer); |
127 DCHECK(CVPixelBufferGetPixelFormatType(pixel_buffer) == | 127 RTC_DCHECK(CVPixelBufferGetPixelFormatType(pixel_buffer) == |
128 kCVPixelFormatType_420YpCbCr8BiPlanarFullRange); | 128 kCVPixelFormatType_420YpCbCr8BiPlanarFullRange); |
129 DCHECK(CVPixelBufferGetHeightOfPlane(pixel_buffer, 0) == | 129 RTC_DCHECK(CVPixelBufferGetHeightOfPlane(pixel_buffer, 0) == |
130 static_cast<size_t>(frame.height())); | 130 static_cast<size_t>(frame.height())); |
131 DCHECK(CVPixelBufferGetWidthOfPlane(pixel_buffer, 0) == | 131 RTC_DCHECK(CVPixelBufferGetWidthOfPlane(pixel_buffer, 0) == |
132 static_cast<size_t>(frame.width())); | 132 static_cast<size_t>(frame.width())); |
133 | 133 |
134 CVReturn cvRet = CVPixelBufferLockBaseAddress(pixel_buffer, 0); | 134 CVReturn cvRet = CVPixelBufferLockBaseAddress(pixel_buffer, 0); |
135 if (cvRet != kCVReturnSuccess) { | 135 if (cvRet != kCVReturnSuccess) { |
136 LOG(LS_ERROR) << "Failed to lock base address: " << cvRet; | 136 LOG(LS_ERROR) << "Failed to lock base address: " << cvRet; |
137 return false; | 137 return false; |
138 } | 138 } |
139 uint8* dst_y = reinterpret_cast<uint8*>( | 139 uint8* dst_y = reinterpret_cast<uint8*>( |
140 CVPixelBufferGetBaseAddressOfPlane(pixel_buffer, 0)); | 140 CVPixelBufferGetBaseAddressOfPlane(pixel_buffer, 0)); |
141 int dst_stride_y = CVPixelBufferGetBytesPerRowOfPlane(pixel_buffer, 0); | 141 int dst_stride_y = CVPixelBufferGetBytesPerRowOfPlane(pixel_buffer, 0); |
142 uint8* dst_uv = reinterpret_cast<uint8*>( | 142 uint8* dst_uv = reinterpret_cast<uint8*>( |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 : callback_(nullptr), compression_session_(nullptr) { | 217 : callback_(nullptr), compression_session_(nullptr) { |
218 } | 218 } |
219 | 219 |
220 H264VideoToolboxEncoder::~H264VideoToolboxEncoder() { | 220 H264VideoToolboxEncoder::~H264VideoToolboxEncoder() { |
221 DestroyCompressionSession(); | 221 DestroyCompressionSession(); |
222 } | 222 } |
223 | 223 |
224 int H264VideoToolboxEncoder::InitEncode(const VideoCodec* codec_settings, | 224 int H264VideoToolboxEncoder::InitEncode(const VideoCodec* codec_settings, |
225 int number_of_cores, | 225 int number_of_cores, |
226 size_t max_payload_size) { | 226 size_t max_payload_size) { |
227 DCHECK(codec_settings); | 227 RTC_DCHECK(codec_settings); |
228 DCHECK_EQ(codec_settings->codecType, kVideoCodecH264); | 228 RTC_DCHECK_EQ(codec_settings->codecType, kVideoCodecH264); |
229 // TODO(tkchin): We may need to enforce width/height dimension restrictions | 229 // TODO(tkchin): We may need to enforce width/height dimension restrictions |
230 // to match what the encoder supports. | 230 // to match what the encoder supports. |
231 width_ = codec_settings->width; | 231 width_ = codec_settings->width; |
232 height_ = codec_settings->height; | 232 height_ = codec_settings->height; |
233 // We can only set average bitrate on the HW encoder. | 233 // We can only set average bitrate on the HW encoder. |
234 bitrate_ = codec_settings->startBitrate * 1000; | 234 bitrate_ = codec_settings->startBitrate * 1000; |
235 | 235 |
236 // TODO(tkchin): Try setting payload size via | 236 // TODO(tkchin): Try setting payload size via |
237 // kVTCompressionPropertyKey_MaxH264SliceBytes. | 237 // kVTCompressionPropertyKey_MaxH264SliceBytes. |
238 | 238 |
(...skipping 20 matching lines...) Expand all Loading... |
259 VTCompressionSessionGetPixelBufferPool(compression_session_); | 259 VTCompressionSessionGetPixelBufferPool(compression_session_); |
260 CVPixelBufferRef pixel_buffer = nullptr; | 260 CVPixelBufferRef pixel_buffer = nullptr; |
261 CVReturn ret = CVPixelBufferPoolCreatePixelBuffer(nullptr, pixel_buffer_pool, | 261 CVReturn ret = CVPixelBufferPoolCreatePixelBuffer(nullptr, pixel_buffer_pool, |
262 &pixel_buffer); | 262 &pixel_buffer); |
263 if (ret != kCVReturnSuccess) { | 263 if (ret != kCVReturnSuccess) { |
264 LOG(LS_ERROR) << "Failed to create pixel buffer: " << ret; | 264 LOG(LS_ERROR) << "Failed to create pixel buffer: " << ret; |
265 // We probably want to drop frames here, since failure probably means | 265 // We probably want to drop frames here, since failure probably means |
266 // that the pool is empty. | 266 // that the pool is empty. |
267 return WEBRTC_VIDEO_CODEC_ERROR; | 267 return WEBRTC_VIDEO_CODEC_ERROR; |
268 } | 268 } |
269 DCHECK(pixel_buffer); | 269 RTC_DCHECK(pixel_buffer); |
270 if (!internal::CopyVideoFrameToPixelBuffer(input_image, pixel_buffer)) { | 270 if (!internal::CopyVideoFrameToPixelBuffer(input_image, pixel_buffer)) { |
271 LOG(LS_ERROR) << "Failed to copy frame data."; | 271 LOG(LS_ERROR) << "Failed to copy frame data."; |
272 CVBufferRelease(pixel_buffer); | 272 CVBufferRelease(pixel_buffer); |
273 return WEBRTC_VIDEO_CODEC_ERROR; | 273 return WEBRTC_VIDEO_CODEC_ERROR; |
274 } | 274 } |
275 | 275 |
276 // Check if we need a keyframe. | 276 // Check if we need a keyframe. |
277 bool is_keyframe_required = false; | 277 bool is_keyframe_required = false; |
278 if (frame_types) { | 278 if (frame_types) { |
279 for (auto frame_type : *frame_types) { | 279 for (auto frame_type : *frame_types) { |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 } | 390 } |
391 if (status != noErr) { | 391 if (status != noErr) { |
392 LOG(LS_ERROR) << "Failed to create compression session: " << status; | 392 LOG(LS_ERROR) << "Failed to create compression session: " << status; |
393 return WEBRTC_VIDEO_CODEC_ERROR; | 393 return WEBRTC_VIDEO_CODEC_ERROR; |
394 } | 394 } |
395 ConfigureCompressionSession(); | 395 ConfigureCompressionSession(); |
396 return WEBRTC_VIDEO_CODEC_OK; | 396 return WEBRTC_VIDEO_CODEC_OK; |
397 } | 397 } |
398 | 398 |
399 void H264VideoToolboxEncoder::ConfigureCompressionSession() { | 399 void H264VideoToolboxEncoder::ConfigureCompressionSession() { |
400 DCHECK(compression_session_); | 400 RTC_DCHECK(compression_session_); |
401 internal::SetVTSessionProperty(compression_session_, | 401 internal::SetVTSessionProperty(compression_session_, |
402 kVTCompressionPropertyKey_RealTime, true); | 402 kVTCompressionPropertyKey_RealTime, true); |
403 internal::SetVTSessionProperty(compression_session_, | 403 internal::SetVTSessionProperty(compression_session_, |
404 kVTCompressionPropertyKey_ProfileLevel, | 404 kVTCompressionPropertyKey_ProfileLevel, |
405 kVTProfileLevel_H264_Baseline_AutoLevel); | 405 kVTProfileLevel_H264_Baseline_AutoLevel); |
406 internal::SetVTSessionProperty( | 406 internal::SetVTSessionProperty( |
407 compression_session_, kVTCompressionPropertyKey_AverageBitRate, bitrate_); | 407 compression_session_, kVTCompressionPropertyKey_AverageBitRate, bitrate_); |
408 internal::SetVTSessionProperty(compression_session_, | 408 internal::SetVTSessionProperty(compression_session_, |
409 kVTCompressionPropertyKey_AllowFrameReordering, | 409 kVTCompressionPropertyKey_AllowFrameReordering, |
410 false); | 410 false); |
(...skipping 18 matching lines...) Expand all Loading... |
429 if (compression_session_) { | 429 if (compression_session_) { |
430 VTCompressionSessionInvalidate(compression_session_); | 430 VTCompressionSessionInvalidate(compression_session_); |
431 CFRelease(compression_session_); | 431 CFRelease(compression_session_); |
432 compression_session_ = nullptr; | 432 compression_session_ = nullptr; |
433 } | 433 } |
434 } | 434 } |
435 | 435 |
436 } // namespace webrtc | 436 } // namespace webrtc |
437 | 437 |
438 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) | 438 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) |
OLD | NEW |