ffmpeg video to opengl texture

Я пытаюсь визуализировать полученные кадры и преобразовать их из видео с помощью ffmpeg в текстуру OpenGL, которая будет помещена на квад . Я довольно сильно вымотал Google и не нашел ответа, ну, я нашел ответы, но ни один из них, похоже, не сработал.

В основном,Я использую avcodec_decode_video2 () для декодирования кадра, затем sws_scale () для преобразования кадра в RGB и затем glTexSubImage2D () для создания текстуры openGL из это, но кажется, что ничего не работает.

Я убедился, что "целевой" AVFrame имеет мощность двух измерений в настройке контекста SWS. Вот мой код:

SwsContext *img_convert_ctx = sws_getContext(pCodecCtx->width,
                pCodecCtx->height, pCodecCtx->pix_fmt, 512,
                256, PIX_FMT_RGB24, SWS_BICUBIC, NULL,
                NULL, NULL);

//While still frames to read
while(av_read_frame(pFormatCtx, &packet)>=0) {
    glClear(GL_COLOR_BUFFER_BIT);

    //If the packet is from the video stream
    if(packet.stream_index == videoStream) {
        //Decode the video
        avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);

        //If we got a frame then convert it and put it into RGB buffer
        if(frameFinished) {
            printf("frame finished: %i\n", number);
            sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);

            glBindTexture(GL_TEXTURE_2D, texture);
            //gluBuild2DMipmaps(GL_TEXTURE_2D, 3, pCodecCtx->width, pCodecCtx->height, GL_RGB, GL_UNSIGNED_INT, pFrameRGB->data);
            glTexSubImage2D(GL_TEXTURE_2D, 0, 0,0, 512, 256, GL_RGB, GL_UNSIGNED_BYTE, pFrameRGB->data[0]);
            SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, number);
            number++;
        }
    }

    glColor3f(1,1,1);
    glBindTexture(GL_TEXTURE_2D, texture);
    glBegin(GL_QUADS);
        glTexCoord2f(0,1);
        glVertex3f(0,0,0);

        glTexCoord2f(1,1);
        glVertex3f(pCodecCtx->width,0,0);

        glTexCoord2f(1,0);
        glVertex3f(pCodecCtx->width, pCodecCtx->height,0);

        glTexCoord2f(0,0);
        glVertex3f(0,pCodecCtx->height,0);

    glEnd();

Как вы можете видеть в этом коде, я также сохраняю кадры в файлы .ppm, просто чтобы убедиться, что они действительно отрисовываются, что они и есть.

Используемый файл - это .wmv на 854x480, может в этом проблема? То, что я просто говорю, чтобы было 512x256?

P.S. Я просмотрел этот вопрос о переполнении стека , но это не помогло.

Кроме того, у меня есть glEnable (GL_TEXTURE_2D) , и я протестировал его, просто загрузив нормальный bmp.

РЕДАКТИРОВАТЬ

Я получаю изображение на экране сейчас, но это искаженный беспорядок, я предполагаю, что что-то связано с изменением значений до степени 2 (в декодировании, swscontext и gluBuild2DMipmaps , как показано в моем коде). Обычно у меня почти такой же код, как показано выше, только я изменил glTexSubImage2D на gluBuild2DMipmaps и изменил типы на GL_RGBA .

Здесь вот как выглядит фрейм:

Ffmpeg as OpenGL Texture garbled

ИЗМЕНИТЬ СНОВА

Только что понял, что я не показал код для настройки pFrameRGB:

//Allocate video frame for 24bit RGB that we convert to.
AVFrame *pFrameRGB;
pFrameRGB = avcodec_alloc_frame();

if(pFrameRGB == NULL) {
    return -1;
}

//Allocate memory for the raw data we get when converting.
uint8_t *buffer;
int numBytes;
numBytes = avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
buffer = (uint8_t *) av_malloc(numBytes*sizeof(uint8_t));

//Associate frame with our buffer
avpicture_fill((AVPicture *) pFrameRGB, buffer, PIX_FMT_RGB24,
    pCodecCtx->width, pCodecCtx->height);

Теперь, когда я изменил PixelFormat в ] avgpicture_get_size на PIX_FMT_RGB24 , я сделал то же самое в SwsContext и изменил GluBuild2DMipmaps на [11103102] I109102] изображение немного лучше, но похоже, что у меня все еще отсутствуют линии, и оно все еще немного растянуто:

Ffmpeg Garbled OpenGL Texture 2

Другое редактирование

После того, как я последовал совету Макке и передал фактическое разрешение в OpenGL, я получил почти правильные кадры, но все еще немного искаженные и в черно-белом режиме теперь только 6 кадров в секунду, а не 110 кадров в секунду:

enter image description here

PS

У меня есть функция для сохранения е кадры в изображение после sws_scale () , и они выходят нормально, как цвет и все такое, так что что-то в OGL делает его черно-белым.

ПОСЛЕДНЕЕ РЕДАКТИРОВАНИЕ

Работает! Хорошо, теперь он работает, в основном я не увеличиваю текстуру до степени 2, а просто использую разрешение видео.

Я получил текстуру, отображающуюся правильно, с удачным предположением о правильном glPixelStorei ()

glPixelStorei(GL_UNPACK_ALIGNMENT, 2);

Кроме того, если у кого-то еще есть субизображение () , показывающее пустую проблему, как у меня, вы должны заполнить текстуру хотя бы один раз с помощью glTexImage2D () , поэтому я использую его один раз в цикл, а затем используйте glTexSubImage2D () после этого.

Спасибо Macke и datenwolf за вашу помощь.

40
задан Community 23 May 2017 в 11:47
поделиться