AvFrame和AvPacket

2023-05-16

在FFmpeg中,未压缩的图像和压缩的视频码流分别使用AVFrame结构和AVPacket结构保存; 针对视频编码器,其流程为从数据源获取图像格式的输入数据,保存为AVFrame对象并传入编码器,从编码器输出AVPacket结构。

1. AVFrame结构体

typedef struct AVFrame {
#define AV_NUM_DATA_POINTERS 8 //表示一个AVFrame结构最多保存8个图像分量;
 
	//待编码的图像像素数据保存在其中,各图像分量的像素数据保存在AVframe::data[0]~data[7]
    uint8_t *data[AV_NUM_DATA_POINTERS];
 
    int linesize[AV_NUM_DATA_POINTERS]; //每个分量的存储区的宽度,称为步长;
 
	/*指向数据平面/通道的指针。
	  对于视频,指向data[]
	  对于planar音频,每个通道有分离的数据指针,且linesize[0]包含每个通道buffer的大小;
	  对于packed音频,仅仅是一个数据指针,且linesize[0]包含所有通道buffer的总大小; 
	*/
    uint8_t **extended_data;
 
	//图像宽高
    int width, height;
 
	//本帧描述的音频采样数(每个频道) 
    int nb_samples;
 
     //帧格式,常见的为AV_PIX_FMT_YUV420P
    int format;
 
    int key_frame; //当前帧的关键帧标识位;1表该帧为关键帧;0表非关键帧;
 
 
    enum AVPictureType pict_type;//当前帧的类型,0,1,2分别表示I帧,P帧,B帧;
 
    //采样视频帧的长宽比,如果未知/未指定,则为0/1;
    AVRational sample_aspect_ratio;
 
    int64_t pts;//当前帧的显示时间戳;
 
#if FF_API_PKT_PTS
    //PTS复制自AVPacket,被解码产生此帧。
    int64_t pkt_pts;
#endif
 
    //dts从触发返回帧的AVPacket中复制
    //这也是由AVPacket计算出的AVFrame的显示时间。 无PTS值的DTS值
    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;
 
    //AVBuffer引用支持这个帧的数据
    AVBufferRef *buf[AV_NUM_DATA_POINTERS];
 
    AVBufferRef **extended_buf;
 
	//扩展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;
 
    //从输入到解码器的最后一个AVPacket重新排序pos 
    int64_t pkt_pos;
 
    //对应报文的持续时间,以AVStream->time_base units表示,如果未知则为0
    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对齐;

示例:

//创建AVFrame结构的实例并初始化;
//仅仅创建AVFrame的实例,并没有分配用于存储其内部图像的内存空间;
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;
 
//给AVFrame结构中的音视频数据分配内存空间;
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;//当前packet的显示时间戳;必须大于等于dts
    int64_t dts;//当前packet的解码时间戳,以AVStream的time_base为单位;
    uint8_t *data;//码流数据保存在data指针指向的内存;
    int   size;//数据长度为size字节;可通过data和size读取编码后的码流;
    int   stream_index;//当前packet所从属的stream序号;
    int   flags;
    AVPacketSideData *side_data;
    int side_data_elems;
    //当前packet的显示时长,即按照顺序显示下一帧pts与当前pts的差值;
    int64_t duration; 
    //当前packet在数据流中的二进制位置; -1表示未知;
    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(使用前将#替换为@)

AvFrame和AvPacket 的相关文章

  • CUDA是什么-CUDA简介

    CPU GPU CPU CPU xff08 Central Processing Unit xff09 是一块超大规模的集成电路 xff0c 是一台计算机的运算核心 xff08 Core xff09 和控制核心 xff08 Control
  • 自动驾驶传感器评估 ——IMU惯性测量单元

    自动驾驶传感器评估 IMU惯性测量单元 前言 对于自动驾驶来说 xff0c 高精度定位必不可少 为了让自动驾驶系统更高频率的获取定位信息 xff0c 就必须引入更高频率的传感器 xff0c 这时就体现出了惯性测量单元 xff08 Inert
  • 洛谷:P1238 走迷宫(DFS)

    题目描述 有一个mn格的迷宫 表示有m行 n列 xff0c 其中有可走的也有不可走的 xff0c 如果用1表示可以走 xff0c 0表示不可以走 xff0c 文件读入这m n个数据和起始点 结束点 起始点和结束点都是用两个数据来描述的 xf
  • 通过ajax进行文件上传及回显并解决后台返回图片路径却不能直接显示问题

    1 选中图片立刻回显 前端代码 lt div class 61 34 row 34 id 61 34 uplodFilel 34 gt lt div class 61 34 col md 8 34 gt lt label gt 上传身份证正
  • STM32CubeMX配置串口

    配置串口 1 在Piont amp Configuration中的A gt Z找到USART1 xff1b 2 第一个选项Mode是用来设置串口模式或关闭串口 xff0c 第二个选项Hardware Flow Control用来开启硬件流控
  • postman汉化教程(历史老版本)

    目录 1 下载对应版本的postman 2 替换url中对应的版本号 3 下载postman对应版本的汉化包 4 打开postman文件位置 5 打开后寻找 app 9 12 2 resources 目录 然后将下载好的压缩包解压 6 重启
  • c++学习 :函数形参4种传递形式:(int a)(int &a)(int *a)(int *& a)

    c 43 43 学习 xff1a 函数形参4种传递形式 1 void func int para 2 void func int amp para 3 void func int pointer 4 void func int amp po
  • RTOS关于SysTickHandler()

    我们知道FREERTOS会自动装载PendSV Handler 和SVC Handler 函数 xff0c 这里我们希望自己对其从新定义 xff0c 故做如下处理 include 34 delay h 34 include 34 sys h
  • STM32 正点原子学习(个人学习)

    系统执行一般只设置一次优先级分组 设置好之后不再改变 xff0c 不然会导致混乱 抢占优先级先进行判断响应优先级后 xff0c 同级别抢占优先级但高级别的响应优先级也不能打断同级别抢占优先级低级别的响应优先级 系统中断优先级分组函数 xff
  • Spring AOP使用案例

    AOP 原理 代理模式 需求背景 返回前端的用户信息包含手机号等敏感内容 xff0c 并在系统上已经有大量接口 现拿到需求 xff0c 需要在返回前端的对象中 xff0c 找到手机号的属性并将手机号加密 现状 xff1a 分散在各处的接口中
  • 【JVM】说一下jvm运行时数据区域

    说一下jvm运行时数据区域 文章目录 说一下jvm运行时数据区域程序计数器栈本地方法栈堆方法区运行时常量池直接内存 本篇文章总结自 深入理解Java虚拟机 程序计数器 程序计数器是一块较小的内存空间 xff0c 它可以看作是当前线程所执行的
  • ffmpeg错误总结

    av err2str 在C 43 43 项目中 xff0c 使用FFmpeg中的av err2str函数时 xff0c 报错 解决 xff1a 调用该函数的文件开始加上以下代码 xff1a span class token keyword
  • 【JVM】垃圾回收算法

    垃圾回收算法 文章目录 垃圾回收算法标记 清除算法标记 复制算法Appel式回收 标记整理算法混合使用 标记 清除算法 标记 清除算法是最早出席那也是最基础的垃圾收集算法 xff0c 是1960年由Lisp之父John McCarthy所提
  • 【JVM】如何判决一个对象的生死

    如何判决一个对象的生死 文章目录 如何判决一个对象的生死如何判断对象是否存活 xff08 应该被回收 xff09 引用计数法可达性分析算法引用生存还是死亡 如何判断对象是否存活 xff08 应该被回收 xff09 引用计数法 很多教科书判断

随机推荐

  • 【大前端】vue,jq,uniapp ajax默认的请求格式

    vue jq uniapp ajax默认的请求格式 文章目录 vue jq uniapp ajax默认的请求格式常见的内容类型 xff08 content type xff09 jq默认请求格式默认内容类型 xff1a multipart
  • 【大前端】uniapp上传图片

    uniapp上传图片 看本篇文章之前建议看下本篇文章 直接上代码 uni chooseImage success chooseImageRes 61 gt 获取文件的路径 const tempFilePaths 61 chooseImage
  • 【JavaWeb】el表达式与jstl标签的使用

    el表达式与jstl标签的使用 el表达式 简介 el表达式的全称 xff1a Expression Language 是表达式语言 EL表达式的作用 xff1a EL表达式主要是代替jsp页面中的表达式脚本在jsp页面中进行数据的输出 因
  • 【Java】说说Java的线程池

    说说Java的线程池 文章目录 说说Java的线程池为什么要使用线程池ThreadPoolExecutor提供的构造方法解析 线程池处理流程 为什么要使用线程池 创建 销毁线程需要消耗系统资源 xff0c 线程池可以复用已创建的线程控制并发
  • 【Java】Java的类加载器和双亲委派模型

    文章目录 类加载器双亲委派模型 类加载器 对于任意一个类 xff0c 都必须由加载它的类加载器和这个类本身一起共同确立其在Java虚拟机中的唯一性 xff0c 每一个类加载器 xff0c 都有一个独立的类名称空间 比较两个类是否 34 相等
  • 【git】说说git的基础命令

    git的基础命令 命令名称作用git config global user name 用户名设置用户签名git config global user email 邮箱设置用户签名git init初始化本地库git status查看本地库状态
  • 【maven】maven基础知识入门

    maven 文章目录 maven什么是maven为什么使用maven项目构建过程的几个主要环节maven核心概念如何通过坐标到仓库中查找jar包 什么是maven Maven 是 Apache 软件基金会组织维护的一款自动化构建工具 xff
  • 【spring】说说spring的IOC与DI

    说说spring的IOC与DI 文章目录 说说spring的IOC与DIid属性和name属性标签scope Bean的作用范围Spring xff0c 配置生成Bean的三种方式Sping 的 Bean属性注入Sping的Bean属性通过
  • ffmpeg时间戳相关函数

    1 概述 ffmpeg中与时间戳相关的函数主要有 xff1a av rescale q xff0c av rescale q rnd xff0c av compare ts av rescale q span class token cla
  • 【计算机网络】网线规格的鉴别与接线方法

    网线规格的鉴别与接线发送 文章目录 网线规格的鉴别与接线发送一 怎么判断网线类型 xff1f 二 制作网线标准三 屏蔽类型四 使用场景五 米数标记接线方法 一 怎么判断网线类型 xff1f 可以根据网线外皮的标识来判断 xff0c 正规厂商
  • 【Java】说说spring-jdbc和spring事务管理

    文章目录 说说spring jdbc和spring事务管理spring jdbc1 配置数据源2 使用jdbcTemplete3 在dao层使用jdbcTemplete 外部配置方式新建配置文件jdbc properties修改数据源配置部
  • 【微服务】springcloud-dubbo,springCloudAlibaba服务调用使用dubbo

    springcloud dubbo xff0c springCloudAlibaba服务调用使用dubbo 文章目录 springcloud dubbo xff0c springCloudAlibaba服务调用使用dubbo添加依赖配置具体
  • 【项目实战】spring boot中使用webSocket

    spring boot中使用webSocket 文章目录 spring boot中使用webSocket引入依赖支持配置类接口类前端连接方式前端信息发送方式 引入依赖 需要在基础的spring boot web项目项目中添加下面一个依赖 x
  • 【项目复盘】springboot项目中使用mybatis-plus进行分页

    springboot项目中使用mybatis plus进行分页 文章目录 springboot项目中使用mybatis plus进行分页引入依赖配置类实体类持久层业务层 引入依赖 span class token generics span
  • 【项目复盘】javax.validation的简单使用

    javax validation的简单使用 javax validation需要与hibernate validator配合使用 validation bean 是基于JSR 303标准开发出来的 xff0c 使用注解方式实现 xff0c
  • 【项目复盘】springboot中使用swagger生成接口文档并配置bootstrap主题

    springboot中使用swagger生成接口文档并配置bootstrap主题 引入依赖 span class token generics span class token punctuation lt span dependency
  • 【项目复盘】微服务网关GateWay过滤

    微服务网管过滤 新建一个过滤类 span class token annotation punctuation 64 Component span span class token comment 过滤器的执行优先级 返回值越小 执行优先级
  • 【项目实战】Winodws下使用ELK搭建日志分析框架

    项目实战 Winodws下使用ELK搭建日志分析框架 ELK是什么 xff1a 引用官网的一句话 xff1a 核心产品包括 Elasticsearch Kibana Beats 和 Logstash xff08 也称为 ELK Stack
  • java_网络编程知识

    day11 网络编程 主要内容 软件架构CS xff0f BS网络通信三要素TCP通信Socket套接字ServerSocket 学习目标 能够辨别UDP和TCP协议特点 能够说出TCP协议下两个常用类名称 能够编写TCP协议下字符串数据传
  • AvFrame和AvPacket

    在FFmpeg中 未压缩的图像和压缩的视频码流分别使用AVFrame结构和AVPacket结构保存 针对视频编码器 其流程为从数据源获取图像格式的输入数据 保存为AVFrame对象并传入编码器 从编码器输出AVPacket结构 1 AVFr