OpenGL для видео на iPhone - PullRequest
       30

OpenGL для видео на iPhone

10 голосов
/ 27 января 2011

В настоящее время я работаю над проектом по преобразованию физического моделирования в видео на самом iPhone.

Для этого я сейчас использую два разных цикла. Первый цикл выполняется в блоке, где объект AVAssetWriterInput опрашивает EAGLView для получения дополнительных изображений. EAGLView предоставляет изображения из массива, в котором они хранятся.

Другой цикл - это фактическое моделирование. Я выключил таймер симуляции и каждый раз вызываю тик с заранее заданной разницей во времени. Каждый раз, когда вызывается тик, я создаю новое изображение в методе буферов подкачки EAGLView после замены буферов. Это изображение затем помещается в массив, который опрашивает AVAssetWriter.

Существует также несколько разных кодов, чтобы убедиться, что массив не становится слишком большим

Все это прекрасно работает, но очень и очень медленно.

Есть ли что-то, что я делаю, концептуально, заставляя весь процесс быть медленнее, чем мог бы быть? Кроме того, кто-нибудь знает более быстрый способ получить изображение из Open GL, чем glReadPixels?

Ответы [ 4 ]

3 голосов
/ 05 февраля 2011

Видеопамять спроектирована так, что она быстрая для записи и медленная для чтения.Вот почему я выполняю рендеринг в текстуру.Вот весь метод, который я создал для рендеринга сцены в текстуру (есть несколько пользовательских контейнеров, но я думаю, что довольно просто заменить их собственными):

-(TextureInf*) makeSceneSnapshot {
    // create texture frame buffer
    GLuint textureFrameBuffer, sceneRenderTexture;

    glGenFramebuffersOES(1, &textureFrameBuffer);
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer);

    // create texture to render scene to
    glGenTextures(1, &sceneRenderTexture);
    glBindTexture(GL_TEXTURE_2D, sceneRenderTexture);

    // create TextureInf object
    TextureInf* new_texture = new TextureInf();
    new_texture->setTextureID(sceneRenderTexture);
    new_texture->real_width = [self viewportWidth];
    new_texture->real_height = [self viewportHeight];

    //make sure the texture dimensions are power of 2
    new_texture->width = cast_to_power(new_texture->real_width, 2);
    new_texture->height = cast_to_power(new_texture->real_height, 2);

    //AABB2 = axis aligned bounding box (2D)
    AABB2 tex_box;

    tex_box.p1.x = 1 - (GLfloat)new_texture->real_width / (GLfloat)new_texture->width;
    tex_box.p1.y = 0;
    tex_box.p2.x = 1;
    tex_box.p2.y = (GLfloat)new_texture->real_height / (GLfloat)new_texture->height;
    new_texture->setTextureBox(tex_box);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,  new_texture->width, new_texture->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, sceneRenderTexture, 0);

    // check for completness
    if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
        new_texture->release();
        @throw [NSException exceptionWithName: EXCEPTION_NAME
                                       reason: [NSString stringWithFormat: @"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)]
                                     userInfo: nil];
        new_texture = nil;
    } else {
        // render to texture
        [self renderOneFrame];
    }

    glDeleteFramebuffersOES(1, &textureFrameBuffer);

    //restore default frame and render buffers
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, _defaultFramebuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, _colorRenderbuffer);
    glEnable(GL_BLEND);         
    [self updateViewport];      
    glMatrixMode(GL_MODELVIEW);


    return new_texture;
}

Конечно, есливы делаете снимки все время, тогда вам лучше создать текстурный фрейм и визуализировать буферы только один раз (и выделить для них память).

1 голос
/ 02 марта 2011

Вы можете попробовать использовать объект CADisplayLink, чтобы убедиться, что ваша скорость рисования и скорость захвата соответствуют частоте обновления экрана устройства. Возможно, вы замедляете время выполнения цикла выполнения, обновляя и фиксируя слишком много раз за обновление экрана устройства.

В зависимости от целей вашего приложения, вам может не потребоваться захватывать каждый представленный кадр, поэтому в своем селекторе вы можете выбрать, захватывать текущий кадр или нет.

1 голос
/ 05 февраля 2011

Следует помнить, что графический процессор работает асинхронно с процессором, поэтому, если вы попытаетесь выполнить glReadPixels сразу после завершения рендеринга, вам придется подождать, пока команды будут сброшены в графический процессор и обработаны, прежде чемпрочитайте их обратно.

Вместо того, чтобы ждать синхронно, визуализируйте снимки в очередь текстур (используя FBO, как упоминал Макс).Подождите, пока вы не отрендерите еще пару кадров, прежде чем снимать один из предыдущих кадров.Я не знаю, поддерживает ли iPhone заборы или синхронизирует объекты, но если это так, вы можете проверить их, чтобы увидеть, завершился ли рендеринг перед чтением пикселей.

0 голосов
/ 06 февраля 2013

Хотя вопрос не новый, на него еще не ответили, поэтому я подумал, что я смогу ответить.

glReadPixels действительно очень медленный, и поэтому его нельзя использовать для записи видео из OpenGL-приложения безЭто негативно влияет на производительность.

Мы нашли обходной путь и создали бесплатный SDK под названием Everyplay, который может записывать графику на основе OpenGL в видеофайл без потери производительности.Вы можете проверить это в https://developers.everyplay.com/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...