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 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 RTC_DCHECK(pixel_buffer); | 126 RTC_DCHECK(pixel_buffer); |
127 RTC_DCHECK(CVPixelBufferGetPixelFormatType(pixel_buffer) == | |
128 kCVPixelFormatType_420YpCbCr8BiPlanarFullRange); | |
129 RTC_DCHECK(CVPixelBufferGetHeightOfPlane(pixel_buffer, 0) == | 127 RTC_DCHECK(CVPixelBufferGetHeightOfPlane(pixel_buffer, 0) == |
130 static_cast<size_t>(frame.height())); | 128 static_cast<size_t>(frame.height())); |
131 RTC_DCHECK(CVPixelBufferGetWidthOfPlane(pixel_buffer, 0) == | 129 RTC_DCHECK(CVPixelBufferGetWidthOfPlane(pixel_buffer, 0) == |
132 static_cast<size_t>(frame.width())); | 130 static_cast<size_t>(frame.width())); |
133 | 131 |
134 CVReturn cvRet = CVPixelBufferLockBaseAddress(pixel_buffer, 0); | 132 OSType format = CVPixelBufferGetPixelFormatType(pixel_buffer); |
135 if (cvRet != kCVReturnSuccess) { | 133 if (format == kCVPixelFormatType_420YpCbCr8Planar || |
136 LOG(LS_ERROR) << "Failed to lock base address: " << cvRet; | 134 format == kCVPixelFormatType_420YpCbCr8PlanarFullRange) { |
137 return false; | 135 CVPixelBufferLockBaseAddress(pixel_buffer, 0); |
138 } | 136 for (size_t planeIndex = 0; |
139 uint8_t* dst_y = reinterpret_cast<uint8_t*>( | 137 planeIndex < CVPixelBufferGetPlaneCount(pixel_buffer); planeIndex++) { |
140 CVPixelBufferGetBaseAddressOfPlane(pixel_buffer, 0)); | 138 void* baseAddress = |
141 int dst_stride_y = CVPixelBufferGetBytesPerRowOfPlane(pixel_buffer, 0); | 139 CVPixelBufferGetBaseAddressOfPlane(pixel_buffer, planeIndex); |
142 uint8_t* dst_uv = reinterpret_cast<uint8_t*>( | 140 memcpy(baseAddress, frame.buffer((webrtc::PlaneType)planeIndex), |
143 CVPixelBufferGetBaseAddressOfPlane(pixel_buffer, 1)); | 141 frame.allocated_size((webrtc::PlaneType)planeIndex)); |
144 int dst_stride_uv = CVPixelBufferGetBytesPerRowOfPlane(pixel_buffer, 1); | 142 } |
145 // Convert I420 to NV12. | 143 CVPixelBufferUnlockBaseAddress(pixel_buffer, 0); |
146 int ret = libyuv::I420ToNV12( | 144 } else if (format == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange || |
147 frame.buffer(webrtc::kYPlane), frame.stride(webrtc::kYPlane), | 145 format == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) { |
148 frame.buffer(webrtc::kUPlane), frame.stride(webrtc::kUPlane), | 146 CVReturn cvRet = CVPixelBufferLockBaseAddress(pixel_buffer, 0); |
149 frame.buffer(webrtc::kVPlane), frame.stride(webrtc::kVPlane), | 147 if (cvRet != kCVReturnSuccess) { |
150 dst_y, dst_stride_y, dst_uv, dst_stride_uv, | 148 LOG(LS_ERROR) << "Failed to lock base address: " << cvRet; |
151 frame.width(), frame.height()); | 149 return false; |
152 CVPixelBufferUnlockBaseAddress(pixel_buffer, 0); | 150 } |
153 if (ret) { | 151 uint8_t* dst_y = reinterpret_cast<uint8_t*>( |
154 LOG(LS_ERROR) << "Error converting I420 VideoFrame to NV12 :" << ret; | 152 CVPixelBufferGetBaseAddressOfPlane(pixel_buffer, 0)); |
| 153 int dst_stride_y = CVPixelBufferGetBytesPerRowOfPlane(pixel_buffer, 0); |
| 154 uint8_t* dst_uv = reinterpret_cast<uint8_t*>( |
| 155 CVPixelBufferGetBaseAddressOfPlane(pixel_buffer, 1)); |
| 156 int dst_stride_uv = CVPixelBufferGetBytesPerRowOfPlane(pixel_buffer, 1); |
| 157 // Convert I420 to NV12. |
| 158 int ret = libyuv::I420ToNV12( |
| 159 frame.buffer(webrtc::kYPlane), frame.stride(webrtc::kYPlane), |
| 160 frame.buffer(webrtc::kUPlane), frame.stride(webrtc::kUPlane), |
| 161 frame.buffer(webrtc::kVPlane), frame.stride(webrtc::kVPlane), dst_y, |
| 162 dst_stride_y, dst_uv, dst_stride_uv, frame.width(), frame.height()); |
| 163 CVPixelBufferUnlockBaseAddress(pixel_buffer, 0); |
| 164 if (ret) { |
| 165 LOG(LS_ERROR) << "Error converting I420 VideoFrame to NV12 :" << ret; |
| 166 return false; |
| 167 } |
| 168 |
| 169 } else { |
| 170 LOG(LS_ERROR) << "Unsupported pixel format type :" << format; |
155 return false; | 171 return false; |
156 } | 172 } |
157 return true; | 173 return true; |
158 } | 174 } |
159 | 175 |
160 // This is the callback function that VideoToolbox calls when encode is | 176 // This is the callback function that VideoToolbox calls when encode is |
161 // complete. | 177 // complete. |
162 void VTCompressionOutputCallback(void* encoder, | 178 void VTCompressionOutputCallback(void* encoder, |
163 void* params, | 179 void* params, |
164 OSStatus status, | 180 OSStatus status, |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 #if defined(WEBRTC_IOS) | 365 #if defined(WEBRTC_IOS) |
350 kCVPixelBufferOpenGLESCompatibilityKey, | 366 kCVPixelBufferOpenGLESCompatibilityKey, |
351 #elif defined(WEBRTC_MAC) | 367 #elif defined(WEBRTC_MAC) |
352 kCVPixelBufferOpenGLCompatibilityKey, | 368 kCVPixelBufferOpenGLCompatibilityKey, |
353 #endif | 369 #endif |
354 kCVPixelBufferIOSurfacePropertiesKey, | 370 kCVPixelBufferIOSurfacePropertiesKey, |
355 kCVPixelBufferPixelFormatTypeKey | 371 kCVPixelBufferPixelFormatTypeKey |
356 }; | 372 }; |
357 CFDictionaryRef io_surface_value = | 373 CFDictionaryRef io_surface_value = |
358 internal::CreateCFDictionary(nullptr, nullptr, 0); | 374 internal::CreateCFDictionary(nullptr, nullptr, 0); |
359 int64_t nv12type = kCVPixelFormatType_420YpCbCr8BiPlanarFullRange; | 375 OSType i420type = kCVPixelFormatType_420YpCbCr8Planar; |
360 CFNumberRef pixel_format = | 376 CFNumberRef pixel_format = |
361 CFNumberCreate(nullptr, kCFNumberLongType, &nv12type); | 377 CFNumberCreate(nullptr, kCFNumberSInt32Type, &i420type); |
362 CFTypeRef values[attributes_size] = { | 378 CFTypeRef values[attributes_size] = { |
363 kCFBooleanTrue, | 379 kCFBooleanTrue, |
364 io_surface_value, | 380 io_surface_value, |
365 pixel_format | 381 pixel_format |
366 }; | 382 }; |
367 CFDictionaryRef source_attributes = | 383 CFDictionaryRef source_attributes = |
368 internal::CreateCFDictionary(keys, values, attributes_size); | 384 internal::CreateCFDictionary(keys, values, attributes_size); |
369 if (io_surface_value) { | 385 if (io_surface_value) { |
370 CFRelease(io_surface_value); | 386 CFRelease(io_surface_value); |
371 io_surface_value = nullptr; | 387 io_surface_value = nullptr; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
430 if (compression_session_) { | 446 if (compression_session_) { |
431 VTCompressionSessionInvalidate(compression_session_); | 447 VTCompressionSessionInvalidate(compression_session_); |
432 CFRelease(compression_session_); | 448 CFRelease(compression_session_); |
433 compression_session_ = nullptr; | 449 compression_session_ = nullptr; |
434 } | 450 } |
435 } | 451 } |
436 | 452 |
437 } // namespace webrtc | 453 } // namespace webrtc |
438 | 454 |
439 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) | 455 #endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) |
OLD | NEW |