2016-08-15 12 views
0

デコードされたffmpegフレームに自分のアルファチャンネルを追加するためのすばらしい方法を探しています。デコードされたffmpegフレームにアルファチャンネルを書き込む

私はRGB情報を持つAVIファイルを持っており、透明アルファチャンネル(グレースケール)を記述した同期ビデオストリームを持っています。 ffmpegを使ってAVIファイルをデコードしている間に、出力フレームをRGBAに変換し、自分自身のアルファ情報を追加したい。最後に、半透明のビデオストリームを取得します。

libswscaleやlibswresampleに最適化された関数はありますか?ピクセルを反復するよりも、このようなことはうまくいくのでしょうか?

基本的に私は、私だけがsws_scale_and_add_alphaような機能を持っていた場合、このような機能を書くことができるようにしたいと思います:

void* FFmpegLib_nextFrame_withAlpha(void* _handle, uint8_t* my_alpha_channel) 
{ 
    FFmpegLibHandle* handle = (FFmpegLibHandle*)_handle; 
    AVPacket  packet; 
    int    frameFinished; 

    while(av_read_frame(handle->pFormatCtx, &packet) >= 0) { 
     // Is this a packet from the video stream? 
     if(packet.stream_index==handle->videoStream) { 
      // Decode video frame 
      avcodec_decode_video2(handle->pCodecCtx, handle->pFrame, &frameFinished, &packet); 
      // Did we get a video frame? 
      if(frameFinished) { 
       sws_scale_and_add_alpha 
       (
        handle->sws_ctx, 
        (uint8_t const * const *)handle->pFrame->data, 
        handle->pFrame->linesize, 
        0, 
        handle->pCodecCtx->height, 
        handle->pFrameARGB->data, 
        handle->pFrameARGB->linesize, 
        my_alpha_channel 
       ); 

       return handle->pFrameARGB->data; 
      } 
     } 
    } 

    return NULL; 
} 

答えて

1

私はこれを行うには、約2の方法を考えました。通常、コマンドラインでアルファチャンネルをマージしたい場合、ffmpegにはalphamergeというフィルタがあります。そして、私はあなたがCで同じことをすることができると確信していますが、プログラムするのが難しいかもしれません(ffmpegソースにビデオフィルタの例があります)。

2番目のコードは、AVFrame構造に対して自分自身をコーディングしているだけです。 AVFrameのdataフィールドにピクセル情報が格納されます。アルファチャンネルをパックする必要があります。

まず通常どおり充填ARGBに圧縮された画像フレームを変換

// pFrameARGB should have been allocated and of pix_fmt `AV_PIX_FMT_ARGB` 
sws_scale(sws_ctx, pFrame->data, pFrame->linesize, 0, height, pFrameARGB->data, pFrameARGB->linesize); 

AVFrame.dataは多次元アレイが異なる平面を含んでなります。ここでは、平面的なARGBイメージではなく、パックされたARGBイメージがあるため、data[0]には必要なすべてのピクセルが含まれています。

// cpp example, easy to convert to pure C 
auto p = pFrameARGB->data[0]; 
for (auto i = 0; i < width * height; i++) { 
    auto num = i * sizeof(uint8_t) * 4; 
    auto div_result = std::div(num, width * sizeof(uint8_t) * 4); 

    auto offset = pFrameARGB->linesize * div_result.quot + div_result.rem; 
    p[offset] = my_alpha_channel[i]; 
} 
+0

ありがとう@halfelf。私はalphamergeの例を見て、c実装に潜入しました。実際には、argb画像ピクセルをループするので、実際には2番目のプログラミングオプションのようです。パフォーマンス上の理由から、同じ時間にアルファチャンネルを変換して追加するsws_scaleの代わりを使うなど、ワンショットでやりたいと思っていました。実際には最後に、OpenGLシェーダのテクスチャとしてrgbとアルファチャンネルを使用していますので、シェーダの中で色と透明度を組み合わせるのが最善の方法です。 –

+0

@Micそれを聞いてよかったです。実際に私は前にCUDAで同様のことをしてきました。私はその性能がOpenGLほど良いと信じています。 – halfelf

関連する問題