OpenGL ES 2.0 для видео на iPad / iPhone

Я нахожусь в своем уме, несмотря на хорошую информацию здесь, в StackOverflow ...

Я пытаюсь написать рендербуфер OpenGL для видео на iPad 2 (используя iOS 4.3). Это более точно то, что я пытаюсь сделать:

A)настроить AVAssetWriterInputPixelBufferAdaptor

  1. создать AVAssetWriter, который указывает на видеофайл

  2. настроить AVAssetWriterInput с соответствующими настройками

  3. настроить AVAssetWriterInputPixelBufferAdaptor для добавления данных в видеофайл

B) записать данные в видео файл, используя этот AVAssetWriterInputPixelBufferAdaptor

  1. , отображать код OpenGL на экране

  2. получить буфер OpenGL через glReadPixels

  3. создать CVPixelBufferRef из данных OpenGL

  4. добавить этот PixelBuffer к методу AVAssetWriterInputPixel90 с помощью метода appendPixelBuffer,

  5. У меня проблемы с этим. Моя стратегия прямо сейчас - настроить AVAssetWriterInputPixelBufferAdaptor при нажатии кнопки. Как только AVAssetWriterInputPixelBufferAdaptor становится действительным, я устанавливаю флаг, чтобы сигнализировать EAGLView о создании пиксельного буфера и добавлении его в видеофайл через appendPixelBuffer для заданного количества кадров.

    Прямо сейчас мой код дает сбой, когда он пытается добавить второй пиксельный буфер, что дает мне следующую ошибку:

    -[__NSCFDictionary appendPixelBuffer:withPresentationTime:]: unrecognized selector sent to instance 0x131db0
    

    Вот мой код настройки AVAsset (многие из них были основаны на коде Руди Арамайо, который работает с обычными изображениями, но не настроен для текстур ):

    - (void) testVideoWriter {
    
      //initialize global info
      MOVIE_NAME = @"Documents/Movie.mov";
      CGSize size = CGSizeMake(480, 320);
      frameLength = CMTimeMake(1, 5); 
      currentTime = kCMTimeZero;
      currentFrame = 0;
    
      NSString *MOVIE_PATH = [NSHomeDirectory() stringByAppendingPathComponent:MOVIE_NAME];
      NSError *error = nil;
    
      unlink([betaCompressionDirectory UTF8String]);
    
      videoWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:betaCompressionDirectory] fileType:AVFileTypeQuickTimeMovie error:&error];
    
      NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:AVVideoCodecH264, AVVideoCodecKey,
                                     [NSNumber numberWithInt:size.width], AVVideoWidthKey,
                                     [NSNumber numberWithInt:size.height], AVVideoHeightKey, nil];
      writerInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings];
    
      //writerInput.expectsMediaDataInRealTime = NO;
    
      NSDictionary *sourcePixelBufferAttributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:kCVPixelFormatType_32BGRA], kCVPixelBufferPixelFormatTypeKey, nil];
    
      adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput                                                                          sourcePixelBufferAttributes:sourcePixelBufferAttributesDictionary];
      [adaptor retain];
    
      [videoWriter addInput:writerInput];
    
      [videoWriter startWriting];
      [videoWriter startSessionAtSourceTime:kCMTimeZero];
    
      VIDEO_WRITER_IS_READY = true;
    }
    

    Хорошо, теперь, когда мой videoWriter и адаптер настроены, я приказываю своему рендереру OpenGL создавать буфер пикселей для каждого кадра:

    - (void) captureScreenVideo {
    
      if (!writerInput.readyForMoreMediaData) {
        return;
      }
    
      CGSize esize = CGSizeMake(eagl.backingWidth, eagl.backingHeight);
      NSInteger myDataLength = esize.width * esize.height * 4;
      GLuint *buffer = (GLuint *) malloc(myDataLength);
      glReadPixels(0, 0, esize.width, esize.height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
      CVPixelBufferRef pixel_buffer = NULL;
      CVPixelBufferCreateWithBytes (NULL, esize.width, esize.height, kCVPixelFormatType_32BGRA, buffer, 4 * esize.width, NULL, 0, NULL, &pixel_buffer);
    
      /* DON'T FREE THIS BEFORE USING pixel_buffer! */ 
      //free(buffer);
    
      if(![adaptor appendPixelBuffer:pixel_buffer withPresentationTime:currentTime]) {
          NSLog(@"FAIL");
        } else {
          NSLog(@"Success:%d", currentFrame);
          currentTime = CMTimeAdd(currentTime, frameLength);
        }
    
       free(buffer);
       CVPixelBufferRelease(pixel_buffer);
      }
    
    
      currentFrame++;
    
      if (currentFrame > MAX_FRAMES) {
        VIDEO_WRITER_IS_READY = false;
        [writerInput markAsFinished];
        [videoWriter finishWriting];
        [videoWriter release];
    
        [self moveVideoToSavedPhotos]; 
      }
    }
    

    И, наконец, я перемещаю видео в камеру:

    - (void) moveVideoToSavedPhotos {
      ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
      NSString *localVid = [NSHomeDirectory() stringByAppendingPathComponent:MOVIE_NAME];    
      NSURL* fileURL = [NSURL fileURLWithPath:localVid];
    
      [library writeVideoAtPathToSavedPhotosAlbum:fileURL
                                  completionBlock:^(NSURL *assetURL, NSError *error) {
                                    if (error) {   
                                      NSLog(@"%@: Error saving context: %@", [self class], [error localizedDescription]);
                                    }
                                  }];
      [library release];
    }
    

    Однако , как я уже сказал, у меня происходит сбой при вызове appendPixelBuffer.

    Извините за отправку такого количества кода, но я действительно не знаю, что делаю не так. Казалось, что было бы тривиально обновить проект, который записывает изображения в видео, но я не могу взять пиксельный буфер, созданный с помощью glReadPixels, и добавить его. Это сводит меня с ума! Если у кого-нибудь есть совет или рабочий пример кода OpenGL -> Видео, это было бы потрясающе ... Спасибо!

9
задан Angus Forbes 28 June 2011 в 06:00
поделиться