Error message here!

Hide Error message here!


Error message here!


Hide Error message here!


Error message here!




叶余 2019-02-20 08:49:00 阅读数:557 评论数:0 点赞数:0 收藏数:0


本文基于FFmpeg 4.1版本。

1. 数据结构定义

struct AVFrame定义于struct AVFrame frame;

AVFrame中存储的是经过解码后的原始数据。在解码中,AVFrame是解码器的输出;在编码中,AVFrame是编码器的输入。下图中,“decoded frames”的数据类型就是AVFrame:

_ | | | | | input | demuxer | encoded data | decoder | file | ---------> | packets | -----+ |_| || | v | | | decoded | | frames | || | | | | | | | output | <-------- | encoded data | <----+ | file | muxer | packets | encoder || ||


/// / This structure describes decoded (raw) audio or video data. / / AVFrame must be allocated using avframealloc(). Note that this only / allocates the AVFrame itself, the buffers for the data must be managed / through other means (see below). / AVFrame must be freed with avframefree(). / / AVFrame is typically allocated once and then reused multiple times to hold / different data (e.g. a single AVFrame to hold frames received from a / decoder). In such a case, avframeunref() will free any references held by / the frame and reset it to its original clean state before it / is reused again. / / The data described by an AVFrame is usually reference counted through the / AVBuffer API. The underlying buffer references are stored in AVFrame.buf / / AVFrame.extendedbuf. An AVFrame is considered to be reference counted if at / least one reference is set, i.e. if AVFrame.buf[0] != NULL. In such a case, / every single data plane must be contained in one of the buffers in /* AVFrame.buf or AVFrame.extendedbuf. / There may be a single buffer for all the data, or one separate buffer for / each plane, or anything in between. / / sizeof(AVFrame) is not a part of the public ABI, so new fields may be added / to the end with a minor bump. / / Fields can be accessed through AVOptions, the name string used, matches the / C structure field name for fields accessible through AVOptions. The AVClass / for AVFrame can be obtained from avcodecgetframe_class() // typedef struct AVFrame { uint8t /*data[AVNUMDATAPOINTERS]; int linesize[AV_NUM_DATA_POINTERS]; uint8_t /*/*extended_data; int width, height; int nb_samples; int format; int key_frame; enum AVPictureType pict_type; AVRational sample_aspect_ratio; int64_t pts; ...... } AVFrame;


  1. AVFrame对象必须调用avframealloc()在堆上分配,注意此处指的是AVFrame对象本身,AVFrame对象必须调用avframefree()进行销毁。
  2. AVFrame中包含的数据缓冲区是
  3. AVFrame通常只需分配一次,然后可以多次重用,每次重用前应调用avframeunref()将frame复位到原始的干净可用的状态。

下面将一些重要的成员摘录出来进行说明:data/// / pointer to the picture/channel planes. / This might be different from the first allocated byte / / Some decoders access areas outside 0,0 - width,height, please / see avcodecaligndimensions2(). Some filters and swscale can read / up to 16 bytes beyond the planes, if these filters are to be used, / then 16 extra bytes must be allocated. / / NOTE: Except for hwaccel formats, pointers not needed by the format / MUST be set to NULL. // uint8_t /data[AV_NUM_DATA_POINTERS];

存储原始帧数据(未编码的原始图像或音频格式,作为解码器的输出或编码器的输入)。data是一个指针数组,数组的每一个元素是一个指针,指向视频中图像的某一plane或音频中某一声道的plane。关于图像plane的详细说明参考“色彩空间与像素格式”,音频plane的详细说明参数“ffplay源码解析6-音频重采样 6.1.1节”。下面简单说明:对于packet格式,一幅YUV图像的Y、U、V交织存储在一个plane中,形如YUVYUV...,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。

linesize/// / For video, size in bytes of each picture line. / For audio, size in bytes of each plane. / / For audio, only linesize[0] may be set. For planar audio, each channel /* plane must be the same size. /* /* For video the linesizes should be multiples of the CPUs alignment /* preference, this is 16 or 32 for modern desktop CPUs. /* Some code requires such alignment other code can be slower without /* correct alignment, for yet other it makes no difference. /* /* @note The linesize may be larger than the size of usable data -- there /* may be extra padding present for performance reasons. /*/ int linesize[AV_NUM_DATA_POINTERS];


extended_data/// / pointers to the data planes/channels. / / For video, this should simply point to data[]. / / For planar audio, each channel has a separate data pointer, and / linesize[0] contains the size of each channel buffer. /* For packed audio, there is just one data pointer, and linesize[0] /* contains the total size of the buffer for all channels. /* /* Note: Both data and extended_data should always be set in a valid frame, /* but for planar audio with more channels that can fit in data, /* extended_data must be used in order to access all channels. /*/ uint8_t /*/*extended_data;


width, height/// / @name Video dimensions / Video frames only. The coded dimensions (in pixels) of the video frame, / i.e. the size of the rectangle that contains some well-defined values. / / @note The part of the frame intended for display/presentation is further / restricted by the @ref cropping "Cropping rectangle". / @{ // int width, height;


nb_samples/// / number of audio samples (per channel) described by this frame // int nb_samples;


format/// / format of the frame, -1 if unknown or unset / Values correspond to enum AVPixelFormat for video frames, / enum AVSampleFormat for audio) // int format;

帧格式。如果是未知格式或未设置,则值为-1。对于视频帧,此值对应于“enum AVPixelFormat”结构:

enum AVPixelFormat { AVPIXFMTNONE = -1, AVPIXFMTYUV420P, ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples) AVPIXFMTYUYV422, ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr AVPIXFMTRGB24, ///< packed RGB 8:8:8, 24bpp, RGBRGB... AVPIXFMT_BGR24, ///< packed RGB 8:8:8, 24bpp, BGRBGR... ...... }

对于音频帧,此值对应于“enum AVSampleFormat”格式:

enum AVSampleFormat { AVSAMPLEFMTNONE = -1, AVSAMPLEFMTU8, ///< unsigned 8 bits AVSAMPLEFMTS16, ///< signed 16 bits AVSAMPLEFMTS32, ///< signed 32 bits AVSAMPLEFMTFLT, ///< float AVSAMPLEFMTDBL, ///< double AVSAMPLEFMTU8P, ///< unsigned 8 bits, planar AVSAMPLEFMTS16P, ///< signed 16 bits, planar AVSAMPLEFMTS32P, ///< signed 32 bits, planar AVSAMPLEFMTFLTP, ///< float, planar AVSAMPLEFMTDBLP, ///< double, planar AVSAMPLEFMTS64, ///< signed 64 bits AVSAMPLEFMTS64P, ///< signed 64 bits, planar AVSAMPLEFMTNB ///< Number of sample formats. DO NOT USE if linking dynamically };


/// / 1 -> keyframe, 0-> not // int key_frame;


pict_type/// / Picture type of the frame. // enum AVPictureType pict_type;


/// / @} / @} / @defgroup lavu_picture Image related / / AVPicture types, pixel formats and basic image planes manipulation. / / @{ // enum AVPictureType { AVPICTURETYPENONE = 0, ///< Undefined AVPICTURETYPEI, ///< Intra AVPICTURETYPEP, ///< Predicted AVPICTURETYPEB, ///< Bi-dir predicted AVPICTURETYPES, ///< S(GMC)-VOP MPEG-4 AVPICTURETYPESI, ///< Switching Intra AVPICTURETYPESP, ///< Switching Predicted AVPICTURETYPEBI, ///< BI type };


/// / Sample aspect ratio for the video frame, 0/1 if unknown/unspecified. // AVRational sampleaspectratio;


pts/// / Presentation timestamp in time_base units (time when frame should be shown to user). // int64_t pts;


pkt_pts/#if FFAPIPKTPTS /// / PTS copied from the AVPacket that was decoded to produce this frame. / @deprecated use the pts field instead /*/ attributedeprecated int64t pktpts; /#endif


pkt_dts/// / DTS copied from the AVPacket that triggered returning this frame. (if frame threading isn't used) / This is also the Presentation time of this AVFrame calculated from / only AVPacket.dts values without pts values. // int64t pktdts;


codedpicturenumber/// / picture number in bitstream order // int codedpicturenumber;


displaypicturenumber/// / picture number in display order // int displaypicturenumber;


interlaced_frame/// / The content of the picture is interlaced. // int interlaced_frame;


sample_rate/// / Sample rate of the audio data. // int sample_rate;


channel_layout/// / Channel layout of the audio data. // uint64t channellayout;


/// / @defgroup channel_masks Audio channel masks / / A channel layout is a 64-bits integer with a bit set for every channel. / The number of bits set must be equal to the number of channels. / The value 0 means that the channel layout is not known. / @note this data structure is not powerful enough to handle channels / combinations that have the same channel multiple times, such as / dual-mono. / / @{ // /#define AVCHFRONTLEFT 0x00000001 /#define AVCHFRONTRIGHT 0x00000002 /#define AVCHFRONTCENTER 0x00000004 /#define AVCHLOWFREQUENCY 0x00000008 ...... /// / @} / @defgroup channelmaskc Audio channel layouts / @{ / // /#define AVCHLAYOUTMONO (AVCHFRONTCENTER) /#define AVCHLAYOUTSTEREO (AVCHFRONTLEFT|AVCHFRONTRIGHT) /#define AVCHLAYOUT2POINT1 (AVCHLAYOUTSTEREO|AVCHLOWFREQUENCY)


/// / AVBuffer references backing the data for this frame. If all elements of / this array are NULL, then this frame is not reference counted. This array / must be filled contiguously -- if buf[i] is non-NULL then buf[j] must / also be non-NULL for all j < i. / / There may be at most one AVBuffer per data plane, so for video this array / always contains all the references. For planar audio with more than / AVNUMDATAPOINTERS channels, there may be more buffers than can fit in / this array. Then the extra AVBufferRef pointers are stored in the / extendedbuf array. // AVBufferRef /buf[AV_NUM_DATA_POINTERS];


如果buf[]的所有元素都为NULL,则此帧不会被引用计数。必须连续填充buf[] - 如果buf[i]为非NULL,则对于所有j

extendedbuf&nbextended_buf/// / For planar audio which requires more than AVNUMDATA_POINTERS / AVBufferRef pointers, this array will hold all the references which / cannot fit into AVFrame.buf. / / Note that this is different from AVFrame.extended_data, which always / contains all the pointers. This array only contains the extra pointers, / which cannot fit into AVFrame.buf. / / This array is always allocated using av_malloc() by whoever constructs / the frame. It is freed in avframeunref(). // AVBufferRef //extended_buf; /// / Number of elements in extendedbuf. /*/ int nbextended_buf;


bestefforttimestamp/// / frame timestamp estimated using various heuristics, in stream time base / - encoding: unused / - decoding: set by libavcodec, read by user. // int64t besteffort_timestamp;


pkt_pos/// / reordered pos from the last AVPacket that has been input into the decoder / - encoding: unused / - decoding: Read by user. // int64t pktpos;


pkt_duration/// / duration of the corresponding packet, expressed in / AVStream->timebase units, 0 if unknown. / - encoding: unused / - decoding: Read by user. /*/ int64t pkt_duration;


channels/// / number of audio channels, only used for audio. / - encoding: unused / - decoding: Read by user. // int channels;


pkt_size/// / size of the corresponding packet containing the compressed / frame. / It is set to a negative value if unknown. / - encoding: unused / - decoding: set by libavcodec, read by user. // int pkt_size;


crop_/// / @anchor cropping / @name Cropping / Video frames only. The number of pixels to discard from the the / top/bottom/left/right border of the frame to obtain the sub-rectangle of / the frame intended for presentation. / @{ // sizet croptop; sizet cropbottom; sizet cropleft; sizet cropright; /// / @} /*/


2. 相关函数使用说明

2.1 avframealloc()

/// / Allocate an AVFrame and set its fields to default values. The resulting / struct must be freed using avframefree(). / / @return An AVFrame filled with default values or NULL on failure. / / @note this only allocates the AVFrame itself, not the data buffers. Those / must be allocated through other means, e.g. with avframeget_buffer() or / manually. // AVFrame /avframealloc(void);


2.2 avframefree()

/// / Free the frame and any dynamically allocated objects in it, / e.g. extendeddata. If the frame is reference counted, it will be / unreferenced first. / / @param frame frame to be freed. The pointer will be set to NULL. // void avframe_free(AVFrame /*/*frame);


2.3 avframeref()

/// / Set up a new reference to the data described by the source frame. / / Copy frame properties from src to dst and create a new reference for each / AVBufferRef from src. / / If src is not reference counted, new buffers are allocated and the data is / copied. / / @warning: dst MUST have been either unreferenced with avframeunref(dst), / or newly allocated with avframealloc() before calling this / function, or undefined behavior will occur. / / @return 0 on success, a negative AVERROR on error // int avframeref(AVFrame /dst, const AVFrame /src);


2.4 avframeclone()

/// / Create a new frame that references the same data as src. / / This is a shortcut for avframealloc()+avframeref(). / / @return newly created AVFrame on success, NULL on error. // AVFrame /avframeclone(const AVFrame /src);


2.5 avframeunref()

/// / Unreference all the buffers referenced by frame and reset the frame fields. // void avframeunref(AVFrame /*frame);


2.6 avframemove_ref()

/// / Move everything contained in src to dst and reset src. / / @warning: dst is not unreferenced, but directly overwritten without reading / or deallocating its contents. Call avframeunref(dst) manually / before calling this function to ensure that no memory is leaked. // void avframemove_ref(AVFrame /*dst, AVFrame /*src);


avframemove_ref(dst, src)之前应先调用


2.7 avframeget_buffer()

/// / Allocate new buffer(s) for audio or video data. / / The following fields must be set on frame before calling this function: / - format (pixel format for video, sample format for audio) / - width and height for video / - nbsamples and channellayout for audio / / This function will fill and AVFrame.buf arrays and, if / necessary, allocate and fill AVFrame.extendeddata and AVFrame.extendedbuf. / For planar formats, one buffer will be allocated for each plane. / / @warning: if frame already has been allocated, calling this function will / leak memory. In addition, undefined behavior can occur in certain / cases. / / @param frame frame in which to store the new buffers. / @param align Required buffer size alignment. If equal to 0, alignment will be / chosen automatically for the current CPU. It is highly / recommended to pass 0 here unless you know what you are doing. / / @return 0 on success, a negative AVERROR on error. // int avframeget_buffer(AVFrame /*frame, int align);


  • format (视频像素格式或音频采样格式)
  • width、height(视频画面和宽和高)
  • nbsamples、channellayout(音频单个声道中的采样点数目和声道布局)


2.8 avframecopy()

/// / Copy the frame data from src to dst. / / This function does not allocate anything, dst must be already initialized and / allocated with the same parameters as src. / / This function only copies the frame data (i.e. the contents of the data / / extended data arrays), not any other properties. / / @return >= 0 on success, a negative AVERROR on error. // int avframecopy(AVFrame /dst, const AVFrame /src);


3. 参考资料

[1] [FFMPEG结构体分析:AVFrame](, [](

4. 修改记录

2019-01-13 V1.0 初稿