Faac 编码实时pcm流到aac流 并用mp4v2打包成mp4文件
来源:互联网 发布:郑淳元秋意浓 知乎 编辑:程序博客网 时间:2024/05/16 07:02
由于项目需要, 需要将g711实时音频流,转码成aac流, 最终生成MP4文件保存,
网上搜索了一番, 最后采用如下的方法
1, 采用g711库相关函数, 先将g711音频流,解码成pcm数据,
2,采用faac库, 将解码后的pcm数据,编码成aac 数据
3,采用mp4v2 将aac数据打包成mp4文件
网上下载了,开源的g711代码,和mp4v2-2.0.0
g711解码pcm 没什么好说的,很简单,
BYTEszPcmBuff[PCM_BUFFER_SIZE] = {0};//1024
intnPcmLen = g711a_decode( (short*)szPcmBuff, pBufferG711, nG711Len );
因为传送过来的g711音频流buf大小是 160个字节(nG711Len), 解码后的pcm大小为320所以定义的
PCM_BUFFER_SIZE= 320
关于AAC音频格式的理论知识参考以下这篇文章
AAC音频格式分析与解码
关于使用FAAC编码PCM数据为AAC,参考以下两篇文章
音频编解码·实战篇(1)PCM转至AAC(AAC编码)
Faac编码实时pcm流到aac流
我直接拷贝过来了一部分
首先调用 faacEncHandlehEncode r= faacEncOpen(samplerate,channels,& samplesInput,&maxBytesOutput);
1.打开aac编码引擎,创建aac编码句柄。
参数 samplerate 为要编码的音频pcm流的采样率,channels为要编码的音频pcm流的的频道数(原有的例子程序是从wav文件中读出这些信息),sampleInput在编码时要用到,意思是每次要编码的采样数,参数maxBytesOutput为编码时输出地最大字节数。
2.然后在设置一些编码参数,如
int version=MPEG4; //设置版本,录制MP4文件时要用MPEG4
intobjecttype=LOW; //编码类型
intmidside=1; //M/S编码
intusetns=DEFAULT_TNS; //瞬时噪声定形(temporalnoise shaping,TNS)滤波器
intshortctl=SHORTCTL_NORMAL;
intinputformat=FAAC_INPUT_16BIT; //输入数据类型
intoutputformat=RAW_STREAM; //录制MP4文件时,要用raw流。检验编码是否正确时可设
//置为adts传输流,把aac 流写入.aac文件中,如编码正确
//用千千静听就可以播放。
其他的参数可根据例子程序设置。
设置完参数后就调用faacEncSetConfiguration(hEncoder,aacFormat)设置编码参数。
3.如编码完的aac流要写入MP4文件时,要调用
faacEncGetDecoderSpecificInfo(hEncoder,&(ASC),&(ASCLength));//得到解码信息
//(mpeg4ip mp4 录制使用)
此函数支持MPEG4版本,得到的ASC 和ACSLength 数据在录制MP4(mpegip库)文件时用。
4.然后就是编码了,每次从实时的pcm音频队列中读出samplesInput* channels*(量化位数/8),
字节数的pcm数据。然后再把得到pcm流转变一下存储位数,
====================================================
这里补充说明一下,。
这里我用采样率为8000 单通道, 位深16 的音频为例
nSampleRate = 8000;
nChannal = 1;
m_nBitsPerSample = 16;
调用 faacEncOpen(nSampleRate, nChannal, &m_nInputSamples, &m_nMaxOutputBytes);
之后, 得到m_nInputSamples=1024; m_nMaxOutputBytes = 768;
计算得出 m_nMaxInputBytes = m_nInputSamples*bitsPerSample/8 ;
m_nMaxInputBytes = 2048;
也就是说在调用 faacEncEncode进行编码的时候,每次要解码m_nMaxInputBytes的PCM数据,类似帧的概念, 解码一帧PCM数据 输出的aac数据最大为m_nMaxOutputBytes, 你只需申请最大为m_nMaxInputBytes 的输出内存(m_pOutAACBuffer),交给faacEncEncode 就行了
intnRet =faacEncEncode(m_hEncoder, (int*)m_pbPCMBuffer,m_nInputSamples,m_pOutAACBuffer,m_nMaxOutputBytes);
根据faacEncEncode的返回值,从m_pOutAACBuffer中取出nRet个字节,就是编码后的aac数据,注意在调用faacEncEncode前几次返回值为0,不要惊讶, 这是因为FAAC内部有缓存Buff.
然后将从m_pOutAACBuffer中取出编码后的一帧数据,就可以调用mp4v2库的MP4WriteSample函数打包mp4文件了。
参考代码
bool Mp4Mutex::init( int nSampleRate, int nChannal, int bitsPerSample,char * pMp4File ){m_nSampleRate = nSampleRate;m_nAudioChannal = nChannal;m_nBitsPerSample = bitsPerSample;// init faacm_hEncoder = faacEncOpen( nSampleRate, nChannal, &m_nInputSamples, &m_nMaxOutputBytes);m_nMaxInputBytes=m_nInputSamples*bitsPerSample/8;m_pbPCMBuffer = new BYTE [m_nMaxInputBytes];m_pOutAACBuffer = new BYTE [m_nMaxOutputBytes];m_pTempBuffer = new BYTE [TEMP_BUFFER_SIZE];memset(m_pTempBuffer, 0 , TEMP_BUFFER_SIZE);// Get current encoding configurationfaacEncConfigurationPtr pConfiguration = faacEncGetCurrentConfiguration(m_hEncoder);if( !pConfiguration ){printf("GetCurrentConfiguration error!\n");return false;}//设置版本,录制MP4文件时要用MPEG4pConfiguration->version = MPEG4 ;pConfiguration->aacObjectType = LOW; //LC编码//输入数据类型pConfiguration->inputFormat = FAAC_INPUT_16BIT;// outputFormat (0 = Raw; 1 = ADTS)// 录制MP4文件时,要用raw流。检验编码是否正确时可设置为 adts传输流,pConfiguration->outputFormat= 1;//瞬时噪声定形(temporal noise shaping,TNS)滤波器pConfiguration->shortctl = SHORTCTL_NORMAL;pConfiguration->useTns=true;//pConfiguration->useLfe=false;pConfiguration->quantqual=100;pConfiguration->bandWidth=0;pConfiguration->bitRate=0;// Set encoding configurationfaacEncSetConfiguration( m_hEncoder, pConfiguration);return true;}
编码
void Mp4Mutex::StartWriteMp4(unsigned char * pBufferG711,int nG711Len){if ( G711_BUFFER_SIZE < nG711Len ){}BYTE szPcmBuff[PCM_BUFFER_SIZE] = {0};//1024int nPcmLen = g711a_decode( (short*)szPcmBuff, pBufferG711, nG711Len );memcpy(m_pTempBuffer+m_nTempPos, szPcmBuff ,nPcmLen ) ;m_nTempPos += nPcmLen;if ( m_nTempPos < m_nMaxInputBytes ){return ;}memcpy(m_pbPCMBuffer, m_pTempBuffer ,m_nMaxInputBytes ) ;char szTemp[2048]={0};int nLeft = m_nTempPos-m_nMaxInputBytes;memcpy( szTemp, (m_pTempBuffer+m_nMaxInputBytes), nLeft );memset(m_pTempBuffer, 0, TEMP_BUFFER_SIZE );memcpy( m_pTempBuffer, szTemp, nLeft );m_nTempPos -= m_nMaxInputBytes ;int nRet = faacEncEncode(m_hEncoder, (int*)m_pbPCMBuffer, m_nInputSamples, m_pOutAACBuffer, m_nMaxOutputBytes );if ( nRet <= 0 ){return ;}MP4WriteSample( m_Mp4File, m_AudioTrackId, (BYTE*)&m_pOutAACBuffer[7], nRet-7 , 1024, 0, true);}
这里上传了我用来测试的一个工程,一个例子可以下载
http://download.csdn.net/detail/machh/8101485
扫描下方二维码。关注 【音视频开发训练营】 获取更多有价值的技术文章
- Faac 编码实时pcm流到aac流 并用mp4v2打包成mp4文件
- Faac 编码实时pcm流到aac流
- Faac 编码实时pcm流到aac流
- Faac 编码实时pcm流到aac流
- 使用MP4V2开源库将AAC打包到MP4文件中
- Mp4v2实现h264+aac打包成Mp4视频文件
- Mp4v2实现h264+aac打包成Mp4视频文件
- Mp4v2实现h264+aac打包成Mp4视频文件
- 多媒体 Mp4v2实现h264+aac打包成Mp4视频文件
- Mp4v2实现h264+aac打包成Mp4视频文件
- Mp4v2实现h264+aac打包成Mp4视频文件
- Mp4v2实现h264+aac打包成Mp4视频文件
- 开源Faac实现PCM编码AAC
- Mp4V2 AAC/PCM 封装MP4 iOS 很容易,用FFmpeg也一样,直接写文件。
- android 实时PCM数据编码成AAC
- H264 AAC/PCM 到MP4容器
- android 实时PCM数据编码成AAC【转】
- FAAC转换PCM为AAC
- Android 4.1 Surface系统变化说明
- 母函数模板
- 第十周项目一:getcher函数
- loadrunner 测试下载文件的测试脚本
- 用Xmanager + SecureCRT 在Linux 下安装oracle 10g
- Faac 编码实时pcm流到aac流 并用mp4v2打包成mp4文件
- 汉诺塔问题递归算法分析
- websocket
- chef 安装过程中报错 ERROR: Errno::EHOSTUNREACH: No route to host - connect(2)
- Pro Android学习笔记(一四三):触摸屏(2):VelocityTracker
- Hibernate的evict方法和clear方法的区别
- 16进制转10进制
- EM算法浅解
- linux下如何在程序中调用shell命令