FFmpeg5.0のソースコード読み込み - AVFrame

  概要: AVFrameFFmpeg における生データを表す構造体であり、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また、AVFrame1 つのフレームには 1 つのフレームの画像または 1 つの音声データしかありません。

2AVFrame

2.1AVFrame構造定義

  AVFrame独自の操作 API のセットがあり、関連する API を通じて作成 ( av_frame_alloc) およびリリース ( ) する必要がありますav_frame_freeAVFrameのメモリは によって管理されているためですAVBufferPoolこれはAVFrame、メモリが参照カウントによって管理され、再利用できることを意味します。さらに、AVFrameabi は安定していないため、sizeof(AVFrame)固定されていないことに注意してください。その後の更新により、AVFrame構造体定義の末尾にメンバーが直接追加され、その値が変更される可能性があります。
  AVFrame( libavutil/avframe.hin) の構造定義はより複雑なので、コードはここには記載されていませんが、すべてのメンバーの意味はコード定義に従って直接説明されています。

  • 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]
    • 音声データ: 音声データもパックとプランナーに分けられます。
      • パックされたデータ、1 つのみ。
      • プランナー データ、スライス数、およびチャネル数がリンクされ、デュアル チャネル データdata[0]data[1]2 つのチャネルのデータが別々に保存されます。
    • 格納するデータが AV_NUM_DATA_POINTERS (8) チャネルを超える場合、追加のデータを に格納する必要がありますextended_data
  • int linesize[AV_NUM_DATA_POINTERS]:linesizedata1 対 1 で対応し、現在のスライス データまたは現在のデータ フレームの 1 行のサイズを格納します。値は通常、パフォーマンスに合わせて調整されます。
    • ビデオ データ: ビデオ データにはlinesize、現在のデータの行あたりのバイト数 (行あたりのバイト数) が格納されます。実際のデータ サイズは、たとえばwidth*linesize[index]576x432 RGBA データlinesize[0]=align(576x4)=2304と YUV420P の場合ですlinesize[0]==width
    • オーディオ データ: 現在のオーディオ部分のデータ サイズを保存します。すべての部分のサイズは同じでlinesize[0]、他のフィールドは空白のままです。
  • uint8_t **extended_dataextended_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_bufAV_NUM_DATA_POINTERS:スライス数を超えるプランナーのオーディオデータについては、データが格納されます. このフィールドは、チャンネル数extended_dataを超える管理に対応します;AV_NUM_DATA_POINTERSextended_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 AVFrameAPI の実装

& は  AVFrame、メモリ関連の操作の読み取りと変更を除いて、関連する API を介して操作する必要があります.対応する API を使用しない場合、メモリがAVBufferRef正しく解放されない可能性があります.

  • AVFrame *av_frame_alloc(void): メモリをクリアし、いくつかのパラメータをデフォルト値に設定するものを作成します. これは単なるアプリケーションであり、内部データはまだ空であるAVFrameことに注意してください. 対応するリリース API は;AVFrameav_frame_free
  • void av_frame_unref(AVFrame *frame):参照カウント -1 内のAVFrameすべてのマネージドメモリ、および対応するリリース、および最終的にすべてのパラメーターを既定値に設定します。AVBufferRefAVBufferRef
  • 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): コピーしますAVFrameav_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): 対応する型のサイドデータを作成して返します。

おすすめ

転載: blog.csdn.net/GrayOnDream/article/details/129035418