• OpenH.323
  • Your applications
  • Fine tuning
  • What's next?

    H.263 in OpenH.323 HowTo

    Author: Guilhem Tardy
    Last update: March 15, 2005

    The following instructions will take you through the steps necessary to port your OpenH.323 applications to standard compliant, H.263/rfc2190 streaming.

    Adding H.263 to OpenH.323

    You may choose either of these options:

    • replace the non-standard ffh263codec capability with files available here for OpenH.323 version 1.13.5-1 (Janus_patch2) and earlier,
    • or use the rfc2190avcodec capability found in later versions and on the OpenH.323 CVS (external link).

    The former is the easiest when dealing with old versions of OpenH.323, and makes the perfect drop-in replacement for existing applications. You just need to indicate where the FFmpeg-0.4.7 library resides:

    ./configure --avcodec-dir=f:/devel/ffmpeg-0.4.7/libavcodec

    For OpenH.323 1.41.1 or later (including the head CVS), an empty file avcodec_rfc2190.h may be required in the same directory as avcodec.h for the configure program to recognize the FFmpeg-0.4.7 library. More information on this is available here (external link). Then, indicate where the FFmpeg-0.4.7 library resides like this:

    ./configure --enable-rfc2190avcodec=f:/devel/ffmpeg-0.4.7/libavcodec

    From there, you just need to follow the OpenH.323 build instructions found in the openh323/ReadMe.txt file.

    Adding H.263 to your applications

    We will now assume a standard compliant rfc2190avcodec capability as found in OpenH.323 1.41.1 or later (including the head CVS).

    You may also choose the ffh263codec capability as found in the preceding chapter (please note the different constructor compared to the non-standard capability of the same name).

    The easiest way to create an H.263 capability is:

    new H323_RFC2190_H263Capability();

    Now, take a look at the definition of H323_RFC2190_H263Capability in the header file.

    The only parameters of interest are xxxMPI and maxBitRate. The remaining is not supported by the FFmpeg-0.4.7 library nor the OpenH.323 stubs.

    The xxxMPI parameters represent the maximum TX or RX frame rate supported by your application for that particular picture size, with a value between 1 and 32 (in units of 1/29.97 Hz}, or 0 for disable.

    A capability with more than one picture size enabled means that the application may change picture size at any time during a call.

    For example, cifMPI=2 and cif4MPI=6 is suitable for an application that supports up to 15 fps in CIF (352x288) or alternatively up to 5 fps in 4CIF (704x572).

    Please be aware that the codec refuses to change picture size outside of these specified in its capability. This is a feature, not a bug!

    The maxBitRate parameter represents the maximum TX or RX bit rate supported by your application, with a value between 1 and 192400 (in units of 100 bit/s). Yes, you read it right, a setting of 1024 actually means 100*1024 bps = 100 kbps.

    By default, the codec sets its TX maximum bit rate to this value. You may change it later when opening a video channel. In the future, the codec will accept no value higher than specified in its capability.

    Here is some sample code:

    int maxbps = videoBitRate/100;
    SetCapability(0, 1, new H323_RFC2190_H263Capability(0, 0, 2, 0, 0, maxbps);

    Fine tuning the H.263 codec

    Because of the rather poor rate control available in FFmpeg-0.4.7, we will need to make some drastic choices in order to obtain a good picture quality at a set maximum bit rate.

    Given a certain quality (in percentage) and maximum bit rate (in units of 1 kbit/s), here is some sample code:

    codec.SetTxQualityLevel(31 - (30*videoQuality)/100);
    codec.SetTargetFrameTimeMs(videoFPS ? 1000/videoFPS : 0);
    #ifdef H323_AVCODEC
    if (codec.IsDescendant(H323_FFH263Codec::Class())) {
    H323_FFH263Codec & ffcodec = (H323_FFH263Codec &) codec;
    Whenever the rate control fails to predict accurately the size of the encoded picture (e.g. under high motion), AdaptivePacketDelay will automatically reduce the frame rate in order to enforce the desired maximum bit rate.

    This way, your application will maintain a constant picture quality. But failing to set a proper maximum bit rate will most likely result in a very low frame rate. The "native" bit rate varies with the picture size, frame rate, quality, and the natural complexity - especially motion! - of the picture. Therefore, you should take the following estimates with a truck load of salt (quality 75% @ 10 fps):

    • QCIF ⇒ max_bps = 30 kbps
    • CIF ⇒ max_bps = 80 kbps
    • 4CIF ⇒ max_bps = 200 kbps

    SetTargetFrameTimeMs() is somewhat misleading in that it actually sets the maximum frame rate, or 0 for disable (i.e. as fast as one can grab from the camera). The idea is that extreme variations in frame rate would prove uncomfortable to the user.

    The target packet size help reduce the latency induced onto very time-sensitive streams such as audio. This should be set according to the Internet access technology in use:

    • dial-up (64 kbps) ⇒ psize = 200 bytes
    • narrow band (128 kbps) ⇒ psize = 320 bytes
    • wide band (256 kbps or higher) ⇒ psize = 700 bytes

    Please also note that the key frame rate is set by default to about 1 per second (according to the maximum frame rate in the capability). Although this is presently hard-coded in the codec, any value between 0 and 131 (in unit of frames between 2 key frames) is valid.

    Key frames are used to resynchronize the decoder with the remote client in a full picture refresh. Therefore, it is better to keep the time between 2 key frames low to reduce the effect of packet loss. But key frames are usually 3 to 5 times bigger than normal frames, and may induce further packet loss due to the increased bit rate.

    What's next?

    We have been working hard over the past year to expand the set of features:

    • H.263+ & MPEG-4 codecs (ffmpeg-cvs)
    • custom picture sizes
    • dependable rate control
    • incremental, "no key frame" refresh
    • incremental (independent packet) & multi-threaded encoding
    • incremental (independent packet) decoding
    • use of the RTP payload header to correct errors
    • pro-active error resilience in the bitstream
    • H.245 integration and refresh of selected (erroneous) parts of the picture
    • and more parameters available to the applications.
    The latest Salyens plugin for Java and native, multi-platform applications are now production stable, earning praises for their versatility, efficiency and small footprint. Please contact us for more details.