ffmpeg AVFrame結構體及其相關函數


0. 簡介

AVFrame中存儲的是原始數據(例如視頻的YUV, RGB, 音頻的PCM), 此外還包含了一些相關的信息, 例如: 解碼的時候存儲了宏塊類型表, QP表, 運動矢量等數據. 編碼的時候也存儲了相關的數據.

 

1. AVFrame 數據結構定義

FFmpeg 版本3.4.1

struct AVFrame 定義於<libavutil/frame.h>

結構體源碼(我去除了注釋):

  1 typedef struct AVFrame {
  2 #define AV_NUM_DATA_POINTERS 8
  3 
  4     uint8_t *data[AV_NUM_DATA_POINTERS];
  5 
  6     int linesize[AV_NUM_DATA_POINTERS];
  7 
  8     uint8_t **extended_data;
  9 
 10     int width, height;
 11  
 12     int nb_samples;
 13 
 14     int format;
 15 
 16     int key_frame;
 17 
 18     enum AVPictureType pict_type;
 19 
 20     AVRational sample_aspect_ratio;
 21 
 22     int64_t pts;
 23 
 24 #if FF_API_PKT_PTS
 25 
 26     attribute_deprecated
 27     int64_t pkt_pts;
 28 #endif
 29 
 30     int64_t pkt_dts;
 31 
 32     int coded_picture_number;
 33 
 34     int display_picture_number;
 35 
 36     int quality;
 37 
 38     void *opaque;
 39 
 40 #if FF_API_ERROR_FRAME
 41 
 42     attribute_deprecated
 43     uint64_t error[AV_NUM_DATA_POINTERS];
 44 #endif
 45 
 46     int repeat_pict;
 47 
 48     int interlaced_frame;
 49 
 50     int top_field_first;
 51 
 52     int palette_has_changed;
 53 
 54     int64_t reordered_opaque;
 55 
 56     int sample_rate;
 57 
 58     uint64_t channel_layout;
 59 
 60     AVBufferRef *buf[AV_NUM_DATA_POINTERS];
 61 
 62     AVBufferRef **extended_buf;
 63    
 64     int        nb_extended_buf;
 65 
 66     AVFrameSideData **side_data;
 67     int            nb_side_data;
 68 
 69 #define AV_FRAME_FLAG_CORRUPT       (1 << 0)
 70 
 71 #define AV_FRAME_FLAG_DISCARD   (1 << 2)
 72 
 73     int flags;
 74 
 75     enum AVColorRange color_range;
 76 
 77     enum AVColorPrimaries color_primaries;
 78 
 79     enum AVColorTransferCharacteristic color_trc;
 80 
 81     enum AVColorSpace colorspace;
 82 
 83     enum AVChromaLocation chroma_location;
 84 
 85     int64_t best_effort_timestamp;
 86 
 87     int64_t pkt_pos;
 88 
 89     int64_t pkt_duration;
 90 
 91     AVDictionary *metadata;
 92 
 93     int decode_error_flags;
 94 #define FF_DECODE_ERROR_INVALID_BITSTREAM   1
 95 #define FF_DECODE_ERROR_MISSING_REFERENCE   2
 96 
 97     int channels;
 98 
 99     int pkt_size;
100 
101 #if FF_API_FRAME_QP
102     attribute_deprecated
103     int8_t *qscale_table;
104    
105     attribute_deprecated
106     int qstride;
107 
108     attribute_deprecated
109     int qscale_type;
110 
111     AVBufferRef *qp_table_buf;
112 #endif
113 
114     AVBufferRef *hw_frames_ctx;
115 
116     AVBufferRef *opaque_ref;
117 
118     size_t crop_top;
119     size_t crop_bottom;
120     size_t crop_left;
121     size_t crop_right;
122 } AVFrame;
  • 帶有#if ...  #end包含的字段, 都是將要被棄用或已經棄用的. 不再進行解釋.

 

  • 必須使用av_frame_alloc()分配AVFrame, 這只是分配AVFram本身.
  • 必須使用av_frame_free()釋放.

 

  • uint8_t *data[AV_NUM_DATA_POINTERS];

原始數據(對視頻來說是YUB, RGB, 對音頻來說是PCM)

data是一個指針數組, 數組的每一個元素都是一個指針. 指向視頻中圖像的某一plane或者音頻中某一聲道的plane.

對於packed格式, 一個YUV圖像的Y, U, V交織存儲在一個plane中, 例如: YUVYUVYUV... ..., data[0]指向這個plane;

一個雙聲道的音頻幀有左聲道L和右聲道R, 它們交織存儲在一個plane中, 例如: LRLRLR... ..., data[0]指向這個plane.

對於planar格式, 一個YUV圖像有Y, U, V三個plane, data[0]指向Y plane, data[1]質量U plane, data[2]指向V plane.

一個雙聲道的音頻幀有左聲道L和右聲道R兩個plane, data[0]指向L plane, data[1]指向R plane

 

  • int linesize[AV_NUM_DATA_POINTERS];

對於視頻來說, linesize是每行圖像的大小(字節數, 有字節對齊).

對於音頻來說, linesize是每個plane的大小(字節數). 音頻只是用linesize[0]. 對於planar音頻來說, 每個plane的大小必須一樣.

linesize可能會因為性能上的考慮而填充一些額外的數據, 因此linesize可能比實際對應的音視頻數據尺寸要大.

 

  • uint8_t **extended_data;

  指向數據plane

 

 

  • int width, height;

視頻幀像素寬和高.

 

  • int nb_samples;

音頻幀中單個聲道包含的采樣點數.

 

  • int format;

幀格式. 如果是未知格式或未設置, 值為-1.

對於視頻幀, 值對應enum AVPixelFormat結構:

1 enum AVPixelFormat {
2     AV_PIX_FMT_NONE = -1,
3     AV_PIX_FMT_YUV420P,   ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
4     AV_PIX_FMT_YUYV422,   ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
5     AV_PIX_FMT_RGB24,     ///< packed RGB 8:8:8, 24bpp, RGBRGB...
6     AV_PIX_FMT_BGR24,     ///< packed RGB 8:8:8, 24bpp, BGRBGR...
7     AV_PIX_FMT_YUV422P,   ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
8     AV_PIX_FMT_YUV444P,   ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
... ...
};

 

對於音頻幀, 值對應於enum AVSampleFormat結構:

 1 enum AVSampleFormat {
 2     AV_SAMPLE_FMT_NONE = -1,
 3     AV_SAMPLE_FMT_U8,          ///< unsigned 8 bits
 4     AV_SAMPLE_FMT_S16,         ///< signed 16 bits
 5     AV_SAMPLE_FMT_S32,         ///< signed 32 bits
 6     AV_SAMPLE_FMT_FLT,         ///< float
 7     AV_SAMPLE_FMT_DBL,         ///< double
 8 
 9     AV_SAMPLE_FMT_U8P,         ///< unsigned 8 bits, planar
10     AV_SAMPLE_FMT_S16P,        ///< signed 16 bits, planar
11     AV_SAMPLE_FMT_S32P,        ///< signed 32 bits, planar
12     AV_SAMPLE_FMT_FLTP,        ///< float, planar
13     AV_SAMPLE_FMT_DBLP,        ///< double, planar
14     AV_SAMPLE_FMT_S64,         ///< signed 64 bits
15     AV_SAMPLE_FMT_S64P,        ///< signed 64 bits, planar
16 
17     AV_SAMPLE_FMT_NB           ///< Number of sample formats. DO NOT USE if linking dynamically
18 };

 

 

  • int key_frame;

視頻幀是否是關鍵幀的標識, 1: 關鍵幀; 0: 非關鍵幀.

 

  • enum AVPictureType pict_type;

視頻幀類型(I, B, P等)

enum AVPictureType結構:

 1 enum AVPictureType {
 2     AV_PICTURE_TYPE_NONE = 0, ///< Undefined
 3     AV_PICTURE_TYPE_I,     ///< Intra
 4     AV_PICTURE_TYPE_P,     ///< Predicted
 5     AV_PICTURE_TYPE_B,     ///< Bi-dir predicted
 6     AV_PICTURE_TYPE_S,     ///< S(GMC)-VOP MPEG-4
 7     AV_PICTURE_TYPE_SI,    ///< Switching Intra
 8     AV_PICTURE_TYPE_SP,    ///< Switching Predicted
 9     AV_PICTURE_TYPE_BI,    ///< BI type
10 };

 

 

  • AVRational sample_aspect_ratio;

視頻幀的寬高比.

 

  • int64_t pts;

顯示時間戳. 單位是time_base.

 

  • int64_t pkt_dts;

對應packet中的解碼時間戳. 是從對應pacekt中拷貝得到此值.

如果對應的packet中只有dts而未設置pts, 則此值也是frame的pts.

 

  • int coded_picture_number;

編碼幀序號.

 

  • int display_picture_number;

顯示幀序號

 

  • int quality;

品質(介於1(最好)和FF_LAMBDA_MAX(壞)之間)

 

  • void *opaque;

用戶私有信息.

 

  • int repeat_pict;

解碼時, 每幀圖片的延遲時間.

extra_delay = repeat_pict / (2*fps)

 

  • int interlaced_frame;

是否是隔行掃描.

 

  • int top_field_first;

圖像的top field first變量. 如果內容是隔行的, 則首先顯示頂部字段.

 

  • int palette_has_changed;

告訴用戶應用程序調色板已從上一幀更改

 

  • int sample_rate;

音頻采樣率.

 

  • uint64_t channel_layout;

音頻聲道布局. 每bit代表一個特定的聲道.

參考源碼channel_layout.h中定義: 

 1 #define AV_CH_FRONT_LEFT             0x00000001
 2 #define AV_CH_FRONT_RIGHT            0x00000002
 3 #define AV_CH_FRONT_CENTER           0x00000004
 4 #define AV_CH_LOW_FREQUENCY          0x00000008
 5 #define AV_CH_BACK_LEFT              0x00000010
 6 ...   ...
 7 
 8 #define AV_CH_LAYOUT_MONO              (AV_CH_FRONT_CENTER)
 9 #define AV_CH_LAYOUT_STEREO            (AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT)
10 #define AV_CH_LAYOUT_2POINT1           (AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY)
11 #define AV_CH_LAYOUT_2_1               (AV_CH_LAYOUT_STEREO|AV_CH_BACK_CENTER)
12 #define AV_CH_LAYOUT_SURROUND          (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER)
13 #define AV_CH_LAYOUT_3POINT1           (AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY)
14 ...   ...

 

 

 

  • AVBufferRef *buf[AV_NUM_DATA_POINTERS];

此幀的數據可以由AVBufferRef管理, AVBufferRef提供AVBuffer引用機制.

如果buf[]的所有元素都為NULL, 則此幀不會被引用計數.

必須連續填充buf[], 如果buf[i]為非NULL, 則對所有的j < i, 也必須有b[j]必須為非NULL.

對於視頻來說, buf[]包含所有的AVBufferRef指針.

對於具有多於AV_NUM_DATA_POINTERS個聲道的planar音頻來說, 可能buf[]存不下所有的AVBufferRef指針, 多出的AVBufferRef指針存儲在extended_buf數組中.

 

  • AVBufferRef **extended_buf;

對於具有多於AV_NUM_DATA_POINTERS個聲道的planar音頻來說, 可能buf[]存不下所有的AVBufferRef指針, 多出的AVBufferRef指針存儲在extended_buf數組中.

 

  • int nb_extended_buf;

extended_buf中元素的數目.

 

  • AVFrameSideData **side_data;

邊緣數據

 

  • int nb_side_data;

邊緣數據的數目

 

  • int64_t best_effort_timestamp;

在流時間基中估計幀時間戳.

編碼時未使用

解碼時由解碼器設置. 用戶讀取.

 

  • int64_t pkt_pos;

記錄最后一個扔進解碼器的packet在輸入文件中的位置偏移量.

 

  • int64_t pkt_duration;

對應packet的時長, 單位是AVStream->time_base.

 

  • int channels;

音頻聲道數量.

 

  • int pkt_size;

對應packet的大小.

 

 

size_t crop_top;
size_t crop_bottom;
size_t crop_left;
size_t crop_right;

用於視頻幀圖像裁切. 四個值分別為從frame的上/下/左/右邊界裁切的像素數.

 
  • 這寫成員暫時沒有找到完美的解釋(可能也不是很重要或不太常用)

int flags;

enum AVColorRange color_range;

enum AVColorPrimaries color_primaries;

enum AVColorTransferCharacteristic color_trc;

enum AVColorSpace colorspace;

enum AVChromaLocation chroma_location;

AVDictionary *metadata;

int decode_error_flags;

AVBufferRef *hw_frames_ctx;

AVBufferRef *opaque_ref;

 

2. 相關函數 

  • AVFrame *av_frame_alloc(void);

構造一個AVFrame, 對象成員被設為默認值.

此函數只分配AVFrame對象本身, 而不分配AVFrame中的數據緩存區.

 

  • void av_frame_free(AVFrame **frame);

釋放AVFrame.

 

  • int av_frame_ref(AVFrame *dst, const AVFrame *src);

為src中的數據建立一個新的引用.

將src中幀的各屬性拷到dst中, 並且為src中每個AVBufferRef創建一個新的引用.

如果src未使用引用計數, 則dst中會分配新的數據緩存區, 將src中緩存區的數據拷貝到dst中的緩存區.

 

  • AVFrame *av_frame_clone(const AVFrame *src);

創建一個新的AVFrame, 新的AVFrame和src使用統一數據緩存區, 緩存區管理使用引用計數機制.

 

  • void av_frame_unref(AVFrame *frame);

解除本AVFrame對AVFrame中所有緩存區的引用, 並復位AVFrame中的各成員.

 

  • void av_frame_move_ref(AVFrame *dst, AVFrame *src);

將src中所有數據拷貝到dst中, 並復位src.

為避免內存泄漏, 在調用av_frame_move_ref(dst, src)之前應先調用av_frame_unref(dst);

 

  • int av_frame_get_buffer(AVFrame *frame, int align); 

為音頻或視頻數據分配新的緩沖區.

調用本函數前, 幀中的以下成員必須先設置好:

    • format
    • width, height
    • nb_samples, channel_layout

本函數會填充AVFrame.data和AVFrame.buf數組, 如果有需要, 還會分配和填充AVFrame.extended_data和AVFrame.extended_buf.

對於planar格式, 回味每個plane分配一個緩沖區.

 

  • int av_frame_copy(AVFrame *dst, const AVFrame *src);

將src中的幀數據拷貝到dst中.

本函數並不會有任何分配緩沖區的動作, 調用此函數前dst必須已經使用了和src同樣的參數完成了初始化.

本函數只拷貝幀中的數據緩沖區的內容, 而不涉及幀中的其它屬性.

 

參考

[1] 雷霄驊博士結構體分析:AVFrame  https://blog.csdn.net/leixiaohua1020/article/details/14214577

[2] 葉余 FFmpeg數據結構AVFrame https://www.cnblogs.com/leisure_chn/p/10404502.html

[3]YelloLayne FFmpeg結構體:AVFrame https://www.jianshu.com/p/25a329b20078

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM