专注网站平台推广公司,台山网页设计培训,一个网站seo做哪些工作,iis中的网站启动不了目录 一RV1126多线程获取音频编码AAC码流的流程
1.1AI模块的初始化并使能
1.2AENC模块的初始化
1.3绑定AI模块和AENC模块
1.4多线程获取每一帧AAC码流
1.5每个AAC码流添加ADTSHeader头部
1.6写入具体每一帧AAC的…目录 一RV1126多线程获取音频编码AAC码流的流程
1.1AI模块的初始化并使能
1.2AENC模块的初始化
1.3绑定AI模块和AENC模块
1.4多线程获取每一帧AAC码流
1.5每个AAC码流添加ADTSHeader头部
1.6写入具体每一帧AAC的ES码流 二代码实战 一RV1126多线程获取音频编码AAC码流的流程 上面是RV1126多线程获取AAC码流的流程分为六步AI模块的初始化并使能、AENC模块的初始化、绑定AI模块和AENC模块、创建多线程获取AAC码流、向每个AAC码流添加ADTSHeader头部(这个是重点)、写入具体每一帧AAC的ES码流。 1.1AI模块的初始化并使能
AI模块的初始化实际上就是对AI_CHN_ATTR_S的参数进行设置、然后调用RK_MPI_AI_SetChnAttr设置AI模块并使能RK_MPI_AI_EnableChn伪代码如下
AI_CHN_ATTR_S ai_chn_s;
ai_chn_s.pcAudioNode AUDIO_PATH;
ai_chn_s.u32Channels 2;
ai_chn_s.u32NbSamples 1024;
ai_chn_s.u32SampleRate 48000;
ai_chn_s.enAiLayout AI_LAYOUT_NORMAL;
ai_chn_s.enSampleFormat RK_SAMPLE_FMT_S16;
ret RK_MPI_AI_SetChnAttr(AI_CHN, ai_chn_s);
if(ret)
{ printf(RK_MPI_AI_SetChnAttr Failed...\n);
} ret RK_MPI_AI_EnableChn(AI_CHN);
if(ret)
{ printf(RK_MPI_AI_EnableChn Failed...\n);
} 1.2AENC模块的初始化
AENC模块的初始化实际上就是对AI_CHN_ATTR_S的参数进行设置、然后调用RK_MPI_AENC_CreateChn设置AENC模块伪代码如下
AENC_CHN_ATTR_S aenc_attr;
aenc_attr.enCodecType RK_CODEC_TYPE_AAC;
aenc_attr.u32Bitrate 64000;
aenc_attr.u32Quality 1;
aenc_attr.stAencAAC.u32Channels 2;
aenc_attr.stAencAAC.u32SampleRate 48000;
ret RK_MPI_AENC_CreateChn(AENC_CHN, aenc_attr);
if (ret)
{ printf(Create AENC[0] failed! ret%d\n, ret); return -1; }else{ printf(Create AENC[0] success!\n);
}
1.3绑定AI模块和AENC模块
分别创建两个MPP_CHN_S结构体分别是AI模块的MPP_CHN_S和AENC模块的MPP_CHN_S创建完成之后则用RK_MPI_SYS_Bind对两个模块进行绑定
MPP_CHN_S ai_mpp_chn_s;
ai_mpp_chn_s.enModId RK_ID_AI;
ai_mpp_chn_s.s32ChnId 0; MPP_CHN_S aenc_mpp_chn_s;
aenc_mpp_chn_s.enModId RK_ID_AENC;
aenc_mpp_chn_s.s32ChnId 0;
ret RK_MPI_SYS_Bind(ai_mpp_chn_s, aenc_mpp_chn_s);
if (ret) { printf(RK_MPI_SYS_Bind Failed....\n); }else{ printf(RK_MPI_SYS_Bind Success....\n);
} 1.4多线程获取每一帧AAC码流
开启一个线程去采集每一帧AENC模块的数据使用的API是RK_MPI_SYS_GetMediaBuffer 模块ID是RK_ID_AENC通道号ID是AENC创建的通道ID号。这里需要注意的是要进行两层写入。第一层要进行adts header头部的写入第二层则需要进行adts es流的写入
....................................................
While(1)
{ mb RK_MPI_SYS_GetMediaBuffer(RK_ID_AENC, AENC_CHN, -1); if (!mb) { printf(Get Aenc_Buffer break...\n); break; } ................................... fwrite(aac_header, 1, 7, aac_file); //对每一帧AAC码流写入adts_header头部 fwrite(RK_MPI_MB_GetPtr(mb), 1, RK_MPI_MB_GetSize(mb), aac_file); //写入每一帧AAC的ES码流
} ....................................................... 1.5每个AAC码流添加ADTSHeader头部
在写入AACES码流前需要对其进行ADTS Header的封装adts header头部分为adts_fixed_header和adts_variable_header。在对其写入的时候需要把这两个头部都一并写到码流上面。下面就是封装的具体方法。 typedef struct AacFreqIdx_
{ RK_S32 u32SmpRate; RK_U8 u8FreqIdx;
} AacFreqIdx; AacFreqIdx AacFreqIdxTbl[13] {{96000, 0}, {88200, 1}, {64000, 2}, {48000, 3}, {44100, 4}, {32000, 5}, {24000, 6}, {22050, 7}, {16000, 8}, {12000, 9}, {11025, 10}, {8000, 11}, {7350, 12}};
static void GetAdtsHeader(RK_U8 *pu8AdtsHdr, RK_S32 u32SmpleRate, RK_U8 u8ChannelRK_U32 u32DataLen)
{ RK_U8 u8FreqIdx 0; for (int i 0; i 13; i) { if (u32SmlpRate AacFreqIdxTbl[i].u32SmpRate) { u8FreqIdx AacFreqIdxTbl[i].u8FreqIdx; break; } } RK_U32 u32PacketLen u32DataLen 7; pu8AdtsHdr[0] 0xFF; //主要是写入syncword同步字节的前8位 pu8AdtsHdr[1] 0xF1; //主要是写入syncword同步字节的后4位,并且设置ID号、layer、protection_absent pu8AdtsHdr[2] ((AAC_PROFILE_LOW) 6) (u8FreqIdx 2) (u8Channel 2); //设置音频profile、sample_rate_index、声道数 pu8AdtsHdr[3] (((u8Channel 3) 6) (u32PacketLen 11)); //设置声道数original_copyhomecopyright_identification_bit、copyright_identification_start、aac_frame_length
pu8AdtsHdr[4] ((u32PacketLen 0x7FF) 3); //设置aac_frame_lengthadts_buffer_fullness pu8AdtsHdr[5] (((u32PacketLen 7) 5) 0x1F);//设置adts_buffer_fullness number_of_raw_data_blocks_in_frame pu8AdtsHdr[6] 0xFC; //设置 number_of_raw_data_blocks_in_frame
}
上面这个方法需要传入四个参数分别是
第一个参数pu8AdtsHdr需要处理输出的字符串
第二个参数u32SampleRate音频的采样率(根据音频采样率去查找对应的采样率索引这里的索引是AacFreqIdx)
第三个参数u8Channel音频通道数
第四个参数u32DataLen每一帧aac码流的长度(这里需要注意的是在写入AAC码流的时候需要把每个AAC长度7因为头部是adts的头部是7个字节)
设置完成之后就要对每个码流进行7个字节头部的写入。
fwrite(aac_header, 1, 7, aac_file); //对每一帧AAC码流写入adts_header头部 1.6写入具体每一帧AAC的ES码流
在写入AAC头部之后就可以写入每一帧具体的AAC的ES码流
..................................................
fwrite(RK_MPI_MB_GetPtr(mb), 1, RK_MPI_MB_GetSize(mb), aac_file); //写入每一帧AAC的ES码流 二代码实战
#include assert.h
#include fcntl.h
#include getopt.h
#include pthread.h
#include signal.h
#include stdbool.h
#include stdio.h
#include stdlib.h
#include time.h
#include unistd.h#include include/rkmedia/rkmedia_api.h
#include include/rkmedia/rkmedia_buffer.h
#include include/rkmedia/rkmedia_common.h
#include rkmedia_api.h
#define AUDIO_PATH default
#define AI_CHN 0
#define AENC_CHN 0#define AAC_PROFILE_LOW 1typedef struct AacFreqIdx_
{RK_S32 u32SampleRate;RK_U8 u8FreqIdx;
} AacFreqIdx;AacFreqIdx AacFreqIdxTbl[13] {{96000, 0}, {88200, 1}, {64000, 2}, {48000, 3}, {44100, 4}, {32000, 5}, {24000, 6}, {22050, 7}, {16000, 8}, {12000, 9}, {11025, 10}, {8000, 11}, {7350, 12}};static void GetAdtsHeader(RK_U8 *pu8AdtsHdr, RK_S32 u32SmpleRate, RK_U8 u8Channel,RK_U32 u32DataLen)
{RK_U8 u8FreqIdx 0;for (int i 0; i 13; i){if (u32SmpleRate AacFreqIdxTbl[i].u32SampleRate){u8FreqIdx AacFreqIdxTbl[i].u8FreqIdx;break;}}RK_U32 u32PacketLen u32DataLen 7;pu8AdtsHdr[0] 0xFF; // 主要是写入syncword同步字节的前8位pu8AdtsHdr[1] 0xF1; // 主要是写入syncword同步字节的后4位,并且设置ID号、layer、protection_absentpu8AdtsHdr[2] ((AAC_PROFILE_LOW) 6) (u8FreqIdx 2) (u8Channel 2); // 设置音频profile、sample_rate_index、声道数pu8AdtsHdr[3] (((u8Channel 3) 6) (u32PacketLen 11)); // 设置声道数original_copyhomecopyright_identification_bit、copyright_identification_start、aac_frame_lengthpu8AdtsHdr[4] ((u32PacketLen 0x7FF) 3); // 设置aac_frame_lengthadts_buffer_fullnesspu8AdtsHdr[5] (((u32PacketLen 7) 5) 0x1F); // 设置adts_buffer_fullness number_of_raw_data_blocks_in_framepu8AdtsHdr[6] 0xFC; // 设置 number_of_raw_data_blocks_in_frame
}void *get_audio_aenc_thread(void *args)
{pthread_detach(pthread_self());FILE *aac_file fopen(test_capture.aac, w);MEDIA_BUFFER mb NULL;RK_U8 aac_header[7];while (1){mb RK_MPI_SYS_GetMediaBuffer(RK_ID_AENC, AENC_CHN, -1);if (!mb){printf(RK_MPI_SYS_GetMediaBuffer break....\n);break;}printf(Get AAC_Buffer Success...\n);//获取AENC的AAC码流头部GetAdtsHeader(aac_header, 48000, 2, RK_MPI_MB_GetSize(mb));fwrite(aac_header, 1, 7, aac_file); //写入7个字节的头部fwrite(RK_MPI_MB_GetPtr(mb),1, RK_MPI_MB_GetSize(mb), aac_file); //写入AAC的ES码流RK_MPI_MB_ReleaseBuffer(mb);}
}int main(int argc, char *argv[])
{int ret;AI_CHN_ATTR_S ai_chn_s;ai_chn_s.pcAudioNode AUDIO_PATH; //音频采样路径ai_chn_s.u32SampleRate 48000; //音频采样率ai_chn_s.u32NbSamples 1024; //音频采样个数ai_chn_s.u32Channels 2; //音频采样通道ai_chn_s.enSampleFormat RK_SAMPLE_FMT_S16; //采样格式ai_chn_s.enAiLayout AI_LAYOUT_NORMAL; //采样布局ret RK_MPI_AI_SetChnAttr(AI_CHN, ai_chn_s); //设置AI属性if (ret){printf(RK_MPI_AI_SetChnAttr failed...\n);}else{printf(RK_MPI_AI_SetChnAttr success...\n);}ret RK_MPI_AI_EnableChn(AI_CHN); //使能AI模块if (ret){printf(RK_MPI_AI_EnableChn failed...\n);}else{printf(RK_MPI_AI_EnableChn success...\n);}AENC_CHN_ATTR_S aenc_chn_attrs; //AENCaenc_chn_attrs.enCodecType RK_CODEC_TYPE_AAC;//AENC模块的编码协议aenc_chn_attrs.u32Bitrate 64000; //音频编码比特率,64kbpsaenc_chn_attrs.u32Quality 1; //音频质量aenc_chn_attrs.stAencAAC.u32Channels 2; //音频通道数aenc_chn_attrs.stAencAAC.u32SampleRate 48000; //音频编码采样率这里要和AI模块的采样率一致ret RK_MPI_AENC_CreateChn(AENC_CHN, aenc_chn_attrs); //创建AENC模块if (ret){printf(RK_MPI_AENC_CreateChn failed....\n);}else{printf(RK_MPI_AENC_CreateChn success....\n);}MPP_CHN_S ai_mpp_chn_s;ai_mpp_chn_s.enModId RK_ID_AI;ai_mpp_chn_s.s32ChnId AI_CHN;MPP_CHN_S aenc_mpp_chn_s;aenc_mpp_chn_s.enModId RK_ID_AENC;aenc_mpp_chn_s.s32ChnId AENC_CHN;ret RK_MPI_SYS_Bind(ai_mpp_chn_s, aenc_mpp_chn_s); //绑定AI模块和AENC模块if (ret){printf(RK_MPI_SYS_Bind failed....\n);}else{printf(RK_MPI_SYS_Bind success....\n);}pthread_t pid;pthread_create(pid, NULL, get_audio_aenc_thread, NULL); //创建线程获取AENC码流while (1){sleep(2);}RK_MPI_SYS_UnBind(ai_mpp_chn_s, aenc_mpp_chn_s);RK_MPI_AENC_DestroyChn(AENC_CHN);RK_MPI_AI_DisableChn(AI_CHN);return 0;
}