Преобразование кадра FFmpeg в текстуру OpenGL ES

1

Я пытаюсь преобразовать из видео с помощью FFmpeg в текстуру OpenGL ES в jni, но все, что я получаю, это черная текстура. Я glGetError() OpenGL с помощью glGetError(), но ошибки не было.

Вот мой код:

void* pixels;
int err;
int i;
int frameFinished = 0;
AVPacket packet;
static struct SwsContext *img_convert_ctx;
static struct SwsContext *scale_context = NULL;
int64_t seek_target;

 int target_width = 320;
 int target_height = 240;
 GLenum error = GL_NO_ERROR;
 sws_freeContext(img_convert_ctx);  

i = 0;
while((i==0) && (av_read_frame(pFormatCtx, &packet)>=0)) {
        if(packet.stream_index==videoStream) {
        avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);

        if(frameFinished) {
            LOGI("packet pts %llu", packet.pts);
            img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, 
                   pCodecCtx->pix_fmt, 
                   target_width, target_height, PIX_FMT_RGB24, SWS_BICUBIC, 
                   NULL, NULL, NULL);
            if(img_convert_ctx == NULL) {
                LOGE("could not initialize conversion context\n");
                return;
            }
                sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
                LOGI("sws_scale");

                videoTextures = new Texture*[1];
                videoTextures[0]->mWidth = 256; //(unsigned)pCodecCtx->width;
                videoTextures[0]->mHeight = 256; //(unsigned)pCodecCtx->height;
                videoTextures[0]->mData = pFrameRGB->data[0];

                glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

                glGenTextures(1, &(videoTextures[0]->mTextureID));
                glBindTexture(GL_TEXTURE_2D, videoTextures[0]->mTextureID);
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

                if(0 == got_texture)
                {
                    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, videoTextures[0]->mWidth, videoTextures[0]->mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)videoTextures[0]->mData);

                    glTexSubImage2D(GL_TEXTURE_2D, 0, 0,0, videoTextures[0]->mWidth, videoTextures[0]->mHeight, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)videoTextures[0]->mData);
                }else
                {
                    glTexSubImage2D(GL_TEXTURE_2D, 0, 0,0, videoTextures[0]->mWidth, videoTextures[0]->mHeight, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)videoTextures[0]->mData);

                }

                i = 1;
                error = glGetError();
                if( error != GL_NO_ERROR ) {
                    LOGE("couldn't create texture!!");
                       switch (error) {
                        case GL_INVALID_ENUM:
                        LOGE("GL Error: Enum argument is out of range");
                        break;
                        case GL_INVALID_VALUE:
                            LOGE("GL Error: Numeric value is out of range");
                        break;
                        case GL_INVALID_OPERATION:
                            LOGE("GL Error: Operation illegal in current state");
                        break;
                        case GL_OUT_OF_MEMORY:
                            LOGE("GL Error: Not enough memory to execute command");
                        break;
                        default:
                            break;
                       }
                }
        }
    }
    av_free_packet(&packet);
}

Мне удалось сменить pFrameRGB на растровое изображение java, но я просто хочу изменить его на текстуру в c-коде.

Edit1 У меня есть Texture ID, это 0; может ли идентификатор текстуры быть нулевым? Я изменил свой код, но он всегда равен нулю.

Edit2 Отображение текстуры, но это беспорядок.

Теги:
ffmpeg
textures

2 ответа

2

Не используется для GLES, но GL. Там 320, 240 не оценены 512256 в отношении мощности 2. Еще вам нужно использовать расширение texture_rectangle, которое texcoords не равно 0-1, но 0-w/h. Что касается загрузки данных текстуры, glTexImage (...) необходимо использовать в первый раз (даже с данными 0), то glTexSubImage достаточно, я думаю, что размер и т.д. Инициализируется первым, а второй просто отправляет мясо.

Что касается использования ffmpeg, возможно, проблема с версией, но img_context больше подходит для переименования в sws_getContext и инициализируется только один раз, если использование cpu является проблемой, используйте SWS_LINEAR вместо SWS_CUBIC, также я предполагаю, что pFrameRGB был правильно avcodec_alloc_frame(), если, если вы собираетесь использовать GL_RGBA, вы должны использовать PIX_FMT_RGBA, PIX_FMT_RGB24 будет для текстурного конвейера GL_RGB, в конце концов вам не хватает пакета пакетов, чтобы вы могли читать заранее, чтобы поддерживать хорошее отображение в синхронизации, а не поздно.

Я прочитал несколько комментариев о выравнивании распаковки, мне не нужно было (и, увидев успех в области сомнения в этом), чтобы реализовать ffmpeg для библиотеки OpenGL/OpenAL (http://code.google.com/p/openmedialibrary), красиво звуковые биты также были извлечены в ffmpeg для загрузчика OpenAL (http://code.google.com/p/openalextensions). Имеет некоторые интересные функции, и в настоящее время я пытаюсь работать с сжатием текстур, чтобы увидеть, может ли он работать еще лучше. Учтите, что учебники или даже готовы использовать код gpl.

Надеюсь дать некоторое просветление на неясном (по причине) искусстве ffmpeg на интеграцию OpenGL/AL.

0

Попробуйте добавить 16 нулевых байтов к каждому пакету перед тем, как перейти к декодеру.

Некоторые комментарии от avcodec.h:

 /*
 * @warning The input buffer must be FF_INPUT_BUFFER_PADDING_SIZE larger than
 * the actual read bytes because some optimized bitstream readers read 32 or 64
 * bits at once and could read over the end.
 * @warning The end of the input buffer buf should be set to 0 to ensure that
 * no overreading happens for damaged MPEG streams.
  */

Ещё вопросы

Сообщество Overcoder
Наверх
Меню