5

AVFrameをopenglテクスチャに変換するにはどうすればよいですか。実際、オーディオ(オーディオは機能しています)とビデオを出力するレンダラーを作成しましたが、ビデオは出力されません。これが私のコードです:

テクスチャの作成:

glGenTextures(1,&_texture);
glBindTexture(GL_TEXTURE_2D,_texture);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

コード情報:_texture変数は、テクスチャIDを保持するGLuintです

AVFrameを取得してOpenGLテクスチャに変換する関数:

int VideoGL::NextVideoFrame(){
// Get a packet from the queue
AVPacket *videopacket = this->DEQUEUE(VIDEO);
int frameFinished;
if(videopacket!=0){
    avcodec_decode_video2(_codec_context_video, _std_frame,&frameFinished,videopacket);

    if(frameFinished){

        sws_scale(sws_ctx, _std_frame->data, _std_frame->linesize, 0, _codec_context_video->height, _rgb_frame->data, _rgb_frame->linesize);

        if(_firstrendering){
        glBindTexture(GL_TEXTURE_2D,_texture);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _codec_context_video->width,_codec_context_video->height,0,GL_RGB,GL_UNSIGNED_BYTE,_rgb_frame->data[0]);

        _firstrendering = false;

        }else{

            glActiveTexture(_texture);
            glBindTexture(GL_TEXTURE_2D,_texture);
            glTexSubImage2D(GL_TEXTURE_2D,0,0,0,_codec_context_video->width,_codec_context_video->height,GL_RGB,GL_UNSIGNED_BYTE,_rgb_frame->data[0]);

        }
        av_free_packet(videopacket);
        return 0;
    }else{

        av_free_packet(videopacket);
        return -1;
    }

}else{
    return -1;
}
return 0;
}

コード情報:スレッドがAVFrameを格納するキューがあります。この関数は、AVFrameを取得するために頻繁に呼び出され、NULLを取得するまで呼び出されなくなります。

それは実際には機能していません。(私はスタックオーバーフローのいくつかの質問を調べようとしましたが、それはまだ機能していません)何か例、またはそこでのエラーを修正するのを手伝ってくれる人はいますか?

追加データ: GL_RGBをGL_RGBAに変更してフォーマットを試してみましたが、GL_RGBAを試してみるとクラッシュします(幅と高さが非常に大きいため、とにかくサイズを変更しようとしました)。サイズをPowerOf2に変更しようとしましたが、まだ機能しません。

1編集:

スレッド関数:

DWORD WINAPI VideoGL::VidThread(LPVOID myparam){

VideoGL * instance = (VideoGL*) myparam;
instance->wave_audio->Start();

int quantity=0;

AVPacket packet;
while(av_read_frame(instance->_format_context,&packet) >= 0){
    if(packet.stream_index==instance->videoStream){
        instance->ENQUEUE(VIDEO,&packet);
    }
    if(packet.stream_index==instance->audioStream){
        instance->ENQUEUE(AUDIO,&packet);
    }
}

instance->ENQUEUE(AUDIO,NULL);
instance->ENQUEUE(VIDEO,NULL);

return 0;
}

スレッド作成機能:

CreateThread(NULL, 0, VidThread, this, NULL, NULL);

これは、NextVideoFrameを含むクラスと_textureメンバーを指します。

解決済み:

私はdatenwolfのヒントのいくつかに従いました、そして今ビデオはオーディオ/ビデオで正しく表示されています:

スクリーンショットを撮りました

4

1 に答える 1

6

マルチスレッドを使用した OpenGL は少し扱いに​​くいものです。スレッドごとにアクティブな OpenGL コンテキストは 1 つしかないか、まったく存在せず、特定の OpenGL コンテキストは一度に 1 つのスレッドでのみアクティブにできます。スレッド間でコンテキストを移行することは可能ですが、スレッド間でホットな OpenGL-context-potato をプレイしないでください。

次の 2 つの方法があります。

  • メモリ マップされた Pixel Buffer オブジェクトを使用する (一方のスレッドでマップし、もう一方のスレッドで更新する)

  • セカンダリ OpenGL コンテキストを使用して、そのテクスチャを他のコンテキストと共有します。次に、1 つのコンテキストを各スレッドにバインドします (Windows では同じドローアブル、つまり HDC を使用できます)。次に、一方のスレッドでテクスチャを更新しながら、もう一方のスレッドでテクスチャを描画できます。テクスチャの更新により、スレッド間に同期ポイントが導入されるため、描画のためにテクスチャにアクセスしているときに誤ってテクスチャに書き込むことはありません。

于 2013-02-11T22:41:09.420 に答える