当前位置:网站首页>【音视频开发系列】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. */
边栏推荐
猜你喜欢
随机推荐
安全漏洞是如何被发现的?
数据库实体类对应daoimpl,基础的增删改查。
使用cef离屏渲染技术实现在线教育课件和webrtc视频回放融合录制
并发概念基础:线程安全与线程间通信
调用时序错误导致webrtc无法建立链接
Pfsense漏洞复现(CVE-2021-41282)
枚举和联合(自定义类型)-C语言
win10下mediasoup搭建过程中的一些坑记录
基于语音识别的QT设计的csgo互动类视频游戏
Arduino之ESP8266编程学习总结体会
【HIT-SC-MEMO1】哈工大2022软件构造 复习笔记1
Fabric v1.1 environment construction
华硕飞行堡垒系列无线网经常显示“无法连接网络” || 一打开游戏就断网
file editor
JUC锁框架——初识AQS
线程池原理
JUC并发容器——跳表
2022在 Go (Golang) 中使用微服务的系统课程
最全的最详细的指针讲解(C语言)
位段-C语言









