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

1、VoiceEngine Codec数据结构

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

 

[cpp] view plaincopy
  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)方法来判断,在...\src\modules\audio_coding\main\source\acm_codec_database.cc定义

 

[cpp] view plaincopy
  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)定义,比如ISAC\PCMU\PCMA\ILBC\AMR等等,在...\src\modules\audio_coding\main\source\acm_codec_database.cc定义

 

 

[cpp] view plaincopy
  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定义);

[cpp] view plaincopy
  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信息示例代码

[cpp] view plaincopy
  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示例代码

[cpp] view plaincopy
    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);  

转载于:https://www.cnblogs.com/fuland/p/3654803.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/407891.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.NET资源收集

.NET开发资源精华收集与共享 .Net General微软.Net中文主页 .NET Framework开发中心 微软.Net Framework中文产品支持中心 微软.Net Framework中文新闻组(Web) 微软VB.Net中文新闻组(Web) 博客园 .NET 2.0 专题 孟宪会之精彩世界 微软.NET俱乐部 MSDN中文网络广播 AspxBoy教程网…

小程序学习(2):vs code 安装插件

1. wechat-snippet 微信小程序代码辅助,代码片段自动完成 2. minapp 微信小程序标签、属性的智能补全&#xff08;同时支持原生小程序、mpvue 和 wepy 框架&#xff0c;并提供 snippets&#xff09; 需要输入<才会触发标签补全输入空格会触发对应标签的属性补全 3. wxapp-…

C++ 20 内存模型(一)

C 20 内存模型(一) 多线程的基础是优秀的内存模型 C20 内存模型: 高复杂性, 难以理解对多线程有更深入的理解 内存布局 位域 member_name成员名, width bit 宽度 struct bit_field_name {type member_name : width; };struct my_struct {char a;int b : 5; // 最大存储 …

char[]:strlen和sizeof的区别

C code: // char[]&#xff1a;strlen和sizeof的区别#include <stdio.h>#include <string.h>int main(int argc, char* argv[]){char str[] "Hello man";printf("str %s\nstrlen(str) %d\nsizeof(str) %d\n", str, strlen(str), sizeof(st…

讲话的技巧

名人的精神讲话&#xff08;有话则短&#xff0c;无话则免&#xff09;有人问美国第28任总统伍德罗.威尔逊,他准备一份10分钟的讲稿,得花多少时间?威尔逊答&#xff1a;“两星期。”“准备一份1小时的讲稿呢&#xff1f;”“一星期。”“两个小时的讲稿&#xff1f;”“不用准…

sql-C#-类型对应

bitbooltinyintbytesmallintshortintintbigintlongrealfloatfloatdoublemoneydecimaldatetimeDateTimecharstringvarcharstringncharstringnvarcharstringtextstringntextstringimagebyte[]binarybyte[]uniqueidentifierGuid/ SqlDbType转换为C#数据类型 public static Type Sq…

关于局部变量在内存中的地址

C code: #include<stdio.h> void main(){ int aa 11, bb 22; int a 1; int b 2; printf("%X/t%X/t%X/t%X/n", &aa, &bb, &a, &b);} Running Result: 12FF7C 12FF78 12FF74 12FF70 可见局部变量是存放在栈区的&#xff0c;他们的地址先…

C++20 Atomic 原子 内存模型(二)

C20 Atomic 原子 内存模型(二) 原子是C内存模型的基础 强/弱内存模型 1. 强内存模型 Leslie Lamport 定义了顺序一致性的概念 顺序一致性提供两个保证: 指令按源码的顺序执行对所有线程的所有指令有全局的顺序 以上不仅仅作用于原子, 也影响着非原子变量 int main(int a…

认证考试介绍之RHCE篇

认证考试介绍之RHCE篇 RHCE是Red Hat Certified Engineer的简称&#xff0c;始于1999年3月。截至2001年1月17日&#xff0c;Red Hat的统计资料表明&#xff0c;RHCE资格认证的通过率为62.5%。RHCE是市场上第一个面向Linux的认证考试&#xff0c;它不是一个普通的认证测试&#…

jquery 操作服务端控件,select 控件

<asp:DropDownList ID"ddl" runat"server"></asp:DropDownList> <select id"ddlsel" ></select> jquery取得该控件的方式有&#xff1a; 1. var ddl $("#<%ddl.ClientID%>"); //jq获取服务端控件,此方…

C++ 20 线程安全的Map

C 20 线程安全的Map 粗粒度(锁住整个bucket_data) template <typename Key, typename Value, typename Hash std::hash<Key>> class threadsafe_lookup_table { private:class bucket_type{private:using bucket_value std::pair<Key, Value>;using buck…

毕业多年,我们转变了多少?

懵懂,激情,成熟,沉默.似乎就是每个人的必经之路.从毕业时的酬躇满志到如今的随遇而安,从毕业时的悲伤离别到如今的陌路行人.从毕业时的海枯石烂到如今的两情分别.究竟,我们还有多少没有转变?毕业两年了,才知道,理想再崇高,究竟还是比不过面包.没有理想,大家照样活的滋润.没有面…

IOS设计模式之二(门面模式,装饰器模式)

本文原文请见&#xff1a;http://www.raywenderlich.com/46988/ios-design-patterns.由 krq_tiger&#xff08;http://weibo.com/xmuzyq&#xff09;翻译&#xff0c;如果你发现有什么错误&#xff0c;请与我联系谢谢。门面&#xff08;Facade&#xff09;模式&#xff08;译者…

java实现输出字符串中的数字字符

package com.joe; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Test { //将字符串的数字字符输出 public static void main(String[] args) { String str "iu7i8hy4jnb2"; //方法一 …

隐私策略 URL

本隐私策略的目的是说明当您访问和使用本插件时我们可能会搜集的资料, 我们会怎样使用这些资料, 是否会透露给第三方, 以及您对这些资料的使用及修改方面的选择权利. 本隐私策略适用于本插件,您需要仔细阅读本隐私策略. 访问者的信息 本插件会保存用户要求保存的信息 插件将…

揭开Vmware 虚拟软件层的秘密

【电脑商网专稿】虚拟软件究竟是什么软件, 是让所有的软件都”虚拟”执行吗, 虚拟软件层究竟是怎样的一层软件? 为什么现在这么多的公司和个人都在使用这种软件, 虚拟软件能代替操作系统完全控制硬件吗? 下面就让我们逐渐的揭开虚拟化技术这一特殊软件层的秘密吧.谈到虚拟化就…