1

您是否遇到过相同视频copyPixelBufferForItemTime在 iOS 上不正确的问题?

我有AVPlayerItemVideoOutput,挂合适AVPlayerItem。我调用copyPixelBufferForItemTime、接收CVPixelBufferRef然后从中检索 OpenGL 纹理。

CVPixelBufferRef pb = [_playerVideoOutput copyPixelBufferForItemTime:currentTime itemTimeForDisplay:nil];

对于此示例视频,CVPixelBufferRef 存在错误:

int bpr = (int)CVPixelBufferGetBytesPerRow(pb);
int width_real = (int)CVPixelBufferGetWidth(pb);
int width_working = (int)CVPixelBufferGetBytesPerRow(pb)/4;

Mac 输出
bpr = 2400
width_real = 596
width_working = 600

iOS 输出
bpr = 2432
width_real = 596
width_working = 608

它是如何在 iOS 上呈现的:
在此处输入图像描述

在 Mac 上的渲染方式:
在此处输入图像描述

CVPixelBufferGetPixelFormatTypeBGRA在两个平台上返回。

编辑 在 iOS 上创建纹理时,我通过从像素缓冲区读取数据CVPixelBufferGetBaseAddress 并使用提供的大小CVPixelBufferGetWidth/ CVPixelBufferGetHeight

- (GLuint)createTextureFromMovieFrame:(CVPixelBufferRef)movieFrame
{
    int bufferWidth = (int) CVPixelBufferGetWidth(movieFrame);
    int bufferHeight = (int) CVPixelBufferGetHeight(movieFrame);

    // Upload to texture
    CVPixelBufferLockBaseAddress(movieFrame, 0);

    CVOpenGLTextureRef texture=0;
    GLuint tex = 0;

#if TARGET_OS_IOS==1
    void * data = CVPixelBufferGetBaseAddress(movieFrame);
    CVReturn err = 0;
    tex = algotest::MyGL::createRGBATexture(bufferWidth, bufferHeight, data, algotest::MyGL::KLinear);

#else
    CVReturn err = CVOpenGLTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
                                                          getGlobalTextureCache(), movieFrame, 0, &texture);
#endif

    CVPixelBufferUnlockBaseAddress(movieFrame, 0);

    return tex;
}

所以width_working只是为了调试。由于它 mismatch ,并且两者都没有width_real传递不起作用,我认为这是像素缓冲区的错误。width_workingwidth_real

4

1 回答 1

2

像素缓冲区在 iOS 和 mac 上都有每行填充像素,大概是出于对齐的原因。不同之处在于 macCVOpenGLTextureCacheCreateTextureFromImage函数可以理解这一点,而 iOScreateRGBATexture函数不能,而不是没有 bytes-per-row 参数。

您可以在宽度中包含填充像素,然后将它们裁剪掉:

tex = algotest::MyGL::createRGBATexture(CVPixelBufferGetBytesPerRow(movieFrame)/4, bufferHeight, data, algotest::MyGL::KLinear);

或者您可以使用CVOpenGLESTextureCacheiOS 等效项CVOpenGLTextureCache并替换createRGBATexture()CVOpenGLESTextureCacheCreateTextureFromImage(). 然后你的 mac 和 iOS 代码会相似,iOS 代码甚至可能运行得更快,因为 iOS 上的纹理缓存可以避免纹理数据的冗余复制。

于 2017-05-26T22:36:36.790 回答