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

[+]
  1. VoiceEngine Codec数据结构
  2. 参数详细说明
    1. 查看VoiceEngine支持的所有Codec信息示例代码
    2. 初始化VoiceEngine Codec示例代码


1、VoiceEngine Codec数据结构

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

  1. struct CodecInst  
  2. {  
  3.     int pltype;      //payload type负载类型   
  4.     char plname[32]; //payload name负载名称,32个字符表示   
  5.     int plfreq;      //payload frequence负载频率   
  6.     int pacsize;     //packet size包大小   
  7.     int channels;    //声道   
  8.     int rate;        //速率或自适应   
  9. };  
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定义

  1. // Checks if the payload type is in the valid range.   
  2. bool ACMCodecDB::ValidPayloadType(int payload_type) {  
  3.   if ((payload_type < 0) || (payload_type > 127)) {  
  4.     return false;  
  5.   }  
  6.   return true;  
  7. }  
// 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定义


  1. ACMGenericCodec* ACMCodecDB::CreateCodecInstance(const CodecInst* codec_inst) {  
  2.   // All we have support for right now.   
  3.   if (!STR_CASE_CMP(codec_inst->plname, "ISAC")) {  
  4. #if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))   
  5.     return new ACMISAC(kISAC);  
  6. #endif   
  7.   } else if (!STR_CASE_CMP(codec_inst->plname, "PCMU")) {  
  8.     return new ACMPCMU(kPCMU);  
  9.   } else if (!STR_CASE_CMP(codec_inst->plname, "PCMA")) {  
  10.     return new ACMPCMA(kPCMA);  
  11.   } else if (!STR_CASE_CMP(codec_inst->plname, "ILBC")) {  
  12. #ifdef WEBRTC_CODEC_ILBC   
  13.     return new ACMILBC(kILBC);  
  14. #endif   
  15.   } else if (!STR_CASE_CMP(codec_inst->plname, "AMR")) {  
  16. #ifdef WEBRTC_CODEC_AMR   
  17.     return new ACMAMR(kGSMAMR);  
  18. #endif   
  19.   } else if (!STR_CASE_CMP(codec_inst->plname, "AMR-WB")) {  
  20. #ifdef WEBRTC_CODEC_AMRWB   
  21.     return new ACMAMRwb(kGSMAMRWB);  
  22. #endif   
  23.   } else if (!STR_CASE_CMP(codec_inst->plname, "G722")) {  
  24. #ifdef WEBRTC_CODEC_G722   
  25.     return new ACMG722(kG722);  
  26. #endif   
  27.   } else if (!STR_CASE_CMP(codec_inst->plname, "G7221")) {  
  28.     switch (codec_inst->plfreq) {  
  29.       case 16000: {  
  30. #ifdef WEBRTC_CODEC_G722_1   
  31.         int codec_id;  
  32.         switch (codec_inst->rate) {  
  33.           case 16000 : {  
  34.             codec_id = kG722_1_16;  
  35.             break;  
  36.           }  
  37.           case 24000 : {  
  38.             codec_id = kG722_1_24;  
  39.             break;  
  40.           }  
  41.           case 32000 : {  
  42.             codec_id = kG722_1_32;  
  43.             break;  
  44.           }  
  45.           default: {  
  46.             return NULL;  
  47.           }  
  48.           return new ACMG722_1(codec_id);  
  49.         }  
  50. #endif   
  51.       }  
  52.       case 32000: {  
  53. #ifdef WEBRTC_CODEC_G722_1C   
  54.         int codec_id;  
  55.         switch (codec_inst->rate) {  
  56.           case 24000 : {  
  57.             codec_id = kG722_1C_24;  
  58.             break;  
  59.           }  
  60.           case 32000 : {  
  61.             codec_id = kG722_1C_32;  
  62.             break;  
  63.           }  
  64.           case 48000 : {  
  65.             codec_id = kG722_1C_48;  
  66.             break;  
  67.           }  
  68.           default: {  
  69.             return NULL;  
  70.           }  
  71.           return new ACMG722_1C(codec_id);  
  72.         }  
  73. #endif   
  74.       }  
  75.     }  
  76.   } else if (!STR_CASE_CMP(codec_inst->plname, "CN")) {  
  77.     // For CN we need to check sampling frequency to know what codec to create.   
  78.     int codec_id;  
  79.     switch (codec_inst->plfreq) {  
  80.       case 8000: {  
  81.         codec_id = kCNNB;  
  82.         break;  
  83.       }  
  84.       case 16000: {  
  85.         codec_id = kCNWB;  
  86.         break;  
  87.       }  
  88.       case 32000: {  
  89.         codec_id = kCNSWB;  
  90.         break;  
  91.       }  
  92.       default: {  
  93.         return NULL;  
  94.       }  
  95.     }  
  96.     return new ACMCNG(codec_id);  
  97.   } else if (!STR_CASE_CMP(codec_inst->plname, "G729")) {  
  98. #ifdef WEBRTC_CODEC_G729   
  99.     return new ACMG729(kG729);  
  100. #endif   
  101.   } else if (!STR_CASE_CMP(codec_inst->plname, "G7291")) {  
  102. #ifdef WEBRTC_CODEC_G729_1   
  103.     return new ACMG729_1(kG729_1);  
  104. #endif   
  105.   } else if (!STR_CASE_CMP(codec_inst->plname, "speex")) {  
  106. #ifdef WEBRTC_CODEC_SPEEX   
  107.     int codec_id;  
  108.     switch (codec_inst->plfreq) {  
  109.       case 8000: {  
  110.         codec_id = kSPEEX8;  
  111.         break;  
  112.       }  
  113.       case 16000: {  
  114.         codec_id = kSPEEX16;  
  115.         break;  
  116.       }  
  117.       default: {  
  118.         return NULL;  
  119.       }  
  120.     }  
  121.     return new ACMSPEEX(codec_id);  
  122. #endif   
  123.   } else if (!STR_CASE_CMP(codec_inst->plname, "CN")) {  
  124.     // For CN we need to check sampling frequency to know what codec to create.   
  125.     int codec_id;  
  126.     switch (codec_inst->plfreq) {  
  127.       case 8000: {  
  128.         codec_id = kCNNB;  
  129.         break;  
  130.       }  
  131.       case 16000: {  
  132.         codec_id = kCNWB;  
  133.         break;  
  134.       }  
  135.       case 32000: {  
  136.         codec_id = kCNSWB;  
  137.         break;  
  138.       }  
  139.       default: {  
  140.         return NULL;  
  141.       }  
  142.     }  
  143.     return new ACMCNG(codec_id);  
  144.   } else if (!STR_CASE_CMP(codec_inst->plname, "L16")) {  
  145. #ifdef WEBRTC_CODEC_PCM16   
  146.     // For L16 we need to check sampling frequency to know what codec to create.   
  147.     int codec_id;  
  148.     switch (codec_inst->plfreq) {  
  149.       case 8000: {  
  150.         codec_id = kPCM16B;  
  151.         break;  
  152.       }  
  153.       case 16000: {  
  154.         codec_id =kPCM16Bwb;  
  155.         break;  
  156.       }  
  157.       case 32000: {  
  158.         codec_id = kPCM16Bswb32kHz;  
  159.         break;  
  160.       }  
  161.       default: {  
  162.         return NULL;  
  163.       }  
  164.     }  
  165.     return new ACMPCM16B(codec_id);  
  166. #endif   
  167.   } else if (!STR_CASE_CMP(codec_inst->plname, "telephone-event")) {  
  168. #ifdef WEBRTC_CODEC_AVT   
  169.     return new ACMDTMFPlayout(kAVT);  
  170. #endif   
  171.   } else if (!STR_CASE_CMP(codec_inst->plname, "red")) {  
  172. #ifdef WEBRTC_CODEC_RED   
  173.     return new ACMRED(kRED);  
  174. #endif   
  175.   }  
  176.   return NULL;  
  177. }  
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定义);

  1. //负载频率值   
  2. enum PayloadFrequencies  
  3. {  
  4.     kFreq8000Hz  = 8000,  
  5.     kFreq16000Hz = 16000,  
  6.     kFreq32000Hz = 32000  
  7. };  
//负载频率值
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信息示例代码

  1. //列出(获得)引擎支持的所有编解码器信息   
  2. //支持平台:Windows, Mac OS X, Linux   
  3.   
  4. #include "voe_base.h"   
  5. #include "voe_codec.h"   
  6.   
  7. VoiceEngine* ve = VoiceEngine::Create();  
  8. VoECodec* codec = VoECodec::GetInterface(ve);  
  9.   
  10. for (int = 0; i < codec->NumOfCodecs(); i++)  
  11.   
  12. {  
  13.   
  14.    CodecInst cinst;  
  15.   
  16.    codec->GetCodec(i, cinst);  
  17.   
  18.    DISPLAY_CODEC_INFO(i, cinst);  
  19.   
  20. }  
  21.   
  22.   // 释放sub-API   
  23.   codec->Release();  
  24.   
  25.   //删除引擎   
  26.   VoiceEngine::Delete(ve);  
//列出(获得)引擎支持的所有编解码器信息
//支持平台: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示例代码

  1. //初始化VoiceEngine Codec示例代码   
  2. //支持平台:Windows, Mac OS X, Linux   
  3.   
  4. #include "voe_codec.h"   
  5.   
  6. CodecInst cinst;  
  7.   
  8. //初始化iSAC编解码器参数   
  9. strcpy(cinst.plname, "ISAC");  
  10.   
  11. cinst.plfreq   = 16000; // iSAC宽带模式取样频率   
  12. cinst.pltype   = 103;   
  13. cinst.pacsize  = 480;   //使用30ms packet size,480kbps   
  14. cinst.channels = 1;     // 单声道   
  15. cinst.rate     = -1;    // 信道自适应模式   
  16. //初始化完成   
  17.   
  18. //在ID为0的channel激活已初始化的iSAC   
  19. codec->SetSendCodec(0, cinst);  
//初始化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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值