1

FFmpeg を使用してビデオから jni の OpenGL ES テクスチャに変換しようとしていますが、得られるのは黒いテクスチャだけです。で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 テクスチャ ID を出力しました。0 です。テクスチャ ID がゼロになる可能性はありますか? コードを変更しましたが、常にゼロです。

Edit2 のTexture表示ですが、めちゃくちゃです。

4

2 に答える 2

2

GLES には慣れていませんが、GL には慣れていません。そこでは、320、240 は 2 の累乗に関して 512,256 と評価されません。それ以外の場合は、texcoords が 0-1 ではなく 0-w/h である texture_rectangle 拡張を使用する必要があります。テクスチャ データのアップロードに関しては、最初に glTexImage(...) を使用する必要があり (データが 0 の場合でも)、次に glTexSubImage で十分です。サイジングなどは 1 番目で初期化され、2 番目は肉を送信するだけだと思います。

ffmpeg の使用に関しては、おそらくバージョンの問題ですが、img_context は sws_getContext に名前が変更され、1 回だけ初期化されます。CPU の使用が問題である場合は、SWS_CUBIC の代わりに SWS_LINEAR を使用します。 GL_RGBA を使用する場合は PIX_FMT_RGBA を使用する必要があります。PIX_FMT_RGB24 は GL_RGB テクスチャ パイピング用です。

アンパックの配置に関するいくつかのコメントを読みましたが、OpenGL/OpenAL メディア ライブラリ (http://code.google.com/p /openmedialibrary)、オーディオ ビットも ffmpeg から OpenAL ローダーに抽出されています (http://code.google.com/p/openalextensions)。いくつかの優れた機能があり、現在、テクスチャ圧縮を使用して、パフォーマンスがさらに向上するかどうかを確認しようとしています. チュートリアルまたは gpl コードを使用する準備ができていると考えてください。

OpenGL/AL 統合への ffmpeg のあいまいな (不足による) アートについての啓発を期待しています。

于 2012-11-09T15:59:37.337 に答える
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.
  */
于 2012-07-26T13:23:40.080 に答える