您的位置:首页 > 理论基础 > 数据结构算法

WebRTC音视频引擎研究(2)--VoiceEngine音频编解码器数据结构以及参数设置

2015-04-09 17:42 543 查看
WebRTC技术交流群:234795279

1、VoiceEngine Codec数据结构

WebRTC中,用一个结构体struct CodecInst表示特定的音频编解码器对象:

[cpp] view
plaincopy

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定义

[cpp] view
plaincopy

// 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定义

[cpp] view
plaincopy

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定义);

[cpp] view
plaincopy

//负载频率值

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信息示例代码

[cpp] view
plaincopy

//列出(获得)引擎支持的所有编解码器信息

//支持平台: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示例代码

[cpp] view
plaincopy

//初始化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);

转载自:http://blog.csdn.net/temotemo/article/details/7531711
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐