pcm数据编码成为aac格式文件(可以在酷狗播放)

pcm数据编码成为aac格式文件(可以在酷狗播放)

关于其中的aac adts格式可以参考:AAC ADTS格式分析

main.c


#include <stdio.h>
#include <stdlib.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>//生成adts头部信息
static void make_adts_header(AVCodecContext* ctx, uint8_t* adts_header, int aac_length)
{//采样率索引uint8_t freq_idx = 0;switch (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 和 bodyadts_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;
}static int encode(AVCodecContext* ctx, AVFrame* frame, AVPacket* pkt, FILE* outFile)
{int ret;//发送一帧进行编码ret = avcodec_send_frame(ctx, frame);if(ret < 0){fprintf(stderr, "avcodec_send_frame failed! errorcode : %d\n", ret);char buf[128] = {0};av_strerror(ret, buf, 128);printf("---------%s\n", buf);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, "avcodec_receive_packet failed! errorcode : %d\n", ret);return -1;}//aac adts 头部信息uint8_t aac_header[7];make_adts_header(ctx, aac_header, pkt->size);size_t len = 0;//写出头部信息len = fwrite(aac_header, 1, 7, outFile);if(len != 7){fprintf(stderr, "fwrite aac_header failed!\n");return -1;}//写出aac数据len = fwrite(pkt->data, 1, pkt->size, outFile);if(len != pkt->size){fprintf(stderr, "fwrite aac data failed!\n");return -1;}}return -1;
}#define USE_CODEC_NAME 1
int main()
{printf("Hello Audio Encodeer!\n");FILE* infile = NULL;FILE* outfile = NULL;const AVCodec* codec = NULL;AVCodecContext* codec_ctx = NULL;AVFrame* frame = NULL;AVPacket* pkt = NULL;int ret = 0;//注意://   输入的pcm文件的采样点格式必须要与相应编码器支持的格式匹配才可以的,//   否则在avcodec_send_frame时就有可能出错。//   aac这个编码器就是要求格式:float, planar
#if USE_CODEC_NAMEchar* codec_name = "aac";
#elsechar* codec_name = "";
#endifchar* in_pcm_file = "test.pcm";char* out_aac_file = "out_test.aac";enum AVCodecID code_id = AV_CODEC_ID_AAC;//如果有指定的编码器就根据名字查找if(codec_name && strlen(codec_name)){codec = avcodec_find_encoder_by_name(codec_name);}else{//否则根据ID查找是在编码器链表中找的第一个匹配code_id的编码器codec = avcodec_find_encoder(code_id);}//如果没有找到编码器就是没有安装这个编码器if(!codec){fprintf(stderr, "avcodec_find_encoder failed!\n");return 0;}//分配编码器上下文codec_ctx = avcodec_alloc_context3(codec);if(!codec_ctx){fprintf(stderr, "avcodec_alloc_context3 failed!\n");return 0;}codec_ctx->codec_id = code_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;//采样率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){//aac 编码器 : 只支持AV_SAMPLE_FMT_FLTP这一种格式codec_ctx->sample_fmt = AV_SAMPLE_FMT_FLTP;//float, planar}else{sprintf(stderr, "codec->name failed!\n");return 0;}printf("use codec name :%s\n", codec_name);printf("bit rate : %ldkbps\n", codec_ctx->bit_rate / 1024);printf("sample_rate : %d\n", codec_ctx->sample_rate);printf("sample_fmt : %s\n", av_get_sample_fmt_name(codec_ctx->sample_fmt));printf("channels : %d\n", codec_ctx->channels);if(avcodec_open2(codec_ctx, codec, NULL) < 0){fprintf(stderr, "avcodec_open2 failed!\n");return 0;}//每个音频帧在单个通道下的采样数,只有音频这个参数才有效(在调用avcodec_open2()后就有效了)printf("frame_size : %d\n", codec_ctx->frame_size);//打开输入输出文件infile = fopen(in_pcm_file, "rb");if(!infile){fprintf(stderr, "fopen(in_pcm_file) failed!\n");return 0;}outfile = fopen(out_aac_file, "wb");if(!outfile){fprintf(stderr, "fopen(out_aac_file) failed!\n");return 0;}//分配AVPacket 本身结构的内存pkt = av_packet_alloc();if(!pkt){fprintf(stderr, "av_packet_alloc() failed!\n");return 0;}//分配AVFrame本身结构的内存frame = av_frame_alloc();if(!frame){fprintf(stderr, "av_frame_alloc() failed!\n");return 0;}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);//通道数printf("frame nb_samples : %d\n", frame->nb_samples);printf("frame format : %d \n", frame->format);printf("frame channel_layout : %d\n", frame->channel_layout);//计算一帧的数据长度(字节数量)// av_get_bytes_per_sample(frame->format) : 一个采样点占用的字节数// 比如:AV_SAMPLE_FMT_S16  = 两个字节//      AV_SAMPLE_FMT_FLTP = 四个字节// frame->channels : 有几个通道// frame->nb_samples : 单个通道的一帧的采样数int frame_bytes = av_get_bytes_per_sample(frame->format) * frame->channels * frame->nb_samples;printf("frame_bytes : %d\n", frame_bytes);uint8_t* pcm_buf = (uint8_t*)malloc(frame_bytes);if(!pcm_buf){printf("pcm_buf malloc failed!\n");return 0;}uint8_t* pcm_temp_buf = (uint8_t*)malloc(frame_bytes);if(!pcm_temp_buf){printf("pcm_temp_buf malloc failed!\n");return 0;}int64_t pts = 0;while (1){memset(pcm_buf, 0, frame_bytes);size_t read_byte = fread(pcm_buf, 1, frame_bytes, infile);if(read_byte <= 0){sprintf(stderr, "read infile end!\n");break;}//将读取到的数据填充到frame,会根据不同输的不同参数填充到frame->data,frame->linesizeret = av_samples_fill_arrays(frame->data, frame->linesize,pcm_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){sprintf(stderr, "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("aac encoder end!\n");return 0;}

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

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

相关文章

Python---实验九

1、使用标准库urllib爬取“http://news.pdsu.edu.cn/info/1005/31269.htm”平顶山学院新闻网上的图片&#xff0c;要求:保存到F盘pic目录中&#xff0c;文件名称命名规则为“本人姓名” “_图片编号”&#xff0c;如姓名为张三的第一张图片命名为“张三_1.jpg”。 from re imp…

Request.Url学习(转)

原文地址&#xff1a;http://www.cnblogs.com/jame-peng1028/articles/1274207.html?login1#commentform 网址&#xff1a;http://localhost:1897/News/Press/Content.aspx/123?id1#tocRequest.ApplicationPath/Request.PhysicalPathD:\Projects\Solution\web\News\Press\Con…

32接上拉5v_51单片机P0口上拉电阻的选择

作为I/O口输出的时候时&#xff0c;输出低电平为0 输出高电平为高组态(并非5V&#xff0c;相当于悬空状态&#xff0c;也就是说P0 口不能真正的输出高电平)。给所接的负载提供电流&#xff0c;因此必须接(一电阻连接到VCC)&#xff0c;由电源通过这个上拉电阻给负载提供电流。P…

[转载]FPGA/CPLD重要设计思想及工程应用(时序及同步设计)

来源&#xff1a;http://www.eetop.cn/blog/html/11/317611-13412.html 数字电路中,时钟是整个电路最重要、最特殊的信号。 第一, 系统内大部分器件的动作都是在时钟的跳变沿上进行, 这就要求时钟信号时延差要非常小, 否则就可能造成时序逻辑状态出错. 第二, 时钟信号通常是系统…

duration java_Java Duration类| ofMinutes()方法与示例

duration javaDuration Class of Minutes()方法 (Duration Class ofMinutes() method) ofMinutes() method is available in java.time package. ofMinutes()方法在java.time包中可用。 ofMinutes() method is used to represent the given minutes value in this Duration. of…

实验五 图形设计

每复制一个方法都要绑定Paint事件 一、创建Windows窗体应用程序&#xff0c;要求如下&#xff1a;&#xff08;源代码运行界面&#xff0c;缺少任一项为0分&#xff0c;源代码只需粘贴绘制图形代码所在的方法&#xff0c;不用粘贴太多&#xff09; 例如: &#xff08;1&…

yuv编码成h264格式写成文件

yuv编码成h264格式写成文件 &#xff08;使用ffmpeg 编码yuv420p编码成h264格式&#xff09; #include <stdio.h> #include <stdlib.h> #include <stdint.h>#include <libavcodec/avcodec.h> #include <libavutil/time.h> #include <libavut…

c++ stl队列初始化_声明,初始化和访问向量| C ++ STL

c stl队列初始化Here, we have to declare, initialize and access a vector in C STL. 在这里&#xff0c;我们必须声明&#xff0c;初始化和访问C STL中的向量。 向量声明 (Vector declaration) Syntax: 句法&#xff1a; vector<data_type> vector_name;Since, vec…

ADO.NET与SQL Server数据库的交互

7.3.1 使用SqlConnection对象连接数据库 例如&#xff1a;建立与SQL Server数据库的连接。 string connstring"Data Sourceservername;uidusername;pwdpassword;Initial Catalogdbname";SqlConnection connnew SqlConnection(connstring);conn.Open(); 例如&#xf…

nsis 修改exe执行权限

通过修改注册表的方式&#xff0c;修改exe的执行权限。&#xff0c;以下例子是使用管理员运行。 ;添加admin权限 SectionWriteRegStr HKCU "SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers" "$INSTDIR\spp.exe" "RUNASADMIN&qu…

linux ftp日志_linux学习笔记(一)——Linux分区和目录结构

linux学习笔记&#xff08;一&#xff09;——Linux分区和目录结构安装Linux时&#xff0c;手动挂载分区的情况下&#xff0c;/ 和 swap 是必须要挂载的&#xff0c;其他/home、/boot 等可以根据需要自行挂载。一般来说&#xff0c;简单的话&#xff0c;建议挂载三个分区&#…

C#通过VS连接MySQL数据库实现增删改查基本操作

创建一个数据库wsq 里面有一张beyondyanyu表 表里面有id(int)、names(varchar)、count(int)、passwords(varchar) 数据可以自己添 1、导入MySQL引用&#xff0c;你需要从官网或者其他地方下载&#xff0c;私聊我也可以 using MySql.Data.MySqlClient; 2、创建MySqlConnection对…

使用ffmpeg的filter处理yuv数据包括split filter(分流)、crop filter(裁剪)、vflip filter(垂直向上的翻转)、overlay filter(合成)

使用ffmpeg的filter处理yuv数据包括split filter(分流)、crop filter(裁剪)、vflip filter(垂直向上的翻转)、overlay filter(合成) #include <stdio.h>#include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libavfilter/avfil…

vc++ 6.0 堆栈_在C ++中使用链接列表实现堆栈

vc 6.0 堆栈To implement a stack using a linked list, basically we need to implement the push() and pop() operations of a stack using linked list. 要使用链接列表实现堆栈 &#xff0c;基本上&#xff0c;我们需要使用链接列表实现堆栈的push()和pop()操作。 Exampl…

烟雨小书店

烟雨小书店演示视频 源码

协议地址结构_TCP/IP 协议 讲解

计算机网络体系结构分层太厉害了&#xff0c;终于有人能把TCP/IP 协议讲的明明白白了计算机网络体系结构分层不难看出&#xff0c;TCP/IP 与 OSI 在分层模块上稍有区别。OSI 参考模型注重“通信协议必要的功能是什么”&#xff0c;而 TCP/IP 则更强调“在计算机上实现协议应该开…

ffmpeg进行混音,将两路音频pcm数据合成一路输出

ffmpeg进行混音&#xff0c;将两路音频pcm数据合成一路输出 audiomixer.h #ifndef AUDIOMIXER_H #define AUDIOMIXER_H#include <map> #include <mutex> #include <cstdio> #include <cstdint> #include <string> #include <memory>exter…

python sep函数_Python中带有print()函数的sep参数

python sep函数sep parameter stands for separator, it uses with the print() function to specify the separator between the arguments. sep参数代表分隔符&#xff0c;它与print()函数一起使用以指定参数之间的分隔符。 The default value is space i.e. if we dont us…

关于 MySQL 主从复制的配置(转)

来源&#xff1a;http://www.oschina.net/bbs/thread/10388设置Mysql的主从设置很重要&#xff0c;有如下几点用处&#xff1a;1 做备份机器&#xff0c;一旦主服务器崩溃&#xff0c;可以直接启用从服务器作为主服务器2 可以直接锁定从服务器的表只读&#xff0c;然后做备份数…

Silverlight 同域WCF免跨域文件

在sl3使用wcf时常常会因为sl中调用了不同域的wcf服务而导至调用服务失败&#xff0c;记得在很久以前sl当是只支持同域的访问&#xff0c;那么让我有一个想法&#xff0c;就是在sl引用时可以动态地取得当前sl所在的域&#xff0c;而wcf服务也必须同时部署到这个域下边&#xff0…