Platfrom: iphone XR
System: ios 17.3.1
using iphone front camera(normal camera), configure data output format to 'kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange' ('420v' (video range))
I found that Cb, Cr is inside [16, 240], but Y is outside range [16, 235], e.g 240, 255
It will lead that after convert to rbg, rgb may be negative number , and then clamp the r,g,b value between 0 and 255, finally convert clamped rgb back to yuv, yuv is different from origin yuv.
The maxium difference of y channel will be 20.
Both procssing by pure cpu and using metal shader will get this result
CVPixelBuffer.h
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange = '420v', /* Bi-Planar Component Y'CbCr 8-bit 4:2:0, video-range (luma=[16,235] chroma=[16,240]). baseAddr points to a big-endian CVPlanarPixelBufferInfo_YCbCrBiPlanar struct */
// ... some code ...
// config camra data output format
NSDictionary* options = @{
(__bridge NSString*)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange),
//(__bridge NSString*)kCVPixelBufferMetalCompatibilityKey : @(YES),
};
[_videoDataOutput setVideoSettings:options];
// ... some code ...
- (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection;
{
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferRef pixelBuffer = imageBuffer;
CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly);
uint8_t* yBase = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0);
uint8_t* uvBase = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1);
int imageWidth = (int)CVPixelBufferGetWidth(pixelBuffer); // 720
int imageHeight = (int)CVPixelBufferGetHeight(pixelBuffer);// 1280
int y_width = (int)CVPixelBufferGetWidthOfPlane (pixelBuffer, 0); // 720
int y_height = (int)CVPixelBufferGetHeightOfPlane(pixelBuffer, 0); // 1280
int uv_width = (int)CVPixelBufferGetWidthOfPlane (pixelBuffer, 1); // 360
int uv_height = (int)CVPixelBufferGetHeightOfPlane(pixelBuffer, 1); // 640
int y_stride = (int)CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0); int uv_stride = (int)CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1); // 768
// check Y-plane
if (TRUE) {
for(int i = 0 ; i < imageHeight ; i++) {
for(int j = 0; j < imageWidth ; j++) {
uint8_t nv12pixel = *(yBase + y_stride * i + j );
if (nv12pixel < 16 || nv12pixel > 235) { // [16, 235]
NSLog(@"%s: y panel out of range, coord (x:%d, y:%d), h-coord (x:%d, y:%d) ; nv12 %u "
,__FUNCTION__
,j ,i
,j/2, i/2
,nv12pixel );
}
}
}
}
CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly);
}
// ... some code ...
How to deal with this case ?
Hope to get reply, Thanks