背景
AVFrame 主要用來存儲編碼前的原始數據。
AVFrame 結構體
在 frame.h 文件中
主要變量
uint8_t *data[AV_NUM_DATA_POINTERS]; // 存儲每個 planes 的數據
int linesize[AV_NUM_DATA_POINTERS]; // 每一行的音視頻數據
uint8_t **extended_data; // 視頻,指向 data, 音頻有需要則指向新的地址。由于音頻可以支持多個聲道,比如 22,data 存不在,則需要放到這里。
int width, height; // 視頻寬和高
int nb_samples; // 音頻每個通道的采樣數
int format; // 音視頻格式 AVPixelFormat AVSampleFormat
int key_frame; // 是不是關鍵幀
enum AVPictureType pict_type; // 圖片類型
AVRational sample_aspect_ratio; // 寬高比
int64_t pts; // 渲染時間
AVRational time_base; // 時間基
int sample_rate; // 采樣率
AVBufferRef *buf[AV_NUM_DATA_POINTERS]; // 實際數據存儲地方,data 指針指向這里。通過引用來控制是否釋放內存。
AVBufferRef **extended_buf; // 類似 buf,存儲 extended_data
AVChannelLayout ch_layout; // 音頻通道數
AVFrame 函數
常用函數
av_frame_alloc
作用:分配 AVFrame,并設置默認值,通過 av_frame_free 釋放。且不會創建 data buffer,因為此時他還不知道要分配多大的內存。
AVFrame *av_frame_alloc(void);
av_frame_free
釋放 AVFrame,并減少動態分配變量的引用計數。
void av_frame_free(AVFrame **frame);
av_frame_ref
拷貝 src 的值到 dst,并增加 buf 和 extended_buf 引用 (為啥引用到1 就刪除)
int av_frame_ref(AVFrame *dst, const AVFrame *src);
av_frame_unref
減少引用并重置各字段
void av_frame_unref(AVFrame *frame);
av_frame_get_buffer
為音視頻分配內存,調用這個函數前
視頻需要設置:格式、寬和高
音頻需要設置:采樣格式、聲道數、每個聲道的音頻采樣數
否則,不知道要分配多大的內存。
int av_frame_get_buffer(AVFrame *frame, int align);
不常用函數
av_frame_clone
相當于 av_frame_alloc()+av_frame_ref()
AVFrame *av_frame_clone(const AVFrame *src);
av_frame_move_ref
將 src 賦值給 dst
void av_frame_move_ref(AVFrame *dst, AVFrame *src);
av_frame_is_writable
判斷 frame 是否可寫,ffmpeg 好像認為有多個引用,則不可寫。應該是需要加鎖才能確保安全。
int av_frame_is_writable(AVFrame *frame);
av_frame_make_writable
讓 frame 可寫,如果有多個引用frame地址,則重新創建一塊內存。
int av_frame_make_writable(AVFrame *frame);
av_frame_copy
只拷貝 src 的 buf 到 dst,需要提前確保兩者的 buf 內存一樣。
int av_frame_copy(AVFrame *dst, const AVFrame *src);
av_frame_copy_props
只拷貝元信息,應該是只那些輔助信息吧,比如 pts、timebase、sidedata等
int av_frame_copy_props(AVFrame *dst, const AVFrame *src);
av_frame_get_plane_buffer
獲取某個 plane 的數據
AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane);
side_data
side_data 相關
AVFrameSideData *av_frame_new_side_data(AVFrame *frame,enum AVFrameSideDataType type,size_t size);
AVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame,enum AVFrameSideDataType type,AVBufferRef *buf);AVFrameSideData *av_frame_get_side_data(const AVFrame *frame,enum AVFrameSideDataType type);
void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type);
// 返回 sidedata 類型
const char *av_frame_side_data_name(enum AVFrameSideDataType type);
av_frame_apply_cropping
對數據進行裁剪
int av_frame_apply_cropping(AVFrame *frame, int flags);