zoukankan      html  css  js  c++  java
  • WebRTC音视频引擎研究(2)--VoiceEngine音频编解码器数据结构以及参数设置

    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. };  

    参数详细说明:

    1、 pltype范围在1~126之间才是有效值;

            pltype的值是否有效可以通过调用下面ValidPayloadType(int payload_type)方法来判断,在...srcmodulesaudio_codingmainsourceacm_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. }  



    2、 plname是编解码器的名称,可能的值在CreateCodecInstance已定义,如WebRTC默认的"ISAC"

            VoiceEngine支持多个音频编解码器,具体支持的编解码器在CreateCodecInstance(const CodecInst* codec_inst)定义,比如ISACPCMUPCMAILBCAMR等等,在...srcmodulesaudio_codingmainsourceacm_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. }  

    3、 plfreq一般取如下值(在common_types.h定义);

    1. //负载频率值  
    2. enum PayloadFrequencies  
    3. {  
    4.     kFreq8000Hz  = 8000,  
    5.     kFreq16000Hz = 16000,  
    6.     kFreq32000Hz = 32000  
    7. };  

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

    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);  
  • 相关阅读:
    day02【Collection、泛型】
    day11 【final、权限、内部类、引用类型】
    day10 【接口、多态】
    day09 【继承、super、this、抽象类】
    day08 【String类、static关键字、Arrays类、Math类】
    Java基本运算符
    Java非访问修饰符
    2020学习Java开发有前途吗?看看资深程序员怎么说
    两年Java后端开发,面试了几十家公司的面试分享
    五种方法创建java对象,你知道几种呢?
  • 原文地址:https://www.cnblogs.com/fuland/p/3654803.html
Copyright © 2011-2022 走看看