音频编码流程 ----- PCM编码为AAC格式

文章目录

  • 1.音频编码流程
  • 2.编码函数API含义解释
  • 3.音频编码实战Demo PCM转AAC格式

1.音频编码流程

在这里插入图片描述

2.编码函数API含义解释

av_frame_make_writable 确保帧数据可写,尽可能避免数据复制.如果帧可写,则不执行任何操作,如果不可写,则分配新缓冲区并复制数据.返回: 成功时为 0,错误时为负 AVERROR.

av_samples_fill_arrays 这个函数就是将你输入的一帧数据写入AVFrame格式输出,便于后面编码send,recvice使用

3.音频编码实战Demo PCM转AAC格式

编码注意点:

  1. 编码器相关配置得设置正确,比如码率,采样率,声道,采样格式等
  2. 也要设置AVFrame的格式,主要是采样率,声道,采样格式
  3. 如果数据不是FLTP格式的花,需要转化为FLTP格式.
  4. PCM编码后的数据想要编码为AAC格式,得在前面加上adtsheader.
#ifndef MAINBACK_C
#define MAINBACK_C
#endif // MAINBACK_C
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <libavcodec/avcodec.h>
#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavutil/frame.h>
#include <libavutil/samplefmt.h>
#include <libavutil/opt.h>
void f32le_convert_to_fltp(float *f32le, float *fltp, int nb_samples) {float *fltp_l = fltp;   // 左通道float *fltp_r = fltp + nb_samples;   // 右通道for(int i = 0; i < nb_samples; i++) {fltp_l[i] = f32le[i*2];     // 0 1   - 2 3fltp_r[i] = f32le[i*2+1];   // 可以尝试注释左声道或者右声道听听声音}
}
static void get_adts_header(AVCodecContext *ctx, uint8_t *adts_header, int aac_length)
{uint8_t freq_idx = 0;    //0: 96000 Hz  3: 48000 Hz 4: 44100 Hzswitch (ctx->sample_rate) {case 96000: freq_idx = 0; break;case 88200: freq_idx = 1; break;case 64000: freq_idx = 2; break;case 48000: freq_idx = 3; break;case 44100: freq_idx = 4; break;case 32000: freq_idx = 5; break;case 24000: freq_idx = 6; break;case 22050: freq_idx = 7; break;case 16000: freq_idx = 8; break;case 12000: freq_idx = 9; break;case 11025: freq_idx = 10; break;case 8000: freq_idx = 11; break;case 7350: freq_idx = 12; break;default: freq_idx = 4; break;}uint8_t chanCfg = ctx->channels;uint32_t frame_length = aac_length + 7;adts_header[0] = 0xFF;adts_header[1] = 0xF1;adts_header[2] = ((ctx->profile) << 6) + (freq_idx << 2) + (chanCfg >> 2);adts_header[3] = (((chanCfg & 3) << 6) + (frame_length  >> 11));adts_header[4] = ((frame_length & 0x7FF) >> 3);adts_header[5] = (((frame_length & 7) << 5) + 0x1F);adts_header[6] = 0xFC;
}
int encode(AVCodecContext* codec_ctx,AVFrame* frame,AVPacket* pkt,FILE* out)
{int ret=0;ret = avcodec_send_frame(codec_ctx,frame);if(ret<0){printf("avcodec_send_frame failed\n");return ret;}while(1){ret=avcodec_receive_packet(codec_ctx,pkt);if(ret==AVERROR(EAGAIN)||ret==AVERROR(AVERROR_EOF))break;if(ret<0)return ret;if(codec_ctx->flags&AV_CODEC_FLAG_GLOBAL_HEADER){char header[7]={0};get_adts_header(codec_ctx,header,pkt->size);int size=fwrite(header,1,7,out);if(size!=7){printf("fwrite error\n");return 0;}}fwrite(pkt->data,1,pkt->size,out);}}
//编码流程  先初始化编码器,读取原始文件,send,recvice,写入
int main(int argc,char* argv[])
{if(argv<3){printf("argv<3\n");return -1;}char* pcm_path=argv[1];char* out_path=argv[2];FILE* pcm_file=fopen(pcm_path,"rb");FILE* out_file=fopen(out_path,"wb");AVCodec* codec=avcodec_find_encoder(AV_CODEC_ID_AAC);AVCodecContext* codec_ctx=avcodec_alloc_context3(codec);codec_ctx->bit_rate=100000;codec_ctx->channel_layout=AV_CH_LAYOUT_STEREO;codec_ctx->channels=av_get_channel_layout_nb_channels(codec_ctx->channel_layout);codec_ctx->sample_fmt=AV_SAMPLE_FMT_FLTP;
//    codec_ctx->codec_id=AV_CODEC_ID_AAC;
//    codec_ctx->codec_type=AVMEDIA_TYPE_AUDIO;codec_ctx->sample_rate=48000;codec_ctx->profile=FF_PROFILE_AAC_LOW;codec_ctx->flags|=AV_CODEC_FLAG_GLOBAL_HEADER;avcodec_open2(codec_ctx,codec,NULL);AVFrame* frame=av_frame_alloc();AVPacket* pkt=av_packet_alloc();
//    frame->channel_layout=codec_ctx->channel_layout;frame->channels=codec_ctx->channels;
//    frame->sample_rate=codec_ctx->sample_rate;frame->format=codec_ctx->sample_fmt;frame->nb_samples=codec_ctx->frame_size;av_frame_get_buffer(frame,0);//分配frame的buffint frame_bytes=av_get_bytes_per_sample(frame->format)*frame->channels*frame->nb_samples;uint8_t* pcm_buff=av_malloc(frame_bytes);memset(pcm_buff,0,frame_bytes);uint8_t *pcm_temp_buf = (uint8_t *)malloc(frame_bytes);memset(pcm_temp_buf,0,frame_bytes);int pts=0;int ret=0;while(1){int rsize=fread(pcm_buff,1,frame_bytes,pcm_file);ret = av_frame_make_writable(frame);if(ret != 0)printf("av_frame_make_writable failed, ret = %d\n", ret);f32le_convert_to_fltp(pcm_buff,pcm_temp_buf,frame->nb_samples);int need_size=av_samples_fill_arrays(frame->data,frame->linesize,pcm_temp_buf,frame->channels,frame->nb_samples,frame->format,0);if(rsize!=need_size)break;frame->pts=pts;pts+=1;printf("frame pts:%d\n",pts);encode(codec_ctx,frame,pkt,out_file);}encode(codec_ctx,NULL,pkt,out_file);return 0;
}

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

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

相关文章

UE5_ 地编_siki海岛

1.开启水插件 制作流体 2.开启大陆地形的插件

wsl 1和wsl 2在形式上的区别

完整的比较请参考&#xff1a; 比较 WSL 版本 | Microsoft Learn 如果是已经安装完成&#xff0c;但安装的是wsl &#xff0c;之后想由 wsl 1升级到wsl 2&#xff0c;请参考&#xff1a;WSL1升级至WSL2_wsl1升级wsl2_goldVitaminC的博客-CSDN博客 在形式上&#xff0c;wsl 1是…

Java 设计模式 随笔1 监听器/观察者

0. 不由自主&#xff0c;恍恍惚惚&#xff0c;又走回头路&#xff0c;再看一眼有过的幸福… 太棒了流沙!!! 0.1 引用 https://blog.csdn.net/majunzhu/article/details/100869562 ApplicationEvent事件机制源码分析 单机环境下优雅地使用事件驱动进行代码解耦 1. JDK 1.1 …

测试员如何突破自我的瓶颈?我有几点看法

前阵子我自己也对如何“突破瓶颈”思考过&#xff0c;我觉得“突破瓶颈”、“弥补短板”等等都大同小异&#xff0c;从古至今就是测试员们津津乐道的话题。我也对自己该如何“突破瓶颈”总结了几点&#xff0c;跟大家分享下&#xff1a; 1、“常立志、立长志”。“立志”就是目…

测试管理能力—如何带领一个快乐和成功的测试团队

目录 前言&#xff1a; 技巧# 1)业务知识和技术技能 技巧# 2)努力评估和有效的分配工作 技巧# 3)尽量不要超量提交 技巧# 4)沟通和人际交往能力 学习如何说“不”: 谈判技巧: 鼓励合作与发展: 您将看到两个好处: 向高层管理人员汇报和电子邮件交流: 团队会议: 给空间: 做第…

日撸java三百行day75-76

文章目录 说明通用BP神经网络1.通用神经网络2.代码理解2.1 FullAnn类2.2 forward函数2.3 backPropagation函数2.4 不同激活函数的对比结果 说明 闵老师的文章链接&#xff1a; 日撸 Java 三百行&#xff08;总述&#xff09;_minfanphd的博客-CSDN博客 自己也把手敲的代码放在…

大神都在用的4个AI绘画工具,记得收藏

AI绘画工具是一种利用人工智能辅助绘画创作的工具&#xff0c;它可以帮助设计师快速绘制高质量的艺术作品。本文列出了国内外4款免费的AI绘画工具&#xff0c;它们使用起来非常简单&#xff0c;而且创作效果非常不错&#xff0c;一起来看看吧&#xff01; 1.即时灵感 即时灵感…

uniapp电子签名以及竖屏签名后内容旋转90度变为横屏图片

用该插件挺不错的 电子签名插件地址 如果你一个页面要用多个该插件&#xff0c;就改成不同的cavas-id&#xff0c;修改插件源码 效果图 竖屏写 旋转成横屏图片 插件内 在拿到签名临时地址后的页面 <!-- 旋转图片canvas --> <canvas canvas-id"camCacnvs&quo…

Java设计模式之结构型-组合模式(UML类图+案例分析)

目录 一、基础概念 二、UML类图 三、角色分析 四、案例分析 1、基本实现 2、菜单遍历 五、总结 一、基础概念 组合模式&#xff08;Composite Pattern&#xff09;又叫部分-整体模式&#xff0c;它通过将对象组合成树形结构来表示“整体-部分”的层次关系&#xff0c…

el-form实现其中一个填写即可的校验

<el-formref"form":model"formData":rules"formRules"label-width"130px"><el-row :gutter"24"><el-col :span"12"><el-form-item label"司机姓名 :" prop"driverName"…

交叉编译paho带SSL

1.新建文件夹 /home/yiweijiao/woke_lab/paho 2.解压paho.mqtt.c到/home/yiweijiao/woke_lab/paho/paho.mqtt.c 3.新建文件夹/home/yiweijiao/woke_lab/paho/openssl_lib 将已经交叉编译好的openssl复制到这里 4.cd /home/yiweijiao/woke_lab/paho/paho.mqtt.c 新建文件夹…

文盘 Rust -- tokio 绑定 cpu 实践

tokio 是 rust 生态中流行的异步运行时框架。在实际生产中我们如果希望 tokio 应用程序与特定的 cpu core 绑定该怎么处理呢&#xff1f;这次我们来聊聊这个话题。 首先我们先写一段简单的多任务程序。 use tokio::runtime; pub fn main() {let rt runtime::Builder::new_mu…