我想在OpenGLES 2.0 iOS中将视频作为纹理放置到对象中。
我使用AVPlayer
创建AVPlayerItemVideoOutput
,设置
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;
}
结果我从视频中得到了所需的帧:
毕竟我尝试用
更新纹理- (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
方法中调用此方法,但结果是黑屏,只有音频可用。
任何人都可以解释做错了吗?看起来我对纹理做错了......
答案 0 :(得分:1)
问题很可能发生在你发布的代码的其他地方。要检查纹理本身,请创建一个快照(Xcode中的一个功能),看看是否可以在那里看到正确的纹理。显示纹理对象时,您的坐标可能不正确或某些参数丢失,可能是您忘记启用某些属性或者着色器不存在...
由于你到目前为止我建议你首先尝试绘制一个彩色方块,然后尝试将纹理(不是从视频)应用到它,直到你得到正确的结果。然后从视频中实现纹理。
只是一个建议,因为你从视频中获取原始像素数据,你应该考虑只创建一个纹理,然后使用纹理子图像函数直接用数据更新纹理,而不是做一些奇怪的迭代和转换到图像。 glTexSubImage2D
将直接获取缓冲区指针并进行更新。
答案 1 :(得分:0)
我尝试在设备上启动 - 它运行正常。
看起来问题是模拟器不支持某些操作。