【问题标题】:What are these extra bytes coming from the iPhone camera in portrait mode?来自 iPhone 相机纵向模式的这些额外字节是什么?
【发布时间】:2015-02-12 01:37:15
【问题描述】:

当我从- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 获得一帧时,我将返回以下数据:

  • BytesPerRow:1,472 长度:706,560 高度:480 宽度:360 格式: BGRA

这是来自 iPhone 6 plus 的前置摄像头。 这没有意义,因为每行的字节数应该是(宽度 * 通道)(在这种情况下,通道是 4)。但是,它是 (width+8)*channels。这额外的 8 个字节是从哪里来的?

这是我的代码: 将输出附加到会话中,我将方向设置为纵向

bool attachOutputToSession(AVCaptureSession *session, id cameraDelegate)
{
    assert(cameraDelegate);

    AVCaptureVideoDataOutput *m_videoOutput = [[AVCaptureVideoDataOutput alloc] init];

    //create a queue for capturing frames
    dispatch_queue_t captureQueue  = dispatch_queue_create("captureQueue", DISPATCH_QUEUE_SERIAL);

    //Use the AVCaptureVideoDataOutputSampleBufferDelegate capabilities of CameraDelegate:
    [m_videoOutput setSampleBufferDelegate:cameraDelegate queue:captureQueue];

    //setup the video outputs
    m_videoOutput.alwaysDiscardsLateVideoFrames = YES;

    NSNumber *framePixelFormat = [NSNumber numberWithInt:kCVPixelFormatType_32BGRA];//This crashes with 24RGB b/c that isn't supported on iPhone
    m_videoOutput.videoSettings = [ NSDictionary dictionaryWithObject:framePixelFormat forKey:(id)kCVPixelBufferPixelFormatTypeKey];

    //Check if it already has an output from a previous session
    if ([session canAddOutput:m_videoOutput])
    {
        [session addOutput:m_videoOutput];
    }

    //set connection settings
    for (AVCaptureConnection *connection in m_videoOutput.connections)
    {
        if (connection.isVideoMirroringSupported)
            connection.videoMirrored = true;
        if (connection.isVideoOrientationSupported)
            connection.videoOrientation = AVCaptureVideoOrientationPortrait; 
    }

    return true;
}

当我将方向设置为 LandscapeRight 时,我没有这个问题。每行的字节数等于 width*channels。

这是我得到上述数字的地方:

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);

    CIImage *ciImage = [CIImage imageWithCVPixelBuffer:imageBuffer];

    CVPixelBufferLockBaseAddress(imageBuffer,0);
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
    size_t width = CVPixelBufferGetWidth(imageBuffer);
    size_t height = CVPixelBufferGetHeight(imageBuffer);
}

【问题讨论】:

    标签: iphone ios8 avfoundation avcapturesession


    【解决方案1】:

    好的,事实证明这是图像“步幅”的一部分。如果图像宽度不能被所选内存分配整除,则包括此额外填充。当我收到肖像图像时,它是 360x480。由于 360 不能被 16 整除,因此添加了 8 个额外字节作为填充。在这种情况下,16 是内存空间。 我之前没有遇到过这个问题,因为 480 可以被 16 整除。 您可以拨打CVPixelBufferGetBytesPerRowOfPlane (imageBuffer, 1);获取此号码 但奇怪的是,它第一次返回 0,第二次返回 1,依此类推,直到达到真正的缓冲区级别 (8)。然后它在第九张图像上再次返回 0。

    根据此页面上的 rpappalax http://gstreamer-devel.966125.n4.nabble.com/iOS-capture-problem-td4656685.html

    步幅实际上是 CVPixelBufferGetBytesPerRowOfPlane() 和 包括填充(如果有)。当没有填充时 CVPixelBufferGetBytesPerRowOfPlane() 将等于 CVPixelBufferGetWidth(),否则会更大。

    虽然那不完全是我的经验。

    【讨论】:

    • 32BRGA 是单平面格式,所以没有理由乱用 CVPixelBufferGetBytesPerRowOfPlane。只需使用 CVPixelBufferGetBytesPerRow 即可。
    • 你说得对,这很好用。然而,我正在处理一个只占用字节、宽度、高度和总大小的图像结构。所以对我来说,弄清楚如何仅根据我后来拥有的数据来计算这一点很重要。
    猜你喜欢
    • 2018-07-20
    • 2021-12-07
    • 2012-07-22
    • 2013-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-17
    • 1970-01-01
    相关资源
    最近更新 更多