FFmepg--音频编码流程--pcm编码为aac

文章目录

      • 基本概念
      • 流程
      • api
      • code(核心部分)

基本概念

从本地⽂件读取PCM数据进⾏AAC格式编码,然后将编码后的AAC数据存储到本地⽂件。

PCM样本格式:未经压缩的⾳频采样数据裸流
参数:

  • Sample Rate : 采样频率
  • Sample Size : 量化位数
  • Number of Channels : 通道个数
  • Sign : 表示样本数据是否是有符号位
  • Byte Ordering : 字节序
  • Integer Or Floating Point : 整形或浮点型

流程

请添加图片描述

api

  • avcodec_find_encoder:根据指定的AVCodecID查找注册的编码器
  • avcodec_alloc_context3:为AVCodecContext分配内存
  • avcodec_open2:打开编码器
  • avcodec_send_frame:将AVFrame⾮压缩数据给编码器
  • avcodec_receive_packet:获取到编码后的AVPacket数据
  • 设置AVFrame参数: format 、nb_samples、channel_layout、width/height
  • av_frame_get_buffer: 为⾳频或视频帧分配新的buffer
  • av_frame_make_writable:确保AVFrame是可写的
  • av_samples_fill_arrays 填充⾳频帧

code(核心部分)

static int encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt, FILE *output)
{int ret;/* send the frame for encoding */ret = avcodec_send_frame(ctx, frame);if (ret < 0) {fprintf(stderr, "Error sending the frame to the encoder\n");return -1;}while (ret >= 0) {ret = avcodec_receive_packet(ctx, pkt);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {return 0;} else if (ret < 0) {fprintf(stderr, "Error encoding audio frame\n");return -1;}size_t len = 0;if((ctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) {// 需要额外的adts header写入uint8_t aac_header[7];get_adts_header(ctx, aac_header, pkt->size);len = fwrite(aac_header, 1, 7, output);if(len != 7) {fprintf(stderr, "fwrite aac_header failed\n");return -1;}}len = fwrite(pkt->data, 1, pkt->size, output);if(len != pkt->size) {fprintf(stderr, "fwrite aac data failed\n");return -1;}}return -1;
}int main(int argc, char **argv)
{char *in_pcm_file = NULL;char *out_aac_file = NULL;FILE *infile = NULL;FILE *outfile = NULL;const AVCodec *codec = NULL;AVCodecContext *codec_ctx= NULL;AVFrame *frame = NULL;AVPacket *pkt = NULL;int ret = 0;int force_codec = 0;     // 强制使用指定的编码char *codec_name = NULL;in_pcm_file = argv[1];      // 输入PCM文件out_aac_file = argv[2];     // 输出的AAC文件enum AVCodecID codec_id = AV_CODEC_ID_AAC;codec_ctx = avcodec_alloc_context3(codec);if (!codec_ctx) {fprintf(stderr, "Could not allocate audio codec context\n");exit(1);}codec_ctx->codec_id = codec_id;codec_ctx->codec_type = AVMEDIA_TYPE_AUDIO;codec_ctx->bit_rate = 128*1024;codec_ctx->channel_layout = AV_CH_LAYOUT_STEREO;codec_ctx->sample_rate    = 48000; //48000;codec_ctx->channels       = av_get_channel_layout_nb_channels(codec_ctx->channel_layout);codec_ctx->profile = FF_PROFILE_AAC_LOW;    //if(strcmp(codec->name, "aac") == 0) {codec_ctx->sample_fmt = AV_SAMPLE_FMT_FLTP;} else if(strcmp(codec->name, "libfdk_aac") == 0) {codec_ctx->sample_fmt = AV_SAMPLE_FMT_S16;} else {codec_ctx->sample_fmt = AV_SAMPLE_FMT_FLTP;}/* 检测支持采样格式支持情况 */check_sample_fmt(codec, codec_ctx->sample_fmt);check_sample_rate(codec, codec_ctx->sample_rate);check_channel_layout(codec, codec_ctx->channel_layout);codec_ctx->flags = AV_CODEC_FLAG_GLOBAL_HEADER;  //ffmpeg默认的aac是不带adts,而fdk_aac默认带adts,这里我们强制不带/* 将编码器上下文和编码器进行关联 */avcodec_open2(codec_ctx, codec, NULL);// 打开输入和输出文件infile = fopen(in_pcm_file, "rb");outfile = fopen(out_aac_file, "wb");/* packet for holding encoded output */pkt = av_packet_alloc();/* frame containing input raw audio */frame = av_frame_alloc();// 设置frame参数frame->nb_samples     = codec_ctx->frame_size;frame->format         = codec_ctx->sample_fmt;frame->channel_layout = codec_ctx->channel_layout;frame->channels = av_get_channel_layout_nb_channels(frame->channel_layout);/* 为frame分配buffer */av_frame_get_buffer(frame, 0);// 计算出每一帧的数据 单个采样点的字节 * 通道数目 * 每帧采样点数量int frame_bytes = av_get_bytes_per_sample(frame->format) \* frame->channels \* frame->nb_samples;uint8_t *pcm_buf = (uint8_t *)malloc(frame_bytes);uint8_t *pcm_temp_buf = (uint8_t *)malloc(frame_bytes);int64_t pts = 0;printf("start enode\n");for (;;) {memset(pcm_buf, 0, frame_bytes);size_t read_bytes = fread(pcm_buf, 1, frame_bytes, infile);if(read_bytes <= 0) {printf("read file finish\n");break;}/* 确保该frame可写, 如果编码器内部保持了内存参考计数,则需要重新拷贝一个备份目的是新写入的数据和编码器保存的数据不能产生冲突*/av_frame_make_writable(frame);if(AV_SAMPLE_FMT_S16 == frame->format) {// 将读取到的PCM数据填充到frame去ret = av_samples_fill_arrays(frame->data, frame->linesize,pcm_buf, frame->channels,frame->nb_samples, frame->format, 0);} else {// 将读取到的PCM数据填充到frame去// 将本地的f32le packed模式的数据转为float palanarmemset(pcm_temp_buf, 0, frame_bytes);f32le_convert_to_fltp((float *)pcm_buf, (float *)pcm_temp_buf, frame->nb_samples);ret = av_samples_fill_arrays(frame->data, frame->linesize,pcm_temp_buf, frame->channels,frame->nb_samples, frame->format, 0);}// 设置ptspts += frame->nb_samples;frame->pts = pts;       // 使用采样率作为pts的单位,具体换算成秒 pts*1/采样率ret = encode(codec_ctx, frame, pkt, outfile);if(ret < 0) {printf("encode failed\n");break;}}/* 冲刷编码器 */encode(codec_ctx, NULL, pkt, outfile);// 关闭文件fclose(infile);fclose(outfile);// 释放内存if(pcm_buf) {free(pcm_buf);}if (pcm_temp_buf) {free(pcm_temp_buf);}av_frame_free(&frame);av_packet_free(&pkt);avcodec_free_context(&codec_ctx);printf("main finish, please enter Enter and exit\n");getchar();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/747968.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Matlab进阶绘图第45期—蝴蝶气泡图

蝴蝶气泡图是一种特殊的柱泡图/气泡柱状图。 蝴蝶图一般由左右两个水平柱状图组合而成&#xff0c;其形如蝴蝶展翅&#xff0c;可以很直观地展示两种数据直接的差异。 而蝴蝶气泡图则是在两个水平柱状图每根柱子外侧额外添加大小不同的气泡&#xff0c;用于表示另外一个数据变…

使用IDEA2023创建传统的JavaWeb项目并运行与调试

日期:2024-0312 作者:dusuanyun 文档环境说明: OS:Deepin 20.9(Linux) JDK: OpenJDK21 Tomcat:10.1.19 IDEA: 2023.3.4 (Ultimate Edition) 本文档默认已经安装JDK及环境变量的配置。 关键词…

单片机设计-超声波视力保护仪的设计与实现

项目介绍 技术&#xff1a;C语言、单片机等 本设计利用超声波技术检测眼睛与书本的距离&#xff0c;调整看书位置&#xff0c;通过光敏检测判断环境光线强度是否适合阅读&#xff0c;并通过定时器设定阅读时长&#xff0c;以此解决人们由于看书姿势的错误&#xff0c;阅读环境…

R语言数据挖掘-关联规则挖掘(1)

一、分析目的和数据集描述 要分析的数据是美国一区域的保险费支出的历史数据。保险费用数据表的每列分别为年龄、性别、体重指数、孩子数量、是否吸烟、所在区域、保险收费。 本文的主要目的是分析在年龄、性别、体重指数、孩子数量、是否吸烟、所在区域中这些因素中&#xf…

webpack5零基础入门-8清空前次打包文件与处理图标字体资源

1.配置output中的clean属性为true output: {/**文件输出路径 绝对路径*///__dirname 表示当前文件的文件夹目录path: path.resolve(__dirname, dist),//所有文件的输出目录/**文件名 */filename: static/js/dist.js,//入口文件输出文件名clean: true,//在打包前将path整个目录内…

SSM SpringBoot vue智能手机参数分析平台

SSM SpringBoot vue智能手机参数分析平台 系统功能 首页 图片轮播 新闻资讯 手机信息 手机百科 登录注册 个人中心 后台管理 登录注册 个人中心 手机百科管理 用户管理 手机对比管理 配置管理 新闻资讯管理 手机信息管理 对比信息管理 我的收藏管理 开发环境和技术 开发语言…

安卓国产百度网盘与国外云盘软件onedrive对比

我更愿意使用国外软件公司的产品&#xff0c;而不是使用国内百度等制作的流氓软件。使用这些国产软件让我不放心&#xff0c;他们占用我的设备大量空间&#xff0c;在我的设备上推送运行各种无用的垃圾功能。瞒着我&#xff0c;做一些我不知道的事情。 百度网盘安装包大小&…

爬虫 某物流

目标地址 url "https://api.jdl.com/aging/feeInquiryNewByJDL" 加密参数 ciphertext和data 搜关键字ciphertext跟着栈走 很明显的DES加密 window globalconst e require(jsencrypt); // const e require(JSEncrypt) // e r(775).JSEncrypt // const t requi…

《ARM汇编与逆向工程》读书心得与实战体验

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 &#x1f4d8; 一、引言 &#x1f4dd; 二、…

信雅纳网络测试的二次开发集成:XOA(Xena Open-Source Automation)开源自动化测试

目录 XOA是什么 XOA CLI XOA Python API ​XOA Python Test Suite/测试套件 XOA Converter Source Code XOA是什么 XOA&#xff08;Xena Open-Source Automation&#xff09;是一个开源的测试自动化框架&#xff0c;追求“高效、易用、灵活”的跨操作系统的开发框架。能…

android studio的布局没有提示之SDK不匹配

我新建了一个项目&#xff0c;然后突然发现布局没有提示了&#xff1a; 我看了下我的build.gradle 我直接修改compileSdkVersion为30就能正常使用了

电源常用通讯电路详解

数字电源的采样和PWM驱动电路原理&#xff0c;通过这些技术&#xff0c;数字电源可以在内部形成控制闭环。但是要实现电源的控制和管理&#xff0c;还是需要与数字控制核心建立通讯连接。本期将带领大家了解数字电源常用的通讯电路。 一、常用的通讯方式 在前面数字电源与模拟…

TCP的三次握手和4次挥手

一、首先讲一下TCP的由来 最开始&#xff0c;人们考虑到将网络信息的呼唤与回应进行规范&#xff0c;达成一种公认的协议&#xff0c;就好像没有交通规则的路口设定交通规则。 人们设计出完美的OSI协议&#xff0c;这个协议包含七个层次由下到上分别是&#xff1a; 物理层&…

数据结构知识点汇总(持续更新版)

数据结构 一、绪论 检测知识&#xff1a; 1.1基本概念 以前的计算机 弹道计算机 现如今 主要运用于非数值的计算 基本概念和术语 数据&#xff1a;是信息的载体&#xff0c;描述客观事物属性的值&#xff0c;字符以及所有能输入到计算机中并被计算机程序识别和处理的符号的…

如何搭建“Docker Registry私有仓库,在CentOS7”?

1、下载镜像Docker Registry docker pull registry:2.7.1 2、运行私有库Registry docker run -d -p 5000:5000 -v ${PWD}/registry:/var/lib/registry --restartalways --name registry registry:2.7.1 3、拉取镜像 docker pull busybox 4、打标签&#xff0c;修改IP&#x…

原创 | 一文读懂高斯过程

作者&#xff1a;贾恩东 本文约2700字&#xff0c;建议阅读9分钟 本文将使用通俗易懂的语言引导读者入门高斯过程。 高斯过程&#xff08;Gaussian Process&#xff09;是机器学习中一个相当基础的概念&#xff0c;本文中笔者将使用通俗的语言让读者入门高斯过程。 高斯过程&am…

Python之Web开发中级教程----创建Django子应用

Python之Web开发中级教程----创建Django子应用 基于上一个教程的Django项目&#xff08;可以先看上一集&#xff0c;链接如下&#xff1a;&#xff09; https://mp.csdn.net/mp_blog/creation/editor/136724897 2.创建子应用 python manager.py startapp book admin.py&…

FPGA静态时序分析与约束(三)、读懂vivado时序报告

系列文章目录 FPGA静态时序分析与约束&#xff08;一&#xff09;、理解亚稳态 FPGA静态时序分析与约束&#xff08;二&#xff09;、时序分析 文章目录 系列文章目录前言一、时序分析回顾二、打开vivado任意工程2.1 工程布局路由成功后&#xff0c;点击vivado左侧**IMPLEMENT…

Oracle 19c 傻瓜式安装

1.创建用户和组&#xff1a; /usr/sbin/groupadd -g 54321 oinstall /usr/sbin/groupadd -g 54322 dba /usr/sbin/groupadd -g 54323 oper /usr/sbin/useradd -u 54321 -g oinstall -G dba,oper oracle 2.给oracle设置密码 passwd oracle 3.关闭防火墙和selinux systemctl s…

❤ css布局篇

❤ css布局篇 一、基础布局 &#xff08;1&#xff09;居中布局 ① 文字居中 <div class"div1">测试文字居中</div> body {margin: 0;padding: 0;padding: 10%; } .div1 {width: 100px;height: 100px;background: cadetblue;text-align: center; }te…