1、VoiceEngine Codec數據結構
WebRTC中,用一個結構體struct CodecInst表示特定的音頻編解碼器對象:
- struct CodecInst
- {
- int pltype; //payload type負載類型
- char plname[32]; //payload name負載名稱,32個字符表示
- int plfreq; //payload frequence負載頻率
- int pacsize; //packet size包大小
- int channels; //聲道
- int rate; //速率或自適應
- };
參數詳細說明:
1、 pltype範圍在1~126之間纔是有效值;
pltype的值是否有效可以通過調用下面ValidPayloadType(int payload_type)方法來判斷,在...\src\modules\audio_coding\main\source\acm_codec_database.cc定義
- // Checks if the payload type is in the valid range.
- bool ACMCodecDB::ValidPayloadType(int payload_type) {
- if ((payload_type < 0) || (payload_type > 127)) {
- return false;
- }
- return true;
- }
2、 plname是編解碼器的名稱,可能的值在CreateCodecInstance已定義,如WebRTC默認的"ISAC"
VoiceEngine支持多個音頻編解碼器,具體支持的編解碼器在CreateCodecInstance(const CodecInst* codec_inst)定義,比如ISAC\PCMU\PCMA\ILBC\AMR等等,在...\src\modules\audio_coding\main\source\acm_codec_database.cc定義
- ACMGenericCodec* ACMCodecDB::CreateCodecInstance(const CodecInst* codec_inst) {
- // All we have support for right now.
- if (!STR_CASE_CMP(codec_inst->plname, "ISAC")) {
- #if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
- return new ACMISAC(kISAC);
- #endif
- } else if (!STR_CASE_CMP(codec_inst->plname, "PCMU")) {
- return new ACMPCMU(kPCMU);
- } else if (!STR_CASE_CMP(codec_inst->plname, "PCMA")) {
- return new ACMPCMA(kPCMA);
- } else if (!STR_CASE_CMP(codec_inst->plname, "ILBC")) {
- #ifdef WEBRTC_CODEC_ILBC
- return new ACMILBC(kILBC);
- #endif
- } else if (!STR_CASE_CMP(codec_inst->plname, "AMR")) {
- #ifdef WEBRTC_CODEC_AMR
- return new ACMAMR(kGSMAMR);
- #endif
- } else if (!STR_CASE_CMP(codec_inst->plname, "AMR-WB")) {
- #ifdef WEBRTC_CODEC_AMRWB
- return new ACMAMRwb(kGSMAMRWB);
- #endif
- } else if (!STR_CASE_CMP(codec_inst->plname, "G722")) {
- #ifdef WEBRTC_CODEC_G722
- return new ACMG722(kG722);
- #endif
- } else if (!STR_CASE_CMP(codec_inst->plname, "G7221")) {
- switch (codec_inst->plfreq) {
- case 16000: {
- #ifdef WEBRTC_CODEC_G722_1
- int codec_id;
- switch (codec_inst->rate) {
- case 16000 : {
- codec_id = kG722_1_16;
- break;
- }
- case 24000 : {
- codec_id = kG722_1_24;
- break;
- }
- case 32000 : {
- codec_id = kG722_1_32;
- break;
- }
- default: {
- return NULL;
- }
- return new ACMG722_1(codec_id);
- }
- #endif
- }
- case 32000: {
- #ifdef WEBRTC_CODEC_G722_1C
- int codec_id;
- switch (codec_inst->rate) {
- case 24000 : {
- codec_id = kG722_1C_24;
- break;
- }
- case 32000 : {
- codec_id = kG722_1C_32;
- break;
- }
- case 48000 : {
- codec_id = kG722_1C_48;
- break;
- }
- default: {
- return NULL;
- }
- return new ACMG722_1C(codec_id);
- }
- #endif
- }
- }
- } else if (!STR_CASE_CMP(codec_inst->plname, "CN")) {
- // For CN we need to check sampling frequency to know what codec to create.
- int codec_id;
- switch (codec_inst->plfreq) {
- case 8000: {
- codec_id = kCNNB;
- break;
- }
- case 16000: {
- codec_id = kCNWB;
- break;
- }
- case 32000: {
- codec_id = kCNSWB;
- break;
- }
- default: {
- return NULL;
- }
- }
- return new ACMCNG(codec_id);
- } else if (!STR_CASE_CMP(codec_inst->plname, "G729")) {
- #ifdef WEBRTC_CODEC_G729
- return new ACMG729(kG729);
- #endif
- } else if (!STR_CASE_CMP(codec_inst->plname, "G7291")) {
- #ifdef WEBRTC_CODEC_G729_1
- return new ACMG729_1(kG729_1);
- #endif
- } else if (!STR_CASE_CMP(codec_inst->plname, "speex")) {
- #ifdef WEBRTC_CODEC_SPEEX
- int codec_id;
- switch (codec_inst->plfreq) {
- case 8000: {
- codec_id = kSPEEX8;
- break;
- }
- case 16000: {
- codec_id = kSPEEX16;
- break;
- }
- default: {
- return NULL;
- }
- }
- return new ACMSPEEX(codec_id);
- #endif
- } else if (!STR_CASE_CMP(codec_inst->plname, "CN")) {
- // For CN we need to check sampling frequency to know what codec to create.
- int codec_id;
- switch (codec_inst->plfreq) {
- case 8000: {
- codec_id = kCNNB;
- break;
- }
- case 16000: {
- codec_id = kCNWB;
- break;
- }
- case 32000: {
- codec_id = kCNSWB;
- break;
- }
- default: {
- return NULL;
- }
- }
- return new ACMCNG(codec_id);
- } else if (!STR_CASE_CMP(codec_inst->plname, "L16")) {
- #ifdef WEBRTC_CODEC_PCM16
- // For L16 we need to check sampling frequency to know what codec to create.
- int codec_id;
- switch (codec_inst->plfreq) {
- case 8000: {
- codec_id = kPCM16B;
- break;
- }
- case 16000: {
- codec_id =kPCM16Bwb;
- break;
- }
- case 32000: {
- codec_id = kPCM16Bswb32kHz;
- break;
- }
- default: {
- return NULL;
- }
- }
- return new ACMPCM16B(codec_id);
- #endif
- } else if (!STR_CASE_CMP(codec_inst->plname, "telephone-event")) {
- #ifdef WEBRTC_CODEC_AVT
- return new ACMDTMFPlayout(kAVT);
- #endif
- } else if (!STR_CASE_CMP(codec_inst->plname, "red")) {
- #ifdef WEBRTC_CODEC_RED
- return new ACMRED(kRED);
- #endif
- }
- return NULL;
- }
3、 plfreq一般取如下值(在common_types.h定義);
- //負載頻率值
- enum PayloadFrequencies
- {
- kFreq8000Hz = 8000,
- kFreq16000Hz = 16000,
- kFreq32000Hz = 32000
- };
4、 pacsize取值是與plfreq有關係的,單位爲kbps,下面是計算公式
計算公式如下:
如果:plfreq = 16000(單位爲hz)
如果我需要30ms(毫秒)的packet size
那麼pacsize = (plfreq *30) /1000 = 480kbps;
也即是:要得到k ms的packet size,則可計算出
pacsize =( plfreq * k) / 1000
而如果plfreq = 32000;20ms的packet size,則pacsize = 640;
5、 channels取值
channels = 1 表示單聲道
channels = 2 表示立體聲道
注意:channels = -1時,表示此時只支持單聲道模式
6、 rate取值,單位是bps
一般取rate = 16000,32000,48000這些16000整數倍的值,即16kbps,32kbps,48kpbs
注意:當rate = -1時,表示此時啓動自適應信道速率
2、查看VoiceEngine支持的所有Codec信息示例代碼
- //列出(獲得)引擎支持的所有編解碼器信息
- //支持平臺:Windows, Mac OS X, Linux
- #include "voe_base.h"
- #include "voe_codec.h"
- VoiceEngine* ve = VoiceEngine::Create();
- VoECodec* codec = VoECodec::GetInterface(ve);
- for (int = 0; i < codec->NumOfCodecs(); i++)
- {
- CodecInst cinst;
- codec->GetCodec(i, cinst);
- DISPLAY_CODEC_INFO(i, cinst);
- }
- // 釋放sub-API
- codec->Release();
- //刪除引擎
- VoiceEngine::Delete(ve);
3、初始化VoiceEngine Codec示例代碼
- //初始化VoiceEngine Codec示例代碼
- //支持平臺:Windows, Mac OS X, Linux
- #include "voe_codec.h"
- CodecInst cinst;
- //初始化iSAC編解碼器參數
- strcpy(cinst.plname, "ISAC");
- cinst.plfreq = 16000; // iSAC寬帶模式取樣頻率
- cinst.pltype = 103;
- cinst.pacsize = 480; //使用30ms packet size,480kbps
- cinst.channels = 1; // 單聲道
- cinst.rate = -1; // 信道自適應模式
- //初始化完成
- //在ID爲0的channel激活已初始化的iSAC
- codec->SetSendCodec(0, cinst);