AVCaptureVideoDataOutput video range value exceed the range

CVPixelBuffer.h defines

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

kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange = 'x420', /* 2 plane YCbCr10 4:2:0, each 10 bits in the MSBs of 16bits, video-range (luma=[64,940] chroma=[64,960]) */

But when I set above format camera output, and I find the output pixelbuffer's value is exceed the range.I can see [0 -255] for 420YpCbCr8BiPlanarVideoRange and [0,1023] for 420YpCbCr10BiPlanarVideoRange

Is it a bug or something wrong of the output?If it is not how can I choose the correct matrix transfer the yuv data to rgb?

Replies

Yes, I found so.

iphone XR , ios 17.3.1

For '420v' (video range), Cb, Cr is inside [16, 240], but Y is outside range [16, 235], e.g 240, 255

that will make after convert to rbg, rgb may be nagative number , and then convert back to yuv, yuv is different from origin yuv (the maxium difference will be 20)


....
    NSDictionary* options = @{
        (__bridge NSString*)kCVPixelBufferPixelFormatTypeKey :  @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange),
        //(__bridge NSString*)kCVPixelBufferMetalCompatibilityKey : @(YES),
    };
    [_videoDataOutput setVideoSettings:options];

 ..... 

- (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); // 768 -- 64字节对齐
        int uv_stride = (int)CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1); // 768
         
        // 检查-y平面
        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) {
                    if (nv12pixel < 10 || nv12pixel > 250) {
                        NSLog(@"%s: y panel out of range, coord (x:%d, y:%d), h-coord (x:%d, y:%d) ; nv12 %u "
                              ,__FUNCTION__
                              ,j ,i  // 注意这里 先'列x'后‘行y’
                              ,j/2, i/2
                              ,nv12pixel );
                    }
                }
            }
        } 
      CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly);}