Reland "Add unit tests for RTCCVPixelBuffer and ObjCVideoTrackSource."
This is a reland of 4ea50c2b421ae3e40d1d02b8eb8c5802288b181e Original change's description: > Add unit tests for RTCCVPixelBuffer and ObjCVideoTrackSource. > > This CL also fixes a couple of bugs found in the toI420 method for > RTCCVPixelBuffers backed by RGB CVPixelBuffers. > > Bug: webrtc:9007 > Change-Id: I19ab8177f4b124a503cfda9f0166bd960f668982 > Reviewed-on: https://webrtc-review.googlesource.com/64940 > Commit-Queue: Anders Carlsson <andersc@webrtc.org> > Reviewed-by: Kári Helgason <kthelgason@webrtc.org> > Cr-Commit-Position: refs/heads/master@{#22656} Bug: webrtc:9007 Change-Id: I2a787c64f8d23ffc4ef2419fc258d965f8a9480b Reviewed-on: https://webrtc-review.googlesource.com/66341 Reviewed-by: Kári Helgason <kthelgason@webrtc.org> Commit-Queue: Anders Carlsson <andersc@webrtc.org> Cr-Commit-Position: refs/heads/master@{#22706}
This commit is contained in:
committed by
Commit Bot
parent
74395345e8
commit
fe9d8178df
@ -28,6 +28,8 @@
|
||||
@synthesize pixelBuffer = _pixelBuffer;
|
||||
@synthesize cropX = _cropX;
|
||||
@synthesize cropY = _cropY;
|
||||
@synthesize cropWidth = _cropWidth;
|
||||
@synthesize cropHeight = _cropHeight;
|
||||
|
||||
+ (NSSet<NSNumber*>*)supportedPixelFormats {
|
||||
return [NSSet setWithObjects:@(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange),
|
||||
@ -112,16 +114,29 @@
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (BOOL)cropAndScaleTo:(CVPixelBufferRef)outputPixelBuffer withTempBuffer:(uint8_t*)tmpBuffer {
|
||||
- (BOOL)cropAndScaleTo:(CVPixelBufferRef)outputPixelBuffer
|
||||
withTempBuffer:(nullable uint8_t*)tmpBuffer {
|
||||
const OSType srcPixelFormat = CVPixelBufferGetPixelFormatType(_pixelBuffer);
|
||||
const OSType dstPixelFormat = CVPixelBufferGetPixelFormatType(outputPixelBuffer);
|
||||
|
||||
switch (srcPixelFormat) {
|
||||
case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange:
|
||||
case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: {
|
||||
[self cropAndScaleNV12To:outputPixelBuffer withTempBuffer:tmpBuffer];
|
||||
size_t dstWidth = CVPixelBufferGetWidth(outputPixelBuffer);
|
||||
size_t dstHeight = CVPixelBufferGetHeight(outputPixelBuffer);
|
||||
if (dstWidth > 0 && dstHeight > 0) {
|
||||
RTC_DCHECK(dstPixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange ||
|
||||
dstPixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange);
|
||||
if ([self requiresScalingToWidth:dstWidth height:dstHeight]) {
|
||||
RTC_DCHECK(tmpBuffer);
|
||||
}
|
||||
[self cropAndScaleNV12To:outputPixelBuffer withTempBuffer:tmpBuffer];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kCVPixelFormatType_32BGRA:
|
||||
case kCVPixelFormatType_32ARGB: {
|
||||
RTC_DCHECK(srcPixelFormat == dstPixelFormat);
|
||||
[self cropAndScaleARGBTo:outputPixelBuffer];
|
||||
break;
|
||||
}
|
||||
@ -143,10 +158,10 @@
|
||||
case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange:
|
||||
case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: {
|
||||
const uint8_t* srcY =
|
||||
static_cast<const uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(_pixelBuffer, 0));
|
||||
static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(_pixelBuffer, 0));
|
||||
const int srcYStride = CVPixelBufferGetBytesPerRowOfPlane(_pixelBuffer, 0);
|
||||
const uint8_t* srcUV =
|
||||
static_cast<const uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(_pixelBuffer, 1));
|
||||
static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(_pixelBuffer, 1));
|
||||
const int srcUVStride = CVPixelBufferGetBytesPerRowOfPlane(_pixelBuffer, 1);
|
||||
|
||||
// Crop just by modifying pointers.
|
||||
@ -173,32 +188,52 @@
|
||||
}
|
||||
case kCVPixelFormatType_32BGRA:
|
||||
case kCVPixelFormatType_32ARGB: {
|
||||
const uint8_t* src =
|
||||
static_cast<const uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(_pixelBuffer, 0));
|
||||
CVPixelBufferRef scaledPixelBuffer = NULL;
|
||||
CVPixelBufferRef sourcePixelBuffer = NULL;
|
||||
if ([self requiresCropping] ||
|
||||
[self requiresScalingToWidth:i420Buffer.width height:i420Buffer.height]) {
|
||||
CVPixelBufferCreate(
|
||||
NULL, i420Buffer.width, i420Buffer.height, pixelFormat, NULL, &scaledPixelBuffer);
|
||||
[self cropAndScaleTo:scaledPixelBuffer withTempBuffer:NULL];
|
||||
|
||||
CVPixelBufferLockBaseAddress(scaledPixelBuffer, kCVPixelBufferLock_ReadOnly);
|
||||
sourcePixelBuffer = scaledPixelBuffer;
|
||||
} else {
|
||||
sourcePixelBuffer = _pixelBuffer;
|
||||
}
|
||||
const uint8_t* src = static_cast<uint8_t*>(CVPixelBufferGetBaseAddress(sourcePixelBuffer));
|
||||
const size_t bytesPerRow = CVPixelBufferGetBytesPerRow(sourcePixelBuffer);
|
||||
|
||||
uint32 libyuvPixelFormat = 0;
|
||||
if (pixelFormat == kCVPixelFormatType_32BGRA) {
|
||||
libyuvPixelFormat = libyuv::FOURCC_ARGB;
|
||||
// Corresponds to libyuv::FOURCC_ARGB
|
||||
libyuv::ARGBToI420(src,
|
||||
bytesPerRow,
|
||||
i420Buffer.mutableDataY,
|
||||
i420Buffer.strideY,
|
||||
i420Buffer.mutableDataU,
|
||||
i420Buffer.strideU,
|
||||
i420Buffer.mutableDataV,
|
||||
i420Buffer.strideV,
|
||||
i420Buffer.width,
|
||||
i420Buffer.height);
|
||||
} else if (pixelFormat == kCVPixelFormatType_32ARGB) {
|
||||
libyuvPixelFormat = libyuv::FOURCC_ABGR;
|
||||
// Corresponds to libyuv::FOURCC_BGRA
|
||||
libyuv::BGRAToI420(src,
|
||||
bytesPerRow,
|
||||
i420Buffer.mutableDataY,
|
||||
i420Buffer.strideY,
|
||||
i420Buffer.mutableDataU,
|
||||
i420Buffer.strideU,
|
||||
i420Buffer.mutableDataV,
|
||||
i420Buffer.strideV,
|
||||
i420Buffer.width,
|
||||
i420Buffer.height);
|
||||
}
|
||||
|
||||
libyuv::ConvertToI420(src,
|
||||
0,
|
||||
i420Buffer.mutableDataY,
|
||||
i420Buffer.strideY,
|
||||
i420Buffer.mutableDataU,
|
||||
i420Buffer.strideU,
|
||||
i420Buffer.mutableDataV,
|
||||
i420Buffer.strideV,
|
||||
_cropX,
|
||||
_cropY,
|
||||
_cropWidth,
|
||||
_cropHeight,
|
||||
i420Buffer.width,
|
||||
i420Buffer.height,
|
||||
libyuv::kRotate0,
|
||||
libyuvPixelFormat);
|
||||
if (scaledPixelBuffer) {
|
||||
CVPixelBufferUnlockBaseAddress(scaledPixelBuffer, kCVPixelBufferLock_ReadOnly);
|
||||
CVBufferRelease(scaledPixelBuffer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: { RTC_NOTREACHED() << "Unsupported pixel format."; }
|
||||
@ -226,11 +261,9 @@
|
||||
|
||||
// Prepare source pointers.
|
||||
CVPixelBufferLockBaseAddress(_pixelBuffer, kCVPixelBufferLock_ReadOnly);
|
||||
const uint8_t* srcY =
|
||||
static_cast<const uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(_pixelBuffer, 0));
|
||||
const uint8_t* srcY = static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(_pixelBuffer, 0));
|
||||
const int srcYStride = CVPixelBufferGetBytesPerRowOfPlane(_pixelBuffer, 0);
|
||||
const uint8_t* srcUV =
|
||||
static_cast<const uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(_pixelBuffer, 1));
|
||||
const uint8_t* srcUV = static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(_pixelBuffer, 1));
|
||||
const int srcUVStride = CVPixelBufferGetBytesPerRowOfPlane(_pixelBuffer, 1);
|
||||
|
||||
// Crop just by modifying pointers.
|
||||
@ -264,13 +297,12 @@
|
||||
const int dstWidth = CVPixelBufferGetWidth(outputPixelBuffer);
|
||||
const int dstHeight = CVPixelBufferGetHeight(outputPixelBuffer);
|
||||
|
||||
uint8_t* dst =
|
||||
reinterpret_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(outputPixelBuffer, 0));
|
||||
const int dstStride = CVPixelBufferGetBytesPerRowOfPlane(outputPixelBuffer, 0);
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>(CVPixelBufferGetBaseAddress(outputPixelBuffer));
|
||||
const int dstStride = CVPixelBufferGetBytesPerRow(outputPixelBuffer);
|
||||
|
||||
// Prepare source pointers.
|
||||
CVPixelBufferLockBaseAddress(_pixelBuffer, kCVPixelBufferLock_ReadOnly);
|
||||
const uint8_t* src = static_cast<const uint8_t*>(CVPixelBufferGetBaseAddress(_pixelBuffer));
|
||||
const uint8_t* src = static_cast<uint8_t*>(CVPixelBufferGetBaseAddress(_pixelBuffer));
|
||||
const int srcStride = CVPixelBufferGetBytesPerRow(_pixelBuffer);
|
||||
|
||||
// Crop just by modifying pointers.
|
||||
|
||||
@ -89,6 +89,10 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (rtc::scoped_refptr<webrtc::I420BufferInterface>)nativeI420Buffer {
|
||||
return _i420Buffer;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RTCMutableI420Buffer
|
||||
|
||||
Reference in New Issue
Block a user