当前位置:网站首页>【音视频开发系列】fdk_aac 之 PCM 转 AAC
【音视频开发系列】fdk_aac 之 PCM 转 AAC
2022-08-04 05:34:00 【_杜竞宁_】
fdkaac库将PCM封装为AAC
/* * auth : dujingning * date : 2022.03.03 * license : MIT */
#include <stdio.h>
#include <string.h>
#include "fdk-aac/aacenc_lib.h"
typedef struct parameterDict{
AACENC_PARAM param;
UINT value;
}Dict;
typedef struct AacContext {
HANDLE_AACENCODER hAacEncoder;
int inBufferIdentifier;
int inputbufElSizes;
#define readMaxLen 4096
int outputbufElSizes;
int outputIdentifier;
int outputBufferSize;
AACENC_BufDesc inputBufDesc;
AACENC_BufDesc outputBufDesc;
AACENC_InArgs inputArgs;
AACENC_OutArgs outputArgs;
}AacCtx;
int aacEncInit(AacCtx *ctx);
int aacEncEnd(AacCtx *ctx);
int aacEncEnd(AacCtx *ctx);
int aacEncInit(AacCtx *ctx){
if (!ctx)
return -1;
memset((void*)ctx, '\0', sizeof(AacCtx));
AACENC_ERROR AAC_ERR = AACENC_OK;
Dict m_Dict[] ={
{
AACENC_AOT, AOT_AAC_LC},
{
AACENC_SBR_MODE, AOT_NULL_OBJECT},
{
AACENC_SAMPLERATE, 44100},
{
AACENC_BITRATE, 44100*2*16},
{
AACENC_BITRATEMODE, 0},
{
AACENC_CHANNELMODE, MODE_2},
{
AACENC_TRANSMUX, TT_MP4_ADTS},
};
AAC_ERR = aacEncOpen( &ctx->hAacEncoder, 0x01, 0x00 );
if (ctx->hAacEncoder == NULL || AAC_ERR != AACENC_OK) {
printf("aacEncOpen ERROR\r\n");
return -1;
}
int i = 0, j = sizeof(m_Dict)/sizeof(Dict);
for ( i = 0; i < j; i++ ) {
AAC_ERR = aacEncoder_SetParam(ctx->hAacEncoder, m_Dict[i].param, m_Dict[i].value);
if ( AAC_ERR != AACENC_OK ){
aacEncEnd(ctx);
ctx->hAacEncoder = NULL;
printf("aacEncoder_SetParam ERROR %d\r\n", i);
return -1;
}
}
if (aacEncEncode(ctx->hAacEncoder, NULL, NULL, NULL, NULL) != AACENC_OK) {
aacEncEnd(ctx);
ctx->hAacEncoder = NULL;
printf("aacEncEncode test ERROR from aacEncInit\n");
return -1;
}
ctx->inBufferIdentifier = IN_AUDIO_DATA;
ctx->inputBufDesc.bufferIdentifiers = &ctx->inBufferIdentifier;
ctx->inputbufElSizes = 2;
ctx->inputBufDesc.bufElSizes = &ctx->inputbufElSizes;
ctx->outputbufElSizes = 1;
ctx->outputBufDesc.bufElSizes = &ctx->outputbufElSizes;
ctx->outputIdentifier = OUT_BITSTREAM_DATA;
ctx->outputBufDesc.bufferIdentifiers = &ctx->outputIdentifier;
ctx->outputBufferSize = readMaxLen;
ctx->outputBufDesc.bufSizes = (INT*)&ctx->outputBufferSize;
ctx->inputBufDesc.numBufs = 1;
ctx->outputBufDesc.numBufs = 1;
return 0;
}
int aacEncode(AacCtx *ctx, void *pPCMdata, unsigned int PCMdataSize, void *outputBuffer){
/* input buffer info */
ctx->inputBufDesc.bufs = &pPCMdata;
ctx->inputBufDesc.bufSizes = &PCMdataSize;
/* output buffer info */
ctx->outputBufDesc.bufs = &outputBuffer;
/* input arguments */
ctx->inputArgs.numInSamples = PCMdataSize/2;
/* output arguments */
memset((void*)&ctx->outputArgs, (int)'\0', sizeof(ctx->outputArgs));
/* encode */
if (aacEncEncode(ctx->hAacEncoder, &ctx->inputBufDesc, &ctx->outputBufDesc, &ctx->inputArgs, &ctx->outputArgs) != AACENC_OK){
printf("aacEncEncode AACENC CODE %d, output bytes : %d\r\n",ctx->outputArgs.numOutBytes);
return 0;
}
return ctx->outputArgs.numOutBytes;
}
int aacEncEnd(AacCtx *ctx){
if (!ctx || !ctx->hAacEncoder) {
return -1;
}
if (aacEncClose(&ctx->hAacEncoder) != AACENC_OK) {
return -1;
}
ctx->hAacEncoder = NULL;
return 0;
}
/* compile : gcc pcm2aac.c -std=c11 -I./include -L./lib -lfdk-aac -lm -o pcm2aac*/
int main(int argc, char *argv[])
{
AacCtx ctx = {
NULL };
if (aacEncInit(&ctx) != 0 || !ctx.hAacEncoder ){
printf("init Fail!\r\n");
}
unsigned char inputBuffer[readMaxLen] = {
0};
unsigned char outputBuffer[readMaxLen] = {
0};
FILE *inputFD = fopen("audio.pcm","r");
FILE *outputFD = fopen("audio_dj.aac","w");
if (inputFD == NULL || outputFD == NULL) {
printf("fail to open file\r\n");
return -1;
}
size_t readLen = 0;
do{
readLen = fread(inputBuffer, 1, readMaxLen, inputFD);
fwrite(outputBuffer, aacEncode(&ctx, inputBuffer, readLen, outputBuffer), 1, outputFD);
}while(readLen > 0);
fclose(inputFD);
fclose(outputFD);
aacEncEnd(&ctx);
return 0;
}
/* -rw-r--r-- 1 13919 197609 1764000 Mar 3 21:34 audio.pcm $ ./ffprobe -ar 44100 -ac 2 -f s16le -i audio.pcm Input #0, s16le, from 'audio.pcm': Duration: 00:00:10.00, bitrate: 1411 kb/s Stream #0:0: Audio: pcm_s16le, 44100 Hz, 2 channels, s16, 1411 kb/s PCM format: L R L R L R L R .... ↓ 2Byte | 1764000 Byte / ( 44100HZ * 2 channls * 2 Byte ) = 10秒 | 比特率:bps(bit per second,位/秒);kbps(通俗地讲就是每秒钟1000比特)作为单位。 比特率=采样率*采样声道数*采样位深 1411200 b/s = 44100*2*16 即 1411.2 kb/s */
/* see fdk-aac project of documentation/aacEncoder.pdf from github with https://github.com/mstorsjo/fdk-aac. 2.2 Calling Sequence 1. Call aacEncOpen() to allocate encoder instance with required configuration. 2. Call aacEncoder SetParam() for each parameter to be set. AOT, samplingrate, channelMode, bitrate and transport type are mandatory. 3. Call aacEncEncode() with NULL parameters to initialize encoder instance with present parameter set. 4. Call aacEncInfo() to retrieve a configuration data block to be transmitted out of band. This is required when using RFC3640 or RFC3016 like transport. 5. Encode input audio data in loop. 6. Call aacEncClose() and destroy encoder instance. */
边栏推荐
猜你喜欢
随机推荐
【HIT-SC-MEMO4】哈工大2022软件构造 复习笔记4
CMDB 腾讯云部分实现
Usage of SFTP
对渗透测试工程师来说,学历重要嘛?
win10下mediasoup搭建过程中的一些坑记录
Pfsense漏洞复现(CVE-2021-41282)
Uos统信系统 本地APT源配置
学好网络安全看这篇文章让你少走弯路
以太网 ARP
Uos统信系统 DISK(RAID+LVM)
EL expression
【C语言】数组名是什么
你要悄悄学网络安全,然后惊艳所有人
淘宝分布式文件系统存储(二)
一场聚会,转行渗透测试月薪13.5k,感谢那个女同学......
Socket编程详解
罗斯50分
Scheduler (Long-term,Short-term, Medium-term Scheduler) & Dispatcher
Visualization and Animation Technology (VR System)
第九篇 ApplicationContext初始化









