ios - Video como textura en OpenGLES2.0
opengl-es textures (2)
Quiero colocar video como textura para objetar en OpenGLES 2.0 iOS. Creo AVPlayer
con AVPlayerItemVideoOutput
, configuración
NSDictionary *videoOutputOptions = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kCVPixelFormatType_32BGRA], kCVPixelBufferPixelFormatTypeKey,
[NSDictionary dictionary], kCVPixelBufferIOSurfacePropertiesKey,
nil];
self.videoOutput = [[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes:videoOutputOptions];
Que obtengo CVPixelBufferRef
para cada momento
CMTime currentTime = [self.videoOutput itemTimeForHostTime:CACurrentMediaTime()];
CVPixelBufferRef buffer = [self.videoOutput copyPixelBufferForItemTime:currentTime itemTimeForDisplay:NULL];
Luego lo convierto en UIImage con este método
+ (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;
}
Como resultado obtuve el fotograma requerido del video:
Después de todo, intento actualizar la textura con
- (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);
}
}
Llamo a este método en el método de update
de GLKView, pero como resultado obtuve una pantalla negra, solo audio disponible.
¿Alguien puede explicar qué hizo mal? Parece que estoy haciendo algo mal con las texturas ...
El problema es más probable en otro lugar que el código que publicaste. Para verificar la textura en sí, cree una instantánea (una característica en Xcode) y vea si puede ver la textura correcta allí. Tal vez sus coordenadas son incorrectas o faltan algunos parámetros cuando se muestra el objeto texturizado, podría ser que olvidó habilitar algunos atributos o que los sombreadores no están presentes ...
Como llegaste tan lejos, te sugiero que primero trates de dibujar un cuadrado de color, luego trata de aplicarle una textura (no del video) hasta que obtengas el resultado correcto. Luego implementa la textura del video.
Y solo una sugerencia, ya que obtiene datos en bruto de píxeles del video, debería considerar crear solo una textura y luego usar la función de textura de subimágenes para actualizar la textura directamente con los datos en lugar de realizar extrañas iteraciones y transformaciones en la imagen. El glTexSubImage2D
tomará su puntero de buffer directamente y hará la actualización.
Intento iniciar en el dispositivo, y funciona bien.
Parece que ese problema es que el simulador no es compatible con algunas operaciones .