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;}

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

  1. 基于FFmpeg的音频编码(PCM数据编码成AAC android)

    概述 在Android上实现录音,并利用 FFmpeg将PCM数据编码成AAC. 详细 代码下载:http://www.demodashi.com/demo/10512.html 之前做的一个demo ...

  2. 【强烈推荐】音频文件免费批量一键格式转换好工具——酷狗音乐

    简介: 最近买了一个U盘,想把偶像JAY的歌曲拷贝到U盘里面,放到车里听,类似车载U盘.但是我的歌曲格式是无损FLAC格式的,车载系统对FLAC格式的音乐兼容性不好,一首歌没听多久就解析失败放下一首了 ...

  3. android酷狗缓存目录,酷狗缓存的歌曲在哪个文件夹_酷狗音乐缓存的歌曲在电脑哪个目录-win7之家...

    酷狗是一款很流行的音乐播放软件,当我们在听歌曲的时候,默认会缓存到文件夹中,方便下次没有网络的时候可以继续听这首歌,有些用户想要知道酷狗缓存的歌曲在哪个文件夹,我们可以从主界面中进入即可找到,接下来给 ...

  4. 【开源项目】基于FFmpeg的PCM数据编码为AAC

    /* * 一笑奈何 * cn-yixiaonaihe.blog.csdn.net */#include <iostream> #include <thread> extern ...

  5. MJPEG+PCM合成AVI视频格式文件

    前段时间将Webcam的MJPEG获得了,也将MJPEG通过硬件解码显示出来了,现在要做的是将MJPEG数据合成视频文件.想到最简单的视频格式就是微软的AVI了,首先我们要对AVI的结构有些认识,下面 ...

  6. php silk文件转换pcm,微信语音silk格式文件转换处理记录

    @(随笔记录)[微信语音|silk|mp3|wav] 日期:2018年08月01日 环境:MacBook Pro,macOS High Sierra 10.13.5(17F77) 引言: 奶奶八十多了 ...

  7. 自己动手写类似酷狗播放器(5)_文件的保存和读取

    对于播放器,我们希望在打开的时候,播放列表存有上一次的歌曲,不必每次去添加,就是通过文件的操作实现的. 这里要实现两个: 1.在播放器打开的时候,能自动加载上一次的歌曲信息进入Listbox,并且更新 ...

  8. 音频编解码·实战篇(1)PCM转至AAC(AAC编码)

    音频编解码·实战篇(1)PCM转至AAC(AAC编码) 作者:柳大·Poechant 博客:blog.csdn.net/poechant 邮箱:zhongchao.ustc@gmail.com 日期: ...

  9. AAC文件解码成PCM格式文件

    上一篇写到PCM格式文件编码成AAC格式文件,这一步的原因是有利于传输.可以将PCM文件做了很大的压缩力度,使得包变得更小,便于传输.我使用播放器播放了AAC文件听到的是音速明显变快了,声音也变得尖锐 ...

  10. pcm编码为aac/MP3格式ffmpeg(八)

    前言 pcm音频是未压缩的数据,占空间,在存储或者传输时一般都会选择先进行有损压缩(比如aac,MP3等等).pcm音频数据在文件存储时一般都按照planner格式存储,例如: 声道1声道2声道3.. ...

最新文章

  1. thinkphp的控制器包含在Url中时注意区分大小写
  2. Advanced Installer 制作.NetWeb部署安装包
  3. java读取ACCESS数据库的简单示例
  4. 双绞线传输距离多长_网线数据传输最大距离是多少米
  5. python多级字典嵌套_python – 如何拆分字符串并形成多级嵌套字典?
  6. 【error】深度优先搜索TypeError: unhashable type: ‘list‘
  7. 中国历史上影响最大的10首诗
  8. 【通用权限管理】角色的分类管理,角色-用户组-职位职务-系统角色的设计上的迷惑也解开...
  9. 尚硅谷JVM笔记(宋红康主讲)
  10. LineageOS源码定制手机系统
  11. 电源层和地线层完整性规则_射频电路设计实例以及一些经常遇见的问题
  12. 常用电压电流转换原理图
  13. [datawhale_5]图像分割二值化
  14. 服务器2008系统提权工具,Windows下提权辅助工具Windows-Exploit-Suggester
  15. win10触摸板手势教程
  16. LINK : fatal error LNK1181: 无法打开输入文件“xx.lib”(SpaHBridge.lib)
  17. 大前端-HTML-标签
  18. 订单表的字段类型 mysql_Mysql数据库下订单表如何设计?
  19. nmap系统版本扫描
  20. 【毕业设计】基于树莓派的指纹识别打卡系统 - 单片机 物联网

热门文章

  1. ucl计算机学院位置,2017伦敦大学学院设施及地理位置介绍
  2. 谷歌浏览器翻译插件的安装与使用
  3. 关于spark-evn.sh的配置(里面有worker的设置)
  4. C# 实现蓝牙检测及蓝牙设备信息获取代码
  5. 阿里云ecs服务器买完后可以更换操作系统么?
  6. 百度飞桨“万有引力”2022首站落地苏州,全面启动中小企业赋能计划
  7. 剑指Offer-22反转链表
  8. Visio 导出图片时字符间距错乱
  9. 【Python数据分析学习实例】篮球运动位置分析
  10. 免费天气api 真正可用