5

このソースコードを参照しています。ここで提供されるコード スニペットは、コードの行 (114 ~ 138) からのものです。これは ffmpeg ライブラリを使用しています。プログラムで次のコードが必要な理由を誰でも説明できますか?

// Determine required buffer size and allocate buffer
numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,
              pCodecCtx->height);
buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t)); 

ある意味では、次の関数が宛先フレームをバッファに関連付けていることを理解しています。しかし、必要性は何ですか?

avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);  

PS: バッファを削除してプログラムをコンパイルしてみました。コンパイルされました。しかし、次の実行時エラーが表示されます。

[swscaler @ 0xa06d0a0] 不正な dst イメージ ポインター
セグメンテーション エラー (コア ダンプ)

4

3 に答える 3

28

AVFrame に 2 つの割り当てがあるように見えることは、あなたを困惑させていると思います。

で行われる 1 つ目はavcodec_alloc_frame()、汎用フレームとそのメタデータにスペースを割り当てます。この時点では、適切なフレームを保持するために必要なメモリはまだ不明です。

次に、別のソースからそのフレームにデータを取り込みます。次にwidthheightと色深度を渡して必要なメモリ量を指定します。

numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);

この時点で、フレームとそのコンテンツは 2 つの別個のオブジェクト (AVFrame とそのbuffer ) です。これらを次のコードでまとめますが、これは実際には変換ではありません。

avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
pCodecCtx->width, pCodecCtx->height);

上記のコードが行うことは、次のように「伝える」pFrameRGBことです

そうして初めて、 でやりたいことを何でもできるようになりますpFrameRGB。そうしないと、キャンバスのないフレームにペイントしようとすると、ペイントが飛び散り、コア ダンプが発生します。

フレーム (AVFrame) とキャンバス (バッファー) を取得したら、それを使用できます。

// Read frames and save first five frames to disk
i=0;
while(av_read_frame(pFormatCtx, &packet)>=0) {
    // Is this a packet from the video stream?
    if(packet.stream_index==videoStream) {
      // Decode video frame
      avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished,
&packet);

上記のコードは、ビデオ フレームを抽出し、pFrame(ネイティブ形式) にデコードします。pFrameこの段階でディスクに保存できます。は必要ないためbuffer、使用できませんpFrameRGB

代わりに、 を使用してフレームを RGB-24 に変換しsws_scale()ます。

フレームを別の形式に変換するには、ソースを別の宛先にコピーします。これは、宛先フレームがソース フレームに対応できるものよりも大きくなる可能性があることと、一部の変換アルゴリズムが変換されていないソースのより広い領域で動作する必要があるためです。また、ソース フレームはライブラリによって処理されるため、安全に書き込むことができない可能性があります。

更新 (コメント)

data[]pFrame/pFrameRGBの は何を指していますか:最初は何もありません。これらは NULL であるため、初期化されていない AVframe を使用するとコア ダンプが発生します。(空のバッファに収まる画像フォーマットとサイズ情報に加えて)またはデコード関数の1つ(同じことを行います)を使用して、それら(およびlinesize[]その他)を初期化します。avpicture_fill

pFrame がメモリ割り当てを必要としないのはなぜですか: 良い質問です。答えは、使用される関数のプロトタイプとレイアウトにあります。pictureパラメータは次のように記述されています。

デコードされたビデオ フレームが格納される AVFrame。avcodec_alloc_frame を使用して AVFrame を取得します。コーデックは実際の bitmap にメモリを割り当てます。デフォルトの get/release_buffer() を使用すると、デコーダはビットマップを必要に応じて解放/再利用します。オーバーライドされた get/release_buffer() (CODEC_CAP_DR1 が必要) を使用して、ユーザーはデコーダーがデコードするバッファーを決定し、デコーダーはユーザーにデータが不要になったことを通知します。ユーザー アプリはこの時点でメモリを解放/再利用/保持できます。それは適切だと思います。

于 2013-01-03T12:36:39.433 に答える
1

ffmpeg は、フレームのピクセル データを特定の順序でフレーム バッファー内に格納します。ストレージは画像フォーマット (YUV、RGB) によって異なります。

avpicture_fill() => この関数は生のバッファを取り、AVPicture 構造体のさまざまなポインタを設定します。

于 2013-01-03T12:43:21.817 に答える
0

ffmpeg または同様のライブラリは、インプレース バッファー変換を行いません。まず、元のデータを失わないことと、さまざまなバッファでの作業速度についてです。次に、多くの変換を行う場合は、必要なバッファーを事前に割り当てることができます。

于 2013-01-03T12:25:42.230 に答える