AVFrame に 2 つの割り当てがあるように見えることは、あなたを困惑させていると思います。
で行われる 1 つ目はavcodec_alloc_frame()
、汎用フレームとそのメタデータにスペースを割り当てます。この時点では、適切なフレームを保持するために必要なメモリはまだ不明です。
次に、別のソースからそのフレームにデータを取り込みます。次にwidth
、height
と色深度を渡して必要なメモリ量を指定します。
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 が必要) を使用して、ユーザーはデコーダーがデコードするバッファーを決定し、デコーダーはユーザーにデータが不要になったことを通知します。ユーザー アプリはこの時点でメモリを解放/再利用/保持できます。それは適切だと思います。