在FFmpeg中,未压缩的图像和压缩的视频码流分别使用AVFrame结构和AVPacket结构保存; 针对视频编码器,其流程为从数据源获取图像格式的输入数据,保存为AVFrame对象并传入编码器,从编码器输出AVPacket结构。
1. AVFrame结构体
typedef struct AVFrame {
#define AV_NUM_DATA_POINTERS 8
uint8_t *data[AV_NUM_DATA_POINTERS];
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;
#if FF_API_PKT_PTS
int64_t pkt_pts;
#endif
int64_t pkt_dts;
int coded_picture_number;
int display_picture_number;
int quality;
void *opaque;
int repeat_pict;
int interlaced_frame;
int top_field_first;
int palette_has_changed;
int64_t reordered_opaque;
int sample_rate;
uint64_t channel_layout;
AVBufferRef *buf[AV_NUM_DATA_POINTERS];
AVBufferRef **extended_buf;
int nb_extended_buf;
AVFrameSideData **side_data;
int nb_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;
int64_t pkt_pos;
int64_t pkt_duration;
AVDictionary *metadata;
int channels;
int pkt_size;
AVBufferRef *hw_frames_ctx;
AVBufferRef *opaque_ref;
size_t crop_top;
size_t crop_bottom;
size_t crop_left;
size_t crop_right;
AVBufferRef *private_ref;
} AVFrame;
在AVFrame结构中,它所包含的最重要的结构即数据的缓存区;待编码的数据的像素数据保存在AVFrame结构的data指针所保存的内存区中;
一个AVFrame结构最多可以保存8个图像分量,各图像分量的像素数据保存在AVFrame::data[0]~AVFrame::data[7]所指向的内存区中;
1.1 创建AVFrame结构的实例并初始化
AVFrame *av_frame_alloc(void);
注:仅仅创建AVFrame结构的实例,以及初始化内部各个字段的值,并没有分配用于存储其内部图像的内存空间;
1.2 给AVFrame结构体中的音视频数据分配内存空间
int av_frame_get_buffer(AVFrame *frame, int align);
作用:实际分配内存空间;
参数1:AVFrame指针;
参数2:对齐方式,<=0表示以32字节对齐;否则以align对齐;
示例:
frame = av_frame_alloc();
if (!frame) {
fprintf(stderr, "Could not allocate video frame\n");
exit(1);
}
frame->format = c->pix_fmt;
frame->width = c->width;
frame->height = c->height;
ret = av_frame_get_buffer(frame, 0);
if (ret < 0) {
fprintf(stderr, "Could not allocate the video frame data\n");
exit(1);
}
1.3 将保存了图像数据的AVFrame结构传入编码器
int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame);
参数1:当前编码器的上下文结构l;
参数2:待编码的图像结构;当该参数为NULL时表示编码结束,此时应该刷新编码器缓存的码流;
返回值:0:正常执行; 负数表错误码;
AVERROR(EAGAIN):输入缓存已满,应该调用avcodec_receive_packet获取输出数据后在尝试输入;
AVERROR_EOF:编码器已收到刷新指令,不再接收的图像输入;
VERROR(EINVAL):编码器状态错误;
VERROR(ENOMEM):内存空间不足;
1.4 释放分配的图像帧结构
void av_frame_free(AVFrame **frame)
2. AVPacket结构体
typedef struct AVPacket {
AVBufferRef *buf;
int64_t pts;
int64_t dts;
uint8_t *data;
int size;
int stream_index;
int flags;
AVPacketSideData *side_data;
int side_data_elems;
int64_t duration;
int64_t pos;
} AVPacket;
2.1 创建AVPacket结构的实例并初始化
AVPacket *av_packet_alloc(void);
2.2 依照一个已存在的packet创建新的packet,新packet是对原packet的引用
AVPacket *av_packet_clone(const AVPacket *src);
2.3 释放一个packet,若该packet存在引用计数,则其引用计数减1
void av_packet_free(AVPacket **pkt);
2.4 按照指定大小分配一个packet的存储空间,并初始化该packet
int av_new_packet(AVPacket *pkt, int size);
2.5 根据传入的packet创建新的引用packet
int av_packet_ref(AVPacket *dst, const AVPacket *src);
2.6 回收该packet
void av_packet_unref(AVPacket *pkt);
2.7 从编码器中获取输出的码流,并保存在传入的AVPacket结构中
int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt);
参数1:当前编码器上下文结构;
参数2:输出的码流包结构,包含编码器输出的视频码流;
返回值:0表正常,负数为错误码;
AVERROR(EAGAIN):编码器尚未完成对新一帧的编码,应继续通过函数avcodec_send_frame传入后续图像;
AVERROR_EOF:编码器已经完成输出内部缓存的码流,编码完成;
VERROR(EINVAL):编码器状态错误;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)