- Backup before tuning
- Use x86_64 architecture in production environment
- System timer precision
- Enable thread priorities mapping
- Start Wowza server as root
- Set TcpNoDelay and QoS lowlatency for RTMP
- Set QoS lowlatency for RTP
- Configure outgoing RTMP stream
- Configure incoming RTMP stream
- Configure quality - latency balance
- Configure jitter buffer on VoIP server or SIP endpoint
- Speex voice quality tuning
- Downstream is a stream from Flash-Server to Flash-client
- Upstream is a stream from Flash-client to Flash-Server
- Yasm video optimization
Flashphoner works in complex environment. This is a tuning guide, which helps you to adjust quality and performance in your environment.
Here SERVER_HOME=/usr/local/WowzaMediaServer
Backup before tuning
[security]
Backup SERVER_HOME dir before tuning
You can restore you default parameters in this case.
Use x86_64 architecture in production environment
[quality, performance, memory]
Use 64-bit system if it is possible.
System timer precision
[quality]
Use highest available system timer on Linux. We have tested our system with such kernel parameters:
HZ=1000
High Resolution Timer=y
How to configure kernel
Example for Kernel: 2.6.38.3, System: CentOS 5.5, Centos 5.6:
General Setup -> enable deprecated sysfs features to support old....
General Setup -> enable deprecated sysfs features by dafault
Processor type and features -> High Resolution Timer Support
Processor type and features -> Timer frequency (1000 HZ)
./include/asm-generic/param.h (USER_HZ 1000 and HZ 1000)
Default system timer precision for some systems
x86_64 system architecture used in table below:
| System | Timer frequency HZ | timing-tool results |
|---|---|---|
| CentOS 5.4 | 250 | Timing has been initialized: 16005672 Timer precision(float) = 3.994328 ms |
| CentOS 5.6 | 500 | Timing has been initialized: 18000552 Timer precision(float) = 1.999448 ms |
| CentOS 6 | 1000 | Timing has been initialized: 19939634 Timer precision(float) = 0.060366 ms |
| RHEL 6 | 1000 | Timing has been initialized: 19949751 Timer precision(float) = 0.050249 ms |
red - requires the kernel configuring
green - does not require the kernel configuring
How to check current system-timer precision
Download the timing-tool and start timing.sh
You will get such results:
Timing has been initialized: 16005672
Timer precision(float) = 3.994328 ms
It means, your timer precision is about 4ms(HZ=250).
When your system HZ value is 1000 and High Resolution Timer Support is enabled, you result must be less than 0.1ms(0.03ms, 0.04ms, 0.05ms e.t.c).
Enable thread priorities mapping
[quality, memory]
Configure setenv.sh as described here: http://www.wowzamedia.com/forums/content.php?5-general-tuning [5,6,13]
Add line:
JAVA_OPTS="$JAVA_OPTS -server -XX:+UseThreadPriorities -XX:ThreadPriorityPolicy=1"
after
JAVA_OPTS="-Xmx1200M"
So, your config should look like this:
... JAVA_OPTS="-Xmx1200M" JAVA_OPTS="$JAVA_OPTS -server -XX:+UseThreadPriorities -XX:ThreadPriorityPolicy=1" ...
Thread priorities may impact on quality of audio-video conversation.
This settings gives Flashphoner permissions to set priority for internal threads.
Start Wowza server as root
[quality]
If java process started as non-root user, Linux does not use thread priority mapping.
You can avoid starting the server as root. See this workaround: http://www.akshaal.info/2008/04/javas-thread-priorities-in-linux.html
Also, look latest JVM documentation here: http://www.oracle.com/technetwork/java/javase/downloads/index.html
Set TcpNoDelay and QoS lowlatency for RTMP
[quality, performance]
Set TcpNoDelay and QoS lowlatency for RTMP sockets.
Configure VHost.xml file as described on this page http://www.wowzamedia.com/forums/content.php?5-general-tuning [7,11]
Uncomment:
<TcpNoDelay>true</TcpNoDelay>
<TrafficClass>16</TrafficClass>
We believe, this socket configuration may impact on latency in some cases.
Set QoS lowlatency for RTP
[quality]
rtp_traffic_class=16
Configure outgoing RTMP stream
[quality]
<Name>rtmp2voip</Name> <Description>RTMP2Voip</Description> <ClassBase>com.flashphoner.app.MyRtmp2VoipStream</ClassBase> <ClassPlay>com.wowza.wms.stream.live.MediaStreamLivePlay</ClassPlay> <Properties> <Property> <Name>maxliveaudiolatency</Name> <Value>500</Value> </Property> <Property> <Name>instantOn</Name> <Value>false</Value> <Type>Boolean</Type> </Property> <Property> <Name>flushInterval</Name> <Value>20</Value> <Type>Integer</Type> </Property> <Property> <Name>onFlushNotifyClients</Name> <Value>true</Value> <Type>Boolean</Type> </Property> <Property> <Name>disableLowBandwidthThrottling</Name> <Value>false</Value> <Type>Boolean</Type> </Property> <Property> <Name>behindDropDFrames</Name> <Value>3000</Value> <Type>Integer</Type> </Property> <Property> <Name>behindDropPFrames</Name> <Value>3000</Value> <Type>Integer</Type> </Property> <Property> <Name>behindDropKFrames</Name> <Value>3000</Value> <Type>Integer</Type> </Property> <Property> <Name>behindDropAudio</Name> <Value>500</Value> <Type>Integer</Type> </Property> </Properties> </Stream>
Configure incoming RTMP stream
[quality]
<Stream> <Name>live</Name> <Description>Live Video</Description> <ClassBase>com.wowza.wms.stream.live.MediaStreamLive</ClassBase> <ClassPlay>com.wowza.wms.stream.live.MediaStreamLivePlay</ClassPlay> <Properties> <Property> <Name>maxliveaudiolatency</Name> <Value>500</Value> </Property> <Property> <Name>instantOn</Name> <Value>false</Value> <Type>Boolean</Type> </Property> <Property> <Name>flushInterval</Name> <Value>20</Value> <Type>Integer</Type> </Property> <Property> <Name>onFlushNotifyClients</Name> <Value>true</Value> <Type>Boolean</Type> </Property> <Property> <Name>disableLowBandwidthThrottling</Name> <Value>false</Value> <Type>Boolean</Type> </Property> <Property> <Name>behindDropDFrames</Name> <Value>1500</Value> <Type>Integer</Type> </Property> <Property> <Name>behindDropPFrames</Name> <Value>3000</Value> <Type>Integer</Type> </Property> <Property> <Name>behindDropKFrames</Name> <Value>6000</Value> <Type>Integer</Type> </Property> <Property> <Name>behindDropAudio</Name> <Value>500</Value> <Type>Integer</Type> </Property> <Property> <Name>isLive</Name> <Value>true</Value> <Type>Boolean</Type> </Property> </Properties> </Stream>
Configure quality - latency balance
[quality]
Flashphoner use buffering of incoming and outgoing stream to adjust quality and drop packets if latency is too big.
SERVER_HOME/conf/flashphoner.properties
| Name | Unit | Default value | Description |
|---|---|---|---|
| in_jitter_buffer_enabled | true/false | false | Enables/disables using of jitter buffer algorithms for incoming streams |
| out_jitter_buffer_enabled |
true/false | true | Enables/disables using of jitter buffer algorithms for outgoing streams |
| min_drop_rate |
percents | 0.5 | If current mean drop rate < min_drop rate, we decrease queue size and decrease latency |
| max_drop_rate |
percents | 1 | If current mean drop rate > max_drop_rate, we increase queue size and increase latency, but up to max_queue_size maximum |
| min_queue_size |
packets | 10 | Minimum queue size |
| max_queue_size |
packets | 50 | Maximum queue size. Latency may grow up to max_queue_size. Then packets will be dropped regardless max_drop_rate |
Note, system timer precision tuning is mandatory for using this options.
Jitter buffer is a thread which flush audio packets every 20ms, using system timer.
If your system timer is not configured properly, you may get worse or unacceptable quality, using the jitter buffer.
Configure jitter buffer on VoIP server or SIP endpoint
[quality]
Jitter buffer may reduce voice chopping and give smoothly conversation.
If you have problems with voice quality, you may setup jitter buffer for your VoIP server, if VoIP server located in your environment of course.
Example of configuring jitter buffer for Asterisk 1.6
jbenable=yes jbforce=yes jbmaxsize=200 jbimpl=fixed
This example uses fixed implementation of jitter buffer with 200 milliseconds size.
Please, consult with your VoIP server documentation to configure jitter buffer properly.
Speex voice quality tuning
[quality]
Flashphoner uses speex codec for RTMP downstreams and RTMP upstreams.
Downstream is a stream from Flash-Server to Flash-client
Some quotes from speex documentation:
Quality (variable)
Speex is a lossy codec, which means that it achives compression at the expense of fidelity of the input speech signal. Unlike
some other speech codecs, it is possible to control the tradeoff made between quality and bit-rate. The Speex encoding process
is controlled most of the time by a quality parameter that ranges from 0 to 10. In constant bit-rate (CBR) operation, the quality
parameter is an integer, while for variable bit-rate (VBR), the parameter is a float.
Complexity (variable)
With Speex, it is possible to vary the complexity allowed for the encoder. This is done by controlling how the search is
performed with an integer ranging from 1 to 10 in a way that's similar to the -1 to -9 options to gzip and bzip2 compression
utilities. For normal use, the noise level at complexity 1 is between 1 and 2 dB higher than at complexity 10, but the CPU
requirements for complexity 10 is about 5 times higher than for complexity 1. In practice, the best trade-off is between
complexity 2 and 4, though higher settings are often useful when encoding non-speech sounds like DTMF tones.
Variable Bit-Rate (VBR)
Variable bit-rate (VBR) allows a codec to change its bit-rate dynamically to adapt to the "difficulty" of the audio being
encoded. In the example of Speex, sounds like vowels and high-energy transients require a higher bit-rate to achieve good
quality, while fricatives (e.g. s,f sounds) can be coded adequately with less bits. For this reason, VBR can achive lower bit-rate
for the same quality, or a better quality for a certain bit-rate. Despite its advantages, VBR has two main drawbacks: first, by
only specifying quality, there's no guaranty about the final average bit-rate. Second, for some real-time applications like voice
over IP (VoIP), what counts is the maximum bit-rate, which must be low enough for the communication channel.
Since patch Flashphoner-1.0.3.512-p.760 you able to configure policy for the downstream on server-side. See table below:
| Policy name | quality | VBR enabled | VBR quality | Algorithm complexity |
|---|---|---|---|---|
| normal | 6 | true | 6 | 3 |
| good | 8 | false | 8 | 4 |
| best | 10 | false | 10 | 8 |
| ultimate | 10 | false | 10 | 10 |
Default policy is "good".
Usage:
Edit server-side flashphoner.properties file:
speex_in_policy = normal
or
speex_in_policy = good
or
speex_in_policy = best
or
speex_in_policy = ultimate
You can use custom policy too:
speex_in_policy = 10,false,10,2
| Higher policies like ultimate policy may increase CPU usage and cause the latency grow. But it gives higher sound quality |
Upstream is a stream from Flash-client to Flash-Server
Use
mic.encodeQuality = 6;
in client-side SoundControl.as
Yasm video optimization
| Since Flashphoner-1.0.4.791, Yasm is included in Flashphoner installation package. You do not need to install yasm, if you use Flashphoner-1.0.4.791 version or above. |
It may optimize video encoding to decrease CPU usage and increase performance.
Get yasm. Yasm is a modular assembler that will optimize video encoding for MMX/SSE.
You can download yasm here
Use simple magic to install it:
./cofigure ./make ./make install
| You should install yasm BEFORE you install Flashphoner |
If the Flashphoner has already installed, you need to do 3 steps:
- Uninstall Flashphoner
- Install yasm
- Install Flashphoner