Я пытаюсь визуализировать полученные кадры и преобразовать их из видео с помощью 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
.
Здесь вот как выглядит фрейм:
ИЗМЕНИТЬ СНОВА
Только что понял, что я не показал код для настройки 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] изображение немного лучше, но похоже, что у меня все еще отсутствуют линии, и оно все еще немного растянуто:
Другое редактирование
После того, как я последовал совету Макке и передал фактическое разрешение в OpenGL, я получил почти правильные кадры, но все еще немного искаженные и в черно-белом режиме теперь только 6 кадров в секунду, а не 110 кадров в секунду:
PS
У меня есть функция для сохранения е кадры в изображение после sws_scale ()
, и они выходят нормально, как цвет и все такое, так что что-то в OGL делает его черно-белым.
ПОСЛЕДНЕЕ РЕДАКТИРОВАНИЕ
Работает! Хорошо, теперь он работает, в основном я не увеличиваю текстуру до степени 2, а просто использую разрешение видео.
Я получил текстуру, отображающуюся правильно, с удачным предположением о правильном glPixelStorei ()
glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
Кроме того, если у кого-то еще есть субизображение ()
, показывающее пустую проблему, как у меня, вы должны заполнить текстуру хотя бы один раз с помощью glTexImage2D ()
, поэтому я использую его один раз в цикл, а затем используйте glTexSubImage2D ()
после этого.
Спасибо Macke и datenwolf за вашу помощь.