概要: AVFrame
FFmpeg における生データを表す構造体であり、FFmpeg の最も重要な構造体の 1 つです。この記事では、FFmpeg ソース コードの理解の役割AVFrame
、関連する構造定義、およびいくつかの操作 API の特定の実装に焦点を当てます。
キーワード: AVFrame
,AVFrameSideData
注: この記事を読む前に、YUV420P、RGBA8 などの基本的なビデオ データ形式と、FLTP、S16 などのオーディオ データ形式を理解する必要があります。また、FFmpeg の基本的なデコード プロセスと のAVFrame
簡単な使用法を理解します。
1.AVFrame
はじめに
FFmpegでデコードされた生データがAVFrame
保存されるので、AVFrame
理解の具体的な実装はFFmpegの使用に大いに役立ちます。AVFrame
オーディオデータまたはビデオデータを格納できる複合構造です。ただし、幅と高さ、サンプリング レートなど、オーディオ データとビデオ データのパラメーターに互換性がないため、2 つのパラメーターAVFrame
の定義がファイルに保持されるため、構造が少し肥大化します (オーディオとビデオの両方が含まれます)。ビデオ パラメータの定義)。
FFmpeg がビデオをデコードするとき、最初に decapsulator を介してビデオのカプセル化を解除しAVPacket
、エンコードされたストリーム データを取得してから、ストリーム データをデコーダに送信してデコードし、デコードされた生データを に格納して返しますAVFrame
。また、AVFrame
1 つのフレームには 1 つのフレームの画像または 1 つの音声データしかありません。
2AVFrame
2.1AVFrame
構造定義
AVFrame
独自の操作 API のセットがあり、関連する API を通じて作成 ( av_frame_alloc
) およびリリース ( ) する必要がありますav_frame_free
。AVFrame
のメモリは によって管理されているためですAVBufferPool
。これはAVFrame
、メモリが参照カウントによって管理され、再利用できることを意味します。さらに、AVFrame
abi は安定していないため、sizeof(AVFrame)
固定されていないことに注意してください。その後の更新により、AVFrame
構造体定義の末尾にメンバーが直接追加され、その値が変更される可能性があります。
AVFrame
( libavutil/avframe.h
in) の構造定義はより複雑なので、コードはここには記載されていませんが、すべてのメンバーの意味はコード定義に従って直接説明されています。
uint8_t *data[AV_NUM_DATA_POINTERS]
: オーディオとビデオの生データを格納します。生データの編成は写真ごとに保存されます。- ビデオデータ:
- パックされたデータの場合、rgba などのピースは 1 つしかなく、その他のデータはその中に格納され
data[0]
、その他のポインターはすべて空です。 - プランナーデータの場合は、プランナーの数に応じて格納する必要があり、例えば、YUV420PデータはYチャンネル、Uチャンネル、Vチャンネルにそれぞれ3スライス、NV12データは1スライスの2スライスとなります
data[0]、data[1]、data[2]
。 ; Y のスライスと UV データの 1 つのスライスが、それぞれスライスに格納されますdata[0]和data[1]
。
- パックされたデータの場合、rgba などのピースは 1 つしかなく、その他のデータはその中に格納され
- 音声データ: 音声データもパックとプランナーに分けられます。
- パックされたデータ、1 つのみ。
- プランナー データ、スライス数、およびチャネル数がリンクされ、デュアル チャネル データ
data[0]
とdata[1]
2 つのチャネルのデータが別々に保存されます。
- 格納するデータが AV_NUM_DATA_POINTERS (8) チャネルを超える場合、追加のデータを に格納する必要があります
extended_data
。
- ビデオデータ:
int linesize[AV_NUM_DATA_POINTERS]
:linesize
とdata
1 対 1 で対応し、現在のスライス データまたは現在のデータ フレームの 1 行のサイズを格納します。値は通常、パフォーマンスに合わせて調整されます。- ビデオ データ: ビデオ データには
linesize
、現在のデータの行あたりのバイト数 (行あたりのバイト数) が格納されます。実際のデータ サイズは、たとえばwidth*linesize[index]
576x432 RGBA データlinesize[0]=align(576x4)=2304
と YUV420P の場合ですlinesize[0]==width
。 - オーディオ データ: 現在のオーディオ部分のデータ サイズを保存します。すべての部分のサイズは同じで
linesize[0]
、他のフィールドは空白のままです。
- ビデオ データ: ビデオ データには
uint8_t **extended_data
extended_data
: オーディオ データ、オーディオ データがプランナーであり、チャネル数が 8 を超える場合、冗長データを見つけてすべてのデータを同時に含める必要があります。それ以外の場合、そのポインティング サムはdata
同じです。int width,height
: ビデオ データの幅と高さは、オーディオ データには意味がありません。int nb_samples
: オーディオ データのサンプル数。ビデオ データには意味がありません。int format
: 現在のデータの形式。ビデオの場合AVPixelFormat
、オーディオの場合はAVSampleFormat
;int key_frame
: 現在のフレームがキー フレームかどうか。AVPictureType pict_type
: IBP フレームなど、現在のフレームのタイプ。AVRational sample_aspect_ratio
: SAR、ビデオ フレームのサンプリング比。0/1 は不明を意味します。
ビデオには、DAR、PAR、SAR の 3 つの比率があります。
SAR
: (ストレージ アスペクト比): ローカルに保存されたビデオ フレームのアスペクト比。DAR
: (表示アスペクト比) 実際の表示アスペクト比、DAR=SAR x PAR;PAR
: (Pixel Aspect Ratio) ピクセルの縦横比。一般的に言えば、ピクセルは正方形または 1:1 ですが、絶対的なものではありません。
int64_t pts
: 現在のフレーム単位time_base
で。int64_t dts
: ユニット内の現在のフレームtime_base
の。int64_t pkt_dts
:現在のフレームに対応するAVPacket
ポイント。int coded_picture_number
: コード ストリーム内のフレームのシリアル番号。int display_picture_number
: フレームのシリアル番号を表示します。int quality
: 画質、値[1, FF_LAMBDA_MAX]
;void *opaque
: 内部で透過的に送信されるユーザーのプライベート データ ポインター。int repeat_pict
: デコード中の現在のフレームの余分な遅延時間を示します. 計算方法は、extra_delay=repeat_pict/(2 x fps)
実際のフレーム間隔時間は余分な間隔 + フレームレート間隔です;int interlaced_frame
: 現在のフレーム画像がインターレース サンプリング モードであるかどうか。値は 0/1 です。int top_field_first
: 現在のフレームがインターレース サンプリングの場合、一番上の行を最初に表示するかどうかを示します。int palette_has_changed
: パレットをサポートする形式の場合、パレットが変更されたかどうかを示します。int64_t reordered_opaque
:int sample_rate
: 8000、44100 などのオーディオ サンプリング レート。AVBufferRef buf[AV_NUM_DATA_POINTERS]
:現在のフレームのdata
メモリを管理しますAVBufferRef
。空の場合は、現在のフレームのメモリがこの方法で管理されていないことを意味します。AVBufferRef **extended_buf
AV_NUM_DATA_POINTERS
:スライス数を超えるプランナーのオーディオデータについては、データが格納されます. このフィールドは、チャンネル数extended_data
を超える管理に対応します;AV_NUM_DATA_POINTERS
extended_data
int nb_extended_buf````:
extended_buf 内のフィールド内のアイテムの数;AVFrameSideData **side_data
: 動きベクトルのデコード成功などの追加データがこの項目に格納されます。int nb_side_data
:side_data
項目数;int flags
: 現在のフレームのフラグ ビットは、現在のフレームのステータスを示します。enum AVColorRange color_range;enum AVColorPrimaries color_primaries;enum AVColorTransferCharacteristic color_trc;enum AVColorSpace colorspace;enum AVChromaLocation chroma_location;
: 現在のフレームの色空間に関する情報。int64_t best_effort_timestamp
: ヒューリスティック アルゴリズムによって計算された pts (エンコードは役に立たない、デコード時にデコーダーによって設定されます)int64_t pkt_pos
: デコーダーに送信された最後のフレームのファイル内のオフセット。int64_t pkt_duration
: 現在のフレームの長さ。AVDictionary *metadata
: エンコード時にユーザーが設定し、デコード時に libavcodec によって設定されるメタデータ。int decode_error_flags
: デコードエラー識別子 (FF_DECODE_ERROR_xxx
);int channels
: オーディオ チャネルの数、廃止されました。int pkt_size
: 現在のパケット エンコード データのサイズ。デコードにのみ役立ちます。AVBufferRef *hw_frames_ctx
: ハードウェア アクセラレーションを使用するフレームをデコードするには、対応するAVHWFramesContext
;AVBufferRef *opaque_ref
: ユーザーデータですが、コードを見ると基本的には使用されません。size_t crop_top;size_t crop_bottom;size_t crop_left;size_t crop_right;
: 現在のフレームの長方形の領域。その他は破棄されます。AVBufferRef *private_ref
: 内部で使用されるデータ、外部で使用されるデータは気にしないでください。AVChannelLayout ch_layout
: 現在のオーディオ データの格納形式 (シングル チャネル、デュアル チャネルなど)。古いバージョンの値は int です。
2.2 AVFrame
API の実装
& は AVFrame
、メモリ関連の操作の読み取りと変更を除いて、関連する API を介して操作する必要があります.対応する API を使用しない場合、メモリがAVBufferRef
正しく解放されない可能性があります.
AVFrame *av_frame_alloc(void)
: メモリをクリアし、いくつかのパラメータをデフォルト値に設定するものを作成します. これは単なるアプリケーションであり、内部データはまだ空であるAVFrame
ことに注意してください. 対応するリリース API は;AVFrame
av_frame_free
void av_frame_unref(AVFrame *frame)
:参照カウント -1 内のAVFrame
すべてのマネージドメモリ、および対応するリリース、および最終的にすべてのパラメーターを既定値に設定します。AVBufferRef
AVBufferRef
void av_frame_free(AVFrame **frame)
: 全体を解放しますAVFrame
。int av_frame_get_buffer(AVFrame *frame, int align)
:現在のオーディオおよびビデオ フレームのパラメータに従ってdata
フィールドを埋めます。int av_frame_ref(AVFrame *dst, const AVFrame *src)
:src
内部のデータとパラメータdst
、実際のデータ ポイントを同じものにコピーしますdata
が、AVBufferRef
管理は異なります。AVFrame *av_frame_clone(const AVFrame *src)
: コピーしますAVFrame
。av_frame_ref
違いは、関数内でターゲットを作成することですAVFrame
。void av_frame_move_ref(AVFrame *dst, AVFrame *src)
:移動後はsrc
空白になります。int av_frame_is_writable(AVFrame *frame)
:現在のフレームのextended_buf
合計buf
が書き込み可能かどうかを確認します。int av_frame_make_writable(AVFrame *frame)
: 主にav_frame_get_buffer
メモリー申請による。int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
: パラメータをコピーします。AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane)
: 目的の平面を返しますAVBufferRef
。int av_frame_apply_cropping(AVFrame *frame, int flags)
: 指定されたトリミング パラメータを適用しても、対応するメモリは解放されませんが、データ ポインタと幅と高さが対応する値に設定されます。
3AVFrameSideData
サイドデータは、動きベクトルなど、デコード プロセスの中間データです。
AVFrameSideData
構造は比較的シンプルで、
3.1AVFrameSideData
構造定義
typedef struct AVFrameSideData {
enum AVFrameSideDataType type;
uint8_t *data; //实际的数据域,具体的数据类型和存储方式通过type解析
size_t size; //数据大小
AVDictionary *metadata; //元数据
AVBufferRef *buf;
} AVFrameSideData;
FFmpegが対応しているデータは以下の通りです。
const char *av_frame_side_data_name(enum AVFrameSideDataType type)
{
switch(type) {
case AV_FRAME_DATA_PANSCAN: return "AVPanScan";
case AV_FRAME_DATA_A53_CC: return "ATSC A53 Part 4 Closed Captions";
case AV_FRAME_DATA_STEREO3D: return "Stereo 3D";
case AV_FRAME_DATA_MATRIXENCODING: return "AVMatrixEncoding";
case AV_FRAME_DATA_DOWNMIX_INFO: return "Metadata relevant to a downmix procedure";
case AV_FRAME_DATA_REPLAYGAIN: return "AVReplayGain";
case AV_FRAME_DATA_DISPLAYMATRIX: return "3x3 displaymatrix";
case AV_FRAME_DATA_AFD: return "Active format description";
case AV_FRAME_DATA_MOTION_VECTORS: return "Motion vectors";
case AV_FRAME_DATA_SKIP_SAMPLES: return "Skip samples";
case AV_FRAME_DATA_AUDIO_SERVICE_TYPE: return "Audio service type";
case AV_FRAME_DATA_MASTERING_DISPLAY_METADATA: return "Mastering display metadata";
case AV_FRAME_DATA_CONTENT_LIGHT_LEVEL: return "Content light level metadata";
case AV_FRAME_DATA_GOP_TIMECODE: return "GOP timecode";
case AV_FRAME_DATA_S12M_TIMECODE: return "SMPTE 12-1 timecode";
case AV_FRAME_DATA_SPHERICAL: return "Spherical Mapping";
case AV_FRAME_DATA_ICC_PROFILE: return "ICC profile";
case AV_FRAME_DATA_DYNAMIC_HDR_PLUS: return "HDR Dynamic Metadata SMPTE2094-40 (HDR10+)";
case AV_FRAME_DATA_REGIONS_OF_INTEREST: return "Regions Of Interest";
case AV_FRAME_DATA_VIDEO_ENC_PARAMS: return "Video encoding parameters";
case AV_FRAME_DATA_SEI_UNREGISTERED: return "H.26[45] User Data Unregistered SEI message";
case AV_FRAME_DATA_FILM_GRAIN_PARAMS: return "Film grain parameters";
case AV_FRAME_DATA_DETECTION_BBOXES: return "Bounding boxes for object detection and classification";
}
return NULL;
}
対応するデータをデコードする場合は、デコード関連のパラメーターを設定し、関連する API を使用しAVFrame
てデータを取得します。
av_dict_set(&opts, "flags2", "+export_mvs", 0);
ret = avcodec_open2(dec_ctx, dec, &opts);
while(){
//send_packet
while(){
//receive avframe
sd = av_frame_get_side_data(frame, AV_FRAME_DATA_MOTION_VECTORS);
}
}
たとえば、モーション ベクトル データは次のようになります
。 mv.png)]
3.2AVFrameSideData
関連する API
const char *av_frame_side_data_name(enum AVFrameSideDataType type)
: 対応するタイプのサイドデータの文字列記述を取得します。void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type)
:AVFrame
現在の対応するサイドデータのデータを解放します。AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, enum AVFrameSideDataType type)
: 対応するAVFrame
型。AVFrameSideData *av_frame_new_side_data(AVFrame *frame, enum AVFrameSideDataType type, size_t size)
: 対応する型のサイドデータを作成して返します。