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