FFmpeg-aac、h264封装flv及时间转换
文章目录
- 时间概念
- 流程
- api
- 核心代码
时间概念
dts: 解码时间戳, 表示压缩帧的解码时间
pts: 显示时间戳, 表示将压缩帧解码后得到的原始帧的显示时间
时间基: time_base , 通常以ms为单位
时间戳: timestamp , 多少个时间基
真实时间:time_base * timestamp
如一个视频帧的dts为40(时间戳) ,time_base:1/1000s
真实时间: 40 * 1/1000 s
ffmpeg/ffplay命令参数:
tbr: 通常为帧率
tbn: 视频流的时间基
tbc: 视频解码的时间基
ffmepg内部时间基:
#define AV_TIME_BASE 1000000 //微妙
时间转换
av_q2d():将时间从AVRational(分数)形式转换为double形式
static inline double av_q2d(AVRational a){return a.num / (double) a.den;
}
时间基转换函数:
av_rescale_q() :⽤于将时间值从⼀种时间基转换为另⼀种时间基
av_rescale_rnd():用于时间取整
av_packet_rescale_ts:⽤于将AVPacket中各种时间值从⼀种时间基转换为另⼀种时间基
1 视频流
转封装过程中的时间基转换:
AVStream.time_base是AVPacket中pts和dts的时间单位
- 对于输⼊流:打开输⼊⽂件后,调⽤avformat_find_stream_info()可获取到每个流中的time_base
- 对于输出流:打开输出⽂件后,调⽤avformat_write_header()可根据输出⽂件封装格式确定每个流的time_base并写⼊输出⽂件中
转码过程中的时间基转换:
编解码器中的时间基为 AVCodecContext.time_base,值为帧率(视频帧)的倒数
解码视频帧:
时间基为 1/framerate
- 视频解码过程中的时间基转换处理:
若从av_read_frame读取的packet,是以AVSteam->time_base,是avcodec_receive_frame后以AVSteam->time_base为准 - 视频编码过程中的时间基转换处理:
编码的时候frame如果以AVstream为time_base送编码器,
则avcodec_receive_packet读取的时候也是以转成AVSteam->time_base
2 视频流
解码后的原始视频帧时间基为 1/framerate
流程
首先生成一个h264和aac,封装为flv add_stream函数类似编码过程

api
- avformat_write_header : 写⽂件头
- av_write_frame/av_interleaved_write_frame: 写packet
- av_write_trailer : 写⽂件尾
- avcodec_parameters_from_context: 将AVCodecContext结构体中码流参数拷⻉到AVCodecParameters结构体中
- int avformat_alloc_output_context2 – 根据filename申请上下文
- AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c) // 新增流通道
int avformat_alloc_output_context2(AVFormatContext **ctx, ff_const59 AVOutputFormat *oformat,const char *format_name, const char *filename) {} ctx:需要创建的context,返回NULL表示失败format:指定对应的AVOutputFormatformat_name: 指定⾳视频的格式,⽐如“flv”,“mpeg”等,如果设置为NULL,则由filename进⾏指定,让ffmpeg⾃⼰推断filename: 指定⾳视频⽂件的路径
核心代码
命令行参数: test.flv aac h264创建流生成
如何转换时间time_base:
open_audio: 关联编码器,会设置codec_ctx->time_base
avformat_write_header: base_time 转化为 1/1000
write_audio_frame中调用write_frame,pts会进行转化
如采样率44.1hz , pts_after = pts_before(-1024) * 1/44100 * 1000 = -23
//输出⽂件容器格式,生成flv文件,对应的ffmepg的源文件为flvenc.c
AVOutputFormat ff_flv_muxer = {.name = "flv",.long_name = NULL_IF_CONFIG_SMALL("FLV (Flash Video)"),.mime_type = "video/x-flv",.extensions = "flv",.priv_data_size = sizeof(FLVContext),.audio_codec = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_ADPCM_SWF,.video_codec = AV_CODEC_ID_FLV1,.init = flv_init,.write_header = flv_write_header,.write_packet = flv_write_packet,.write_trailer = flv_write_trailer,.check_bitstream= flv_check_bitstream,
};static int write_video_frame(AVFormatContext *oc, OutputStream *ost)
{int ret;AVCodecContext *codec_ctx;AVFrame *frame;int got_packet = 0;AVPacket pkt = { 0 };codec_ctx = ost->enc;frame = get_video_frame(ost);av_init_packet(&pkt);/* encode the image */avcodec_encode_video2(codec_ctx, &pkt, frame, &got_packet);if (got_packet){ret = write_frame(oc, &codec_ctx->time_base, ost->st, &pkt);}else{ret = 0;}if (ret < 0){fprintf(stderr, "Error while writing video frame: %s\n", av_err2str(ret));exit(1);}return (frame || got_packet) ? 0 : 1;
}int main(int argc, char **argv)
{OutputStream video_st = { 0 }; // 封装视频编码相关的OutputStream audio_st = { 0 }; // 封装音频编码相关的const char *filename; // 输出文件// AVOutputFormat ff_flv_muxerAVOutputFormat *fmt; // 输出文件容器格式, 封装了复用规则,AVInputFormat则是封装了解复用规则AVFormatContext *oc;AVCodec *audio_codec, *video_codec;int ret;int have_video = 0, have_audio = 0;int encode_video = 0, encode_audio = 0;AVDictionary *opt = NULL;int i;filename = argv[1];/* 分配AVFormatContext并根据filename绑定合适的AVOutputFormat */avformat_alloc_output_context2(&oc, NULL, NULL, filename);fmt = oc->oformat; // 获取绑定的AVOutputFormat// 我们音视频课程音视频编解码主要涉及H264和AAC, 所以我们指定为H264+AACfmt->video_codec = AV_CODEC_ID_H264; // 指定编码器fmt->audio_codec = AV_CODEC_ID_AAC; // 指定编码器/* 使用指定的音视频编码格式增加音频流和视频流 */if (fmt->video_codec != AV_CODEC_ID_NONE){add_stream(&video_st, oc, &video_codec, fmt->video_codec);have_video = 1;encode_video = 1;}if (fmt->audio_codec != AV_CODEC_ID_NONE){add_stream(&audio_st, oc, &audio_codec, fmt->audio_codec);have_audio = 1;encode_audio = 1;}if (have_video)open_video(oc, video_codec, &video_st, opt);if (have_audio)open_audio(oc, audio_codec, &audio_st, opt);/* open the output file, if needed */if (!(fmt->flags & AVFMT_NOFILE)){// 打开对应的输出文件,没有则创建avio_open(&oc->pb, filename, AVIO_FLAG_WRITE);}// audio AVstream->base_time = 1/44100, video AVstream->base_time = 1/25// base_time audio = 1/1000 video = 1/1000avformat_write_header(oc, &opt);while (encode_video || encode_audio){/* select the stream to encode */if (encode_video && // video_st.next_pts值 <= audio_st.next_pts时(!encode_audio || av_compare_ts(video_st.next_pts, video_st.enc->time_base,audio_st.next_pts, audio_st.enc->time_base) <= 0)) {printf("\nwrite_video_frame\n");encode_video = !write_video_frame(oc, &video_st);}else{printf("\nwrite_audio_frame\n");encode_audio = !write_audio_frame(oc, &audio_st);}}av_write_trailer(oc);/* Close each codec. */if (have_video)close_stream(oc, &video_st);if (have_audio)close_stream(oc, &audio_st);if (!(fmt->flags & AVFMT_NOFILE))avio_closep(&oc->pb);avformat_free_context(oc);return 0;
}
相关文章:
FFmpeg-aac、h264封装flv及时间转换
文章目录 时间概念流程api核心代码 时间概念 dts: 解码时间戳, 表示压缩帧的解码时间 pts: 显示时间戳, 表示将压缩帧解码后得到的原始帧的显示时间 时间基: time_base , 通常以ms为单位 时间戳: timestamp , 多少个时间基 真实时间:time_base * timest…...
TCP并发模型 || select || poll || epoll
TCP并发模型: 1.TCP多线程模型: 缺点: 1.创建线程会带来资源开销,能够实现的并发量比较有限 2.IO模型: 1.阻塞IO: 没有数据到来时,可以让任务挂起,节省CPU资源开销,提高系统效率 2.非阻塞IO: 程序未接收到数据时一直执行,效率很低 3…...
【开源】SpringBoot框架开发房屋出售出租系统
目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 房屋销售模块2.2 房屋出租模块2.3 预定意向模块2.4 交易订单模块 三、系统展示四、核心代码4.1 查询房屋求租单4.2 查询卖家的房屋求购单4.3 出租意向预定4.4 出租单支付4.5 查询买家房屋销售交易单 五、免责说明 一、摘…...
STM32的简单介绍
STM32是一种基于ARM Cortex-M内核的32位微控制器,由意法半导体公司开发和生产。STM32具有丰富的外设和功能,适用于各种应用场合,如工业控制、消费电子、物联网、人机交互等。STM32的优势包括低功耗、高性能、高可靠性、易于开发等。STM32的系…...
浏览器同源策略及跨域问题
同源策略:同源策略是一个重要的安全策略,它用于限制一个源的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。 同源策略的作用:保护浏览器中网站的安全,限制ajax只…...
【读书笔记】知识图谱概述
1、KG定义 1.1 背景知识 人工智能分为三个层次,分别是运算智能,感知智能和认知智能。运算智能是让机器能存会算;感知智能是让机器能听会说、能看会认;认知智能是解决机器能理解会思考的问题。由于知识图谱的数据组织方式是计算机…...
用尾插的思路实现 “合并两个有序链表”
一、题目 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1: 输入:l1 [1,2,4], l2 [1,3,4] 输出:[1,1,2,3,4,4]示例 2: 输入:l1 [], l2 [] 输出&#…...
大数据 - Spark系列《十四》- spark集群部署模式
Spark系列文章: 大数据 - Spark系列《一》- 从Hadoop到Spark:大数据计算引擎的演进-CSDN博客 大数据 - Spark系列《二》- 关于Spark在Idea中的一些常用配置-CSDN博客 大数据 - Spark系列《三》- 加载各种数据源创建RDD-CSDN博客 大数据 - Spark系列《…...
考研C语言复习进阶(2)
目录 1. 字符指针 2. 指针数组 3. 数组指针 3.1 数组指针的定义 3.2 &数组名VS数组名 4. 函数指针 5. 函数指针数组 6. 指向函数指针数组的指针 7. 回调函数 8.三步辗转法 9. 指针和数组笔试题解析 10. 指针笔试题 指针的主题,我们在初级阶段的《指…...
设计模式学习笔记 - 设计原则与思想总结:1.总结回顾面向对象、设计原则、编程规范、重构技巧等知识点
概述 对前面的内容的回顾,温故而知新,包括:面向对象、设计原则、规范与重构三个模块的内容。 1.代码质量评判标准 如何评价代码质量的高低? 代码质量的评价具有很强的主观性,描述代码质量的词汇也有很多,…...
WPF图表库LiveCharts的使用
这个LiveCharts非常考究版本,它有非常多个版本,.net6对应的是LiveChart2 我这里的wpf项目是.net6,所以安装的是这三个,搜索的时候要将按钮“包括愈发行版”打勾 git:https://github.com/beto-rodriguez/LiveCharts2?…...
第十三届蓝桥杯省赛C++ C组《全题目+题解》
填空题一般都是找规律题目,耐下心来慢慢分析即可。 第一题《排列字母》 【问题描述】 小蓝要把一个字符串中的字母按其在字母表中的顺序排列。 例如,LANQIAO 排列后为AAILNOQ。 又如,GOODGOODSTUDYDAYDAYUP 排列后为AADDDDDGGOOOOPSTUUYYY。…...
Linux——线程池
目录 线程池的概念 线程池的优点 线程池的实现 【注意】 线程池的线程安全 日志文件的实现 线程池的概念 线程池也是一种池化技术,可以预先申请一批线程,当我们后续有任务的时候就可以直接用,这本质上是一种空间换时间的策略。 如果有任…...
Linux:搭建ntp服务器
我准备两个centos7服务器 一个为主服务器连接着外网,并且搭建了ntp服务给其他主机同步 另外一个没有连接外网,通过第一台设备去同步时间 首先两个服务器都要安装ntp软件 yum -y install ntp 再把他俩的时间都改成别的 左侧的是主服务器,主…...
unity学习(57)——选择角色界面--删除角色2
1.客户端添加点击按钮所触发的事件,在selectMenu界面中增加myDelete函数,当点击“删除角色”按钮时触发该函数的内容。 public void myDelete() {string message nowPlayer.id;//string m Coding<StringDTO>.encode(message);NetWorkScript.get…...
Flutter:构建美观应用的跨平台方案
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…...
【深度学习模型移植】用torch普通算子组合替代torch.einsum方法
首先不得不佩服大模型的强大之处,在算法移植过程中遇到einsum算子在ONNX中不支持,因此需要使用普通算子替代。参考TensorRT - 使用torch普通算子组合替代torch.einsum爱因斯坦求和约定算子的一般性方法。可以写出简单的替换方法,但是该方法会…...
鸿蒙 Harmony 初体验
前言 看现在网上传得沸沸扬扬的鸿蒙,打算弄个 hello world 玩一下, 不然就跟不上时代的发展了 环境安装 我的环境 Windows 11 家庭中文版HarmonyOS SDK (API 9)DevEco Studio (3.1.1 Release)Node.js (16.19.1) 开发IDE下载 官方下载链接 配置 nodejs 这里帮…...
Jmeter+ant,ant安装与配置
1.ant含义 ant:Ant翻译过来是蚂蚁的意思,在我们做接口测试的时候,是可以用来做JMeter接口测试生成测试报告的工具 2.ant下载 下载地址:Apache Ant - Ant Manual Distributions download中选择ant 下载安装最新版zip文件 3.…...
【MySQL基础】MySQL基础操作三
文章目录 🍉1.联合查询🥝笛卡尔积 🍉2.内连接🥝查询单个数据🥝查询多个数据 🍉3.外连接🍉4.自连接🍉5.合并查询 🍉1.联合查询 🥝笛卡尔积 实际开发中往往数…...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...
深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向
在人工智能技术呈指数级发展的当下,大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性,吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型,成为释放其巨大潜力的关键所在&…...
论文阅读:Matting by Generation
今天介绍一篇关于 matting 抠图的文章,抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法,已经有很多的工作和这个任务相关。这两年 diffusion 模型很火,大家又开始用 diffusion 模型做各种 CV 任务了&am…...
Matlab实现任意伪彩色图像可视化显示
Matlab实现任意伪彩色图像可视化显示 1、灰度原始图像2、RGB彩色原始图像 在科研研究中,如何展示好看的实验结果图像非常重要!!! 1、灰度原始图像 灰度图像每个像素点只有一个数值,代表该点的亮度(或…...
