decode_audio.c 解读/decode_video.c 解读
----------------------------------------
date: 2022-04-01
author:hjjdebug
----------------------------------------
decode_audio.c 解读
----------------------------------------
decode_audio, 它能把一个音频编码文件解出成原始音频数据,并写到文件中.
原始音频数据怎样播放? 您可以用ffplay, 但要传递给它参数,见后.
下面演示了如何从文件中读取,分析和写入文件的过程.
1. pkt = av_packet_alloc(); //分配一个包
2. codec = avcodec_find_decoder(AV_CODEC_ID_AAC); //查找一种codec
3. c = avcodec_alloc_context3(codec); 为某codec 分配一个上下文
4. if (avcodec_open2(c, codec, NULL) < 0) ; // 打开codec
5. 打开输入文件和输出文件
f = fopen(filename, "rb");
outfile = fopen(outfilename, "wb");
6. if (!(decoded_frame = av_frame_alloc())) //分配一个frame
7. 读数据到缓存
data_size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);
AUDIO_INBUF_SIZE 可是20480, 缓存不小!
读到了20480数据,现在开始分析它.
8. parser = av_parser_init(codec->id); //初始化parser, 针对某种codec的parser
9. ret = av_parser_parse2(parser, codec_ctx, &pkt->data, &pkt->size,
data, data_size,
AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
输入参数:数据指针(data),数据大小(data_size)
输出参数:pkt->data, pkt->size //数据被分析到packet 中
其它参数:parser context, codec context, 均为输入参数.
返回值, 对aac 来讲返回固定的928 长度.
即每次分析928字节进入pkt,然后把data指针和data_size进行调整以便继续后续分析
10. decode(c, pkt, decoded_frame, outfile);
解码pkt 到decoded_frame 并写入outfile, 这是用户的代码了. 不过还是要调用ffmpeg 接口.
具体如下:
11. 解码过程,发送包,收获frame .
ret = avcodec_send_packet(dec_ctx, pkt);
ret = avcodec_receive_frame(dec_ctx, frame);
send_packet, receive_frame 将压缩包经codec 解开到 frame.
然后: 获取采样点的大小.(由sample format 得到)
data_size = av_get_bytes_per_sample(dec_ctx->sample_fmt);
将frame 解出的原始数据写到文件.
for (i = 0; i < frame->nb_samples; i++)
for (ch = 0; ch < dec_ctx->channels; ch++)
fwrite(frame->data[ch] + data_size*i, 1, data_size, outfile);
//frame 中包含几个channel的数据,由dec_ctx->channel 确定, 目前能支持到8个通道
//每个采用点的大小(data_size), 由采样格式确定 dec_ctx->sample_fmt
//而frame->nb_samples, 当然也是从dec_ctx中获取的,保存到frame 结构中了。
如此即可将解出的frame各channel数据交错写到输出文件中了.
12. 当缓冲的数据小于4096时,再从文件继续读数据塞满缓冲区, 直到data_size 消耗为0,解码完毕.
13 要想播放这个原始数据音频文件,需要记录下它的数据格式:
ret = get_format_from_sample_fmt(&fmt, sfmt))// 从sfmt 获取字符串format
sfmt 是源format, 是 dec_ctx->sample_fmt
ffplay -f f32le -ac 2 -ar 44100 Audio.data
f32le: aac 的采样格式 (sample_fmt)
44100: aac 的采样率 (sample_rate)
2 : aac 的采样通道数 (channels)
从此,你可以了解到音频解码的流程.
这里还要补充一点, decode在 avcodec_send_packet 之后, dec_ctx的信息才补充完整,channels,sample_rate 才有了值!
是的,这是因为 codec 本身并不知道有多少channels, sample_rate是多少,codec 只负责解码,它知道数据 pix的format,
但收到数据包后ctx就不一样了, ctx 会存储具体的数据流信息如channels,sample_rate等,就是所谓的流信息
decode_video.c 解读
----------------------------------------
相较decode_audio.c,
一致的地方都是: 用指定的codec 来打开codec_ctx.
具体为由codecID找到codec, 分配codec_ctx, 打开codec,初始化parser,
分配包,分配frame,打开输入文件.
分析一下不同的地方
1. 首先这个inbuf 的buffer size 只有4096, 而不是音频的20480
2. 没有打开输出文件.每一个frame 对应一个输出文件.
3. 从输入文件读入一次数据4096, 分析缓存中数据消耗4096,但可能并
不能构成一个pkt, pkt->size=0, 会继续读入数据,分析数据,直到pkt->size!=0.
哇!这一次一下子成了25709, 可见也是多个4096 供给的.
然后进行decode.
有可能把packet 发过去,并不能解出frame, 而是EAGAIN, 还需要继续供给packet
parser 分析每次消耗并不一定是4096, 它以能形成packet为准则.
构不成frame 也没问题,反正dec_ctx 会记录.
解出了frame, 由dec_ctx->frame_number 构成输出文件名,将frame 中的数据写入到文件.
数据要素是frame->data, frame->linesize,frame->width,frame-height.
frame->data 是8个指针, 传第一个就够了.
frame->linesize是8个整数,传第一个就够了.
然后打开一个文件,记录下xsize,ysize, 然后书写二进制数据,按行写.每次写一行.
补充:
问1:parser 读到一个packet, 此时packet中有什么?
答1: parser可能要经过若干次数据输入才能形成一个packet,此时只有packet->data,packet-size是有效的.
问2:解码是send_packet, receive_frame, frame->width,frmae->height是如何得到的?
答2: 发过去一个packet, 可能并不能形成一个有效的frame,此时会返回EAGAIN,如果得到了frame,
此时也会填充好frame->width,height参数及data,linesize参数等,称为已经解出了frame,
此时再看ctx, 相关的数据也已经填充好. 看起来一荣俱荣,一损俱损,是同时发生的。
decode_audio.c 解读/decode_video.c 解读相关推荐
- vins 解读_代码解读 | VINS 视觉前端
AI 人工智能 代码解读 | VINS 视觉前端 本文作者是计算机视觉life公众号成员蔡量力,由于格式问题部分内容显示可能有问题,更好的阅读体验,请查看原文链接:代码解读 | VINS 视觉前端 v ...
- vins 解读_VINS-mono详细解读
VINS-mono详细解读 极品巧克力 前言 Vins-mono是香港科技大学开源的一个VIO算法,https://github.com/HKUST-Aerial-Robotics/VINS-Mono ...
- EMANet:Expectation-Maximization Attention Networks for Semantic Segmentation论文解读和代码解读
官方项目地址:含论文和代码 来自北大才子 立夏之光的 ICCV Oral ,理论很漂亮.属于Non local方式 Updated on 2020.1.6 最近一直有人私信我,这个attention ...
- 【lidar】3D目标检测PointPillars:论文解读、代码解读、部署实现(2)
PointPillars部署:TensorRT推理实现,下载地址:添加链接描述 PointPillars 高度优化的点云目标检测网络PointPillars.主要通过tensorrt对网络推理段进行了 ...
- 【lidar】3D目标检测PointPillars:论文解读、代码解读、部署实现(1)
Abstract 点云中的目标检测是自动驾驶等机器人应用中的一个重要方面.在本文中,作者思考了将点云编码成适合下游检测pipeline的格式问题.最近的文献提出了两种类型的编码器:固定编码器往往更快, ...
- VINS-mono详细解读与实现
VINS-mono详细解读 VINS-mono详细解读 前言 Vins-mono是香港科技大学开源的一个VIO算法,https://github.com/HKUST-Aerial-Robotics/V ...
- mysql 4.1.10_Mysql4.1.10初级解读
Mysql4.1.10初级解读 ※※※※※※※※※※※※※※Mysql 初级解读 (所用版本:4.1.10)※※※※※※※※※※※※※※ 安装注意事项 在安装的过程中,请记好您的密码,这是将来登录my ...
- Nature子刊:微生物来源分析包SourceTracker——结果解读和使用教程
文章目录 SourceTracker有什么用? 软件简介 软件结果解读 原文解读 文章实战解读 软件安装 输入文件准备 实验设计 OTU表 代码中文解读 Reference 猜你喜欢 写在后面 前一阵 ...
- 【C 语言】指针 与 数组 ( 指针 | 数组 | 指针运算 | 数组访问方式 | 字符串 | 指针数组 | 数组指针 | 多维数组 | 多维指针 | 数组参数 | 函数指针 | 复杂指针解读)
相关文章链接 : 1.[嵌入式开发]C语言 指针数组 多维数组 2.[嵌入式开发]C语言 命令行参数 函数指针 gdb调试 3.[嵌入式开发]C语言 结构体相关 的 函数 指针 数组 4.[嵌入式开发 ...
最新文章
- Java中的实现马赛克效果以及灰度效果----整张图片
- java 对变量加锁_Java最全锁剖析:独享锁/共享锁+公平锁/非公平锁+乐观锁/悲观锁...
- hdu3786 Floyd或搜索 水题
- Python内置函数(44)——len
- minitab怎么算西格玛水平_西格玛和西格玛水平
- hexo本地博客的转移
- .读取excel表格(JAVA)
- python一共多少模块,python常见模块有哪些
- 视频直播app源码,可拖拽悬浮球
- 直播企业掀“冲击IPO”浪潮,为何老玩家成受益者?
- UE4 替换文件尝试解决 光照构建失败 Lighting build failed. Swarm failed to kick off
- Python站内文章精选大集合!
- Qt配置OpenCV环境变量
- 免费图床,看这一篇就够了!
- Android开发艺术探索完结篇——天道酬勤
- 436分复试被刷!山东大学软件学院
- Sprite Kit 动作系统
- 七宗罪也许每个人都有
- php7的安装方法,php7 iis安装方法详解(图文)
- 微搭低代码数据源新能力详解
热门文章
- 使用python输出所有汉字的拼音hàn-zì-pīn-yīn
- vb毕业设计——基于vb+VB.NET的媒体播放器设计与实现(毕业论文+程序源码)——媒体播放器
- 硕士发表SCI论文84篇遭质疑?!本人霸气回应:有无造假随便查!没有拼爹!...
- 22、Java——汽车租赁系统(对象+集合)
- 世界上最大的全可动射电望远镜在中国开工建设
- 用CSS样式完成作业
- Python零基础学习-开课吧
- 课得软件丨成都web前端培训班哪儿好?
- 【PHP】`异客塞尔`世界 与 神奇的字符串++
- 1985年的图灵奖获得者-Richard Manning Karp