video作为OpenGLES2.0中的纹理

我想将video作为纹理放置在OpenGLES 2.0 iOS中。 我用AVPlayerItemVideoOutput创buildAVPlayerItemVideoOutput ,设置

 NSDictionary *videoOutputOptions = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:kCVPixelFormatType_32BGRA], kCVPixelBufferPixelFormatTypeKey, [NSDictionary dictionary], kCVPixelBufferIOSurfacePropertiesKey, nil]; self.videoOutput = [[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes:videoOutputOptions]; 

比我获得每个时刻的CVPixelBufferRef

 CMTime currentTime = [self.videoOutput itemTimeForHostTime:CACurrentMediaTime()]; CVPixelBufferRef buffer = [self.videoOutput copyPixelBufferForItemTime:currentTime itemTimeForDisplay:NULL]; 

然后我把它转换成UIImage这种方法

 + (UIImage *)imageWithCVPixelBufferUsingUIGraphicsContext:(CVPixelBufferRef)pixelBuffer { CVPixelBufferLockBaseAddress(pixelBuffer, 0); int w = CVPixelBufferGetWidth(pixelBuffer); int h = CVPixelBufferGetHeight(pixelBuffer); int r = CVPixelBufferGetBytesPerRow(pixelBuffer); int bytesPerPixel = r/w; unsigned char *bufferU = CVPixelBufferGetBaseAddress(pixelBuffer); UIGraphicsBeginImageContext(CGSizeMake(w, h)); CGContextRef c = UIGraphicsGetCurrentContext(); unsigned char* data = CGBitmapContextGetData(c); if (data) { int maxY = h; for(int y = 0; y < maxY; y++) { for(int x = 0; x < w; x++) { int offset = bytesPerPixel*((w*y)+x); data[offset] = bufferU[offset]; // R data[offset+1] = bufferU[offset+1]; // G data[offset+2] = bufferU[offset+2]; // B data[offset+3] = bufferU[offset+3]; // A } } } UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); CVPixelBufferUnlockBaseAddress(pixelBuffer, 0); CFRelease(pixelBuffer); return image; } 

因此,我从video中获得了所需的帧:

在这里输入图像说明

毕竟我尝试更新纹理

 - (void)setupTextureWithImage:(UIImage *)image { if (_texture.name) { GLuint textureName = _texture.name; glDeleteTextures(1, &textureName); } NSError *error; _texture = [GLKTextureLoader textureWithCGImage:image.CGImage options:nil error:&error]; if (error) { NSLog(@"Error during loading texture: %@", error); } } 

我在GLKView的update方法中调用这个方法,但结果是黑屏,只有audio可用。

任何人都可以解释什么做错了? 看起来我正在做一些错误的纹理…

这个问题很可能在其他地方,那么你发布的代码。 检查纹理本身创build一个快照(Xcode中的一个function),看看你是否能看到正确的纹理。 也许你的坐标是不正确的,或者在显示带纹理的对象时缺less一些参数,可能是你忘了启用一些属性或着色器不存在…

既然你到目前为止我build议你先画一个彩色正方形,然后尝试应用纹理(不是从video)到它,直到你得到正确的结果。 然后从video实现纹理。

只是一个build议,因为你从video中获得原始像素数据,你应该考虑只创build一个纹理,然后使用纹理子图像函数直接用数据更新纹理,而不是做一些奇怪的迭代和转换到图像。 glTexSubImage2D将直接取得你的缓冲区指针并进行更新。

我尝试在设备上启动 – 而且工作正常。

看起来像那个问题是模拟器不支持一些操作