WAV格式是微软公司(Microsoft)开发的一种声音文件格式,它符合 RIFF(Resource Interchange File Format)文件规范,用于保存 Windows 平台的音频信息资源,被 Windows 平台及其应用程序所广泛支持。

WAVE 是录音时用的标准的 WINDOWS 文件格式,文件的扩展名为“WAV”,数据本身的格式为 PCM 或其他压缩数据,属于无损音乐格式的一种。

所有的 WAV 都有一个文件头,这个文件头记录了音频流的编码参数。WAV文件 = WAV头 + PCM数据

阅读全文 »

在《Windows核心编程 第五版》第19章 DLL基础(511页)中给出了一个建议:

“当一个 MT 版本的模块如果提供一个内存分配函数的时候,它必须同时提供另一个用来释放内存的函数。”。

说得更加直白一点就是,“对于 MT 的模块,不要跨模块进行内存释放。”。但是核心编程这本书上面没有具体分析原因,本文就来分析具体的原因。

阅读全文 »

系统环境 Ubuntu 16.04,在搭建之前建议关闭系统防火墙。

房间服务器搭建

安装依赖程序

1
apt-get install git unzip  lrzsz  nodejs npm automake autoconf libtool nodejs-legacy python-webtest golang –y

安装jdk8

下载jdk8

此处下载对应的版本到/usr/lib/jvm目录,然后解压到当前目录:

1
tar zxf jdk-8u151-linux-x64.tar.gz

设置环境变量

编辑/etc/source文件,在文件尾添加如下内容(因为jdk版本不同,文件夹名称可能会有差别):

1
2
3
export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_151
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

执行source /etc/profile命令让设置生效。

apprtc获取和安装

获取apprtc源码

1
2
cd ~
git clone https://github.com/webrtc/apprtc.git

安装apprtc

1
2
3
4
cd apprtc
npm -g install grunt-cli
npm install
grunt build --force

修改源码

使用ifconfig命令查看本机IP信息:

我使用的阿里云的云服器,服务器在NAT之后,所以172.18.163.203是本地IP,即内网IP;从云服务器的管理页面可以看到该服务器的外网IP,如120.79.164.111。如果使用的是阿里云等服务器还需要在安全策略中设置将所有进/出端口都映射到172.18.163.203

下面以外网IP 120.79.164.111为例,根据实际外网IP进行对应修改。

修改constants.py

constants.py路径:apprtc/out/app_engine/constants.py

设置ICE服务器的IP端口、信令服务器(collider)的IP端口,修改之后的constants.py文件完整内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# Copyright 2015 Google Inc. All Rights Reserved.

"""AppRTC Constants.

This module contains the constants used in AppRTC Python modules.
"""
import os

# Deprecated domains which we should to redirect to REDIRECT_URL.
REDIRECT_DOMAINS = [
'apprtc.appspot.com', 'apprtc.webrtc.org', 'www.appr.tc'
]
# URL which we should redirect to if matching in REDIRECT_DOMAINS.
REDIRECT_URL = 'https://appr.tc'

ROOM_MEMCACHE_EXPIRATION_SEC = 60 * 60 * 24
MEMCACHE_RETRY_LIMIT = 100

LOOPBACK_CLIENT_ID = 'LOOPBACK_CLIENT_ID'

# Turn/Stun server override. This allows AppRTC to connect to turn servers
# directly rather than retrieving them from an ICE server provider.
ICE_SERVER_OVERRIDE = None
# Enable by uncomment below and comment out above, then specify turn and stun
# ICE_SERVER_OVERRIDE = [
# {
# "urls": [
# "turn:hostname/IpToTurnServer:19305?transport=udp",
# "turn:hostname/IpToTurnServer:19305?transport=tcp"
# ],
# "username": "TurnServerUsername",
# "credential": "TurnServerCredentials"
# },
# {
# "urls": [
# "stun:hostname/IpToStunServer:19302"
# ]
# }
# ]

ICE_SERVER_BASE_URL = 'http://120.79.164.111:3033'
ICE_SERVER_URL_TEMPLATE = '%s/v1alpha/iceconfig?key=%s'
ICE_SERVER_API_KEY = os.environ.get('ICE_SERVER_API_KEY')

# Dictionary keys in the collider instance info constant.
WSS_INSTANCE_HOST_KEY = 'host_port_pair'
WSS_INSTANCE_NAME_KEY = 'vm_name'
WSS_INSTANCE_ZONE_KEY = 'zone'
WSS_INSTANCES = [{
WSS_INSTANCE_HOST_KEY: '120.79.164.111:8089',
WSS_INSTANCE_NAME_KEY: 'wsserver-std',
WSS_INSTANCE_ZONE_KEY: 'us-central1-a'
}, {
WSS_INSTANCE_HOST_KEY: '120.79.164.111:8089',
WSS_INSTANCE_NAME_KEY: 'wsserver-std-2',
WSS_INSTANCE_ZONE_KEY: 'us-central1-f'
}]

WSS_HOST_PORT_PAIRS = [ins[WSS_INSTANCE_HOST_KEY] for ins in WSS_INSTANCES]

# memcache key for the active collider host.
WSS_HOST_ACTIVE_HOST_KEY = 'wss_host_active_host'

# Dictionary keys in the collider probing result.
WSS_HOST_IS_UP_KEY = 'is_up'
WSS_HOST_STATUS_CODE_KEY = 'status_code'
WSS_HOST_ERROR_MESSAGE_KEY = 'error_message'

RESPONSE_ERROR = 'ERROR'
RESPONSE_ROOM_FULL = 'FULL'
RESPONSE_UNKNOWN_ROOM = 'UNKNOWN_ROOM'
RESPONSE_UNKNOWN_CLIENT = 'UNKNOWN_CLIENT'
RESPONSE_DUPLICATE_CLIENT = 'DUPLICATE_CLIENT'
RESPONSE_SUCCESS = 'SUCCESS'
RESPONSE_INVALID_REQUEST = 'INVALID_REQUEST'

IS_DEV_SERVER = os.environ.get('APPLICATION_ID', '').startswith('dev')

BIGQUERY_URL = 'https://www.googleapis.com/auth/bigquery'

# Dataset used in production.
BIGQUERY_DATASET_PROD = 'prod'

# Dataset used when running locally.
BIGQUERY_DATASET_LOCAL = 'dev'

# BigQuery table within the dataset.
BIGQUERY_TABLE = 'analytics'

修改apprtc.py

apprtc.py路径:apprtc/out/app_engine/apprtc.py



修改为

(大约位于146行左右)

修改index_template.html

index_template.html路径:apprtc/out/app_engine/index_template.html

设置TURN服务器信息,在javascript脚本中添加servers变量:

1
2
3
4
5
6
7
8
var servers=[{
credential:"helloword",
username:"helloword",
urls:[
"turn:120.79.164.111:3478?transport=udp",
"turn:120.79.164.111:3478?transport=tcp"
]
}];

并将peerConnectionConfig: {{ pc_config | safe }}修改为使用上面声明的servers变量;

1
2
peerConnectionConfig: { "rtcpMuxPolicy":"require","iceServers":servers,"bundlePolicy":"max-bundle"},iceServerRequestUrl: '{{ ice_server_url }}',
// peerConnectionConfig: {{ pc_config | safe }},

##1.4 获取google_appengine
https://download.csdn.net/download/china_jeffery/10375696下载google_appengine.tar,并使用tar命令解压:

1
2
cd ~
unzip google_appengine.tar

启动房间服务器

1
2
cd ~
./google_appengine/dev_appserver.py --host 172.18.163.203 ./apprtc/out/app_engine --skip_sdk_update_check

172.18.163.203为内网IP。

信令服务器搭建

collider源码

Webrtc信令服务可以使用的apprtc自带的collider,这个服务是使用go语言开发。collider已经位于apprtc/src目录中,我们将其拷贝到~/collider/src目录中:

1
2
3
cd ~
mkdir collider/src -p
cp apprtc/src/collider/ collider/src/ -r

编辑~/collider/src/collidermain/main.go文件,将room-server修改为服务器的外网IP和端口8080:

1
var roomSrv = flag.String("room-server", "http://120.79.164.111:8080", "The origin of the room server")

安装go

在安装go之前最好先卸载掉系统上已经安装的go版本:

1
2
3
apt-get remove golang
apt-get remove golang*
apt-get autoremove

然后使用wget命令下载go:

1
wget https://storage.googleapis.com/golang/go1.5.1.linux-amd64.tar.gz

或者从https://download.csdn.net/download/china_jeffery/10375936下载。然后解压tar zxf go1.5.1.linux-amd64.tar.gz

添加如下环境变量到/etc/source文件尾,并使用source /etc/source是环境变量生效:

1
2
3
export GOROOT=/root/go
export PATH=$PATH:$GOROOT/bin
export GOPATH=/root/collider/

collider安装

使用go命令进行collider安装:

1
2
3
cd ~/collider
go get collidermain
go install collidermain

启动信令服务器

1
2
cd ~
./collider/bin/collidermain -port=8089 -tls=false

TURN服务器搭建

webrtc的turn服务是为提供NAT穿透或者中转使用的,因为webrtc客户端可能会在不同的路由器后面或者多层路由器后面,那么他们如何通讯呢?都需要穿透,穿透的服务就是turn服务,webrtc推荐使用的coturn(以前也叫turnserver),它支STUN和Relay。

安装依赖

1
2
sudo apt-get install libssl-dev
sudo apt-get install libevent-dev

下载并编译源码

1
2
3
4
cd ~
git clone https://github.com/coturn/coturn.git
cd coturn
configure && make && make install

启动TURN服务

1
./coturn/bin/turnserver --syslog -a -X 120.79.164.111 -E 172.18.163.203 -f --min-port=32355 --max-port=65535 --user=helloword:helloword -r helloword --cert=turn_server_cert.pem --pkey=turn_server_pkey.pem --log-file=stdout -v

120.79.164.111为外网IP,172.18.163.203为本地IP。
turnserver的参数见:

https://github.com/coturn/coturn/wiki/turnserver

本文最初发布在我的CSDN博客:《WebRTC – 官方apprtc示例搭建》

为什么要使用堆?

应用程序虽然可以使用页面粒度的函数(如VirualAlloc)来分配一个最小为4KB8K的内存块,但是很多时候我们并不需要分配这么大的内存块,我们可能只想分配 1K,2K 的内存块,那么这个时候无论从内存的使用率,还是从性能的角度来看,再分配这么大的一个内存区域显然不是最优的了。

为了满足这种需求,Windows 提供了一个被称为“堆管理器”的组件,它负责管理大内存区域中的内存分配,这些大内存区域就是通过一些页面粒度的内存分配函数(如VirualAlloc)来预定(reserve)的。

堆管理器中的分配粒度相对比较小:在32位系统上是8字节,在64位系统上是16字节

堆管理器已经被 Windows 系统精心设计,在这些小内存分配的情况下会进行内存使用率和性能两个方面的优化。

阅读全文 »

为什么要内存对齐

平台原因

不是所有的CPU都能访问任意地址上的任意数据的,有些CPU只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。

性能原因

尽管内存是以字节为单位,但是大部分处理器并不是按字节块来存取内存的,它一般会以双字节、四字节、8字节、16字节甚至32字节为单位来存取内存,我们将上述这些存取单位称为内存存取粒度

如果数据存储时是按照内存存取粒度对齐的,那么处理器就可以在一个内存访问周期内完成数据的读取;反之,如果数据没有对齐,可能需要多个内存访问周期才能读取完整的数据。

阅读全文 »

为什么需要内存映射

“内存映射文件”可以将硬盘上的文件映射到虚拟地址空间,这样就不需要将所有东西都放入到页交换文件中,比如系统有许多程序同时运行时,如果将这些程序文件都加载到页交换文件中,页交换文件将会变得非常大。事实上,Windows 也并没有将硬盘上的程序文件复制到页交换文件中,因为这样不仅会让页交换文件将会变得非常大,也会浪费很多时间,特别是可执行程序非常大的时候。

当用户要求执行一个应用程序时,系统会打开该应用程序的.exe文件,并计算出应用程序的代码和数据的大小,然后系统会在进程的虚拟地址空间预定一块地址空间,并注明与该区域相关联的物理存储器就是.exe文件本身。

当把一个位于硬盘上的文件(可以是.exe.dll也可以是普通文件)映像用作地址空间区域对应的物理存储器时,我们称这个文件映像为“内存映射文件”

阅读全文 »

页交换文件

虚拟地址空间只是操作系统为进程“虚拟”出来的一块地址区域,并不代表任何实际的空间。而“页交换文件”却对应了实际的空间,这个空间一般是磁盘上名为“pagefile.sys”的文件。

“页交换文件”的大小和位置可以在系统设置(系统属性 -> 高级 -> 性能 -> 设置 -> 高级 )中进行设置:

从微软的官方文档来看,“虚拟内存”等于“物理内存”+“分页文件”总和。可以把“虚拟内存”理解为 Windows 的一种内存管理机制。

阅读全文 »

实模式下内存分配机制

在 8086 或者 80186 以前,程序运行时,操作系统会把程序全都装入内存,程序都是直接运行在物理内存上的。也就是说程序中访问的内存地址都是实际的物理内存地址。当计算机同时运行多个程序时,必须保证这些程序用到的内存总量要小于计算机实际物理内存的大小。

例如某台计算机总的内存大小是128M ,现在同时运行两个程序 A 和 B ,A 需占用内存10M , B 需占用内存110M 。计算机在给程序分配内存时会采取这样的方法:先将内存中的前10M分配给程序 A ,接着再从内存中剩余的118M中划分出 110M分配给程序 B 。这种分配方法虽然可以保证程序 A 和程序 B 都能运行,但是这种简单的内存分配策略会导致很多问题:

阅读全文 »

WebRTC (Web Real-Time Communications) 是一项实时通讯技术,它允许网络应用或者站点在不借助中间媒介的情况下,建立浏览器之间点对点(Peer-to-Peer)的连接,实现视频流和(或)音频流或者其他任意数据的传输。WebRTC包含的这些标准使用户在无需安装任何插件或者第三方的软件的情况下,创建点对点(Peer-to-Peer)的数据分享和电话会议成为可能。

它并不是单一的协议,包含了媒体、加密、传输层等在内的多个协议标准以及一套基于 JavaScript 的 API。通过简单易用的 JavaScript API ,在不安装任何插件的情况下,让浏览器拥有了 P2P音视频和数据分享的能力。同时WebRTC 并不是一个孤立的协议,它拥有灵活的信令,可以便捷的对接现有的SIP 和电话网络的系统。

不同技术领域的人都可以从WebRTC中获取到需要的东西。

阅读全文 »

会话描述协议(Session Description Protocol 或简写 SDP)描述的是流媒体的初始化参数。此协议由 IETF 发表为 RFC 2327。

SDP 完全是一种会话描述格式,它不属于传输协议。

SDP 用于描述多媒体通信会话,包括会话建立、会话请求和参数协商。SDP 不用于传输媒体数据,只能用于两个通信终端的参数协商,包括媒体类型、格式以及所有其他和会话相关的属性。SDP 以字符串的形式描述上述初始化参数。

阅读全文 »
0%