| 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 |