2. Syntax of the graph description

A graph description consists of two major parts. The first part is an (optional) comment introduced by the character %. The second part specifies the flow graph which describes how to connect the nodes. The following example describes a simple graph to play an MP3 audio file.

% This graph description realizes a simple MP3 player.
% Use the -i option of clic to specify the MP3 file

MP3ReadNode ! MPEGAudioDecodeNode ! PlaybackNode
    
To run this graph description, copy it into a file, e.g. mp3play.gd, and start clic with the following command:
./clic mp3play.gd -i /home/bob/audio/song.mp3
    
The option -i is used to specify the input file. To exit the application, enter q at the command line. For detailed information about all options simply type:
./clic -h
    
Appendix A describes the location of the graph descriptions that are included in the current NMM release. The rest of this section describes this example in detail.

2.1. Creating flow graphs

The flow graph section of a graph description describes how to connect the nodes. A node is identified by its name, which is (normally) the C++ class name. The exclamation mark (!) is used to denote a connection between two nodes as seen in the graph description for MP3 files. In this example the statement

MP3ReadNode ! MPEGAudioDecodeNode ! PlaybackNode
      
causes the clic-application to request the nodes MP3ReadNode, MPEGAudioDecodeNode and PlaybackNode. If all nodes can be successfully requested, the MP3ReadNode is connected to the MPEGAudioDecodeNode, and the MPEGAudioDecodeNode to the PlaybackNode. After this clic sets the specified parameters from the command line, like an input file, and starts the entire flow graph.

To specify a more complex flow graph that includes a a demultiplexer we need an additional syntax to describe the different input- or output jacks which a (de)multiplexer can provide. Therefore, a unique string which is called jack tag is associated with each jack to identify it. For example these jack tags are used to distinguish between audio and video in/output of a multiplexer or a demultiplexer node. If a node provides only a single input or output jack the string "default" is used as jack tag and it is used in graph description if no other jack tag is specified. To use a specific input jack that should be used for a connection, the corresponding jack tag must be written before the node name, and behind the node name to specify an output jack respectively. The following example shows the MP3 player graph description with specified "default" jack tags:

% This graph description realizes a simple MP3 player and specifies the
% input and output jacks using their jack tags.
% Use the -i option of clic to specify the MP3 file

            MP3ReadNode         "default"
! "default" MPEGAudioDecodeNode "default"
! "default" PlaybackNode
      
In this example the specification of jack tags is not required because clic uses the jack "default" to connect nodes if no one is specified. Furthermore, we need a syntax to describe branches of nodes that must be connected to a specific output jack of the demultiplexer. To describe a branch in a flow graph, the corresponding nodes are encapsulated in braces ({}) as seen in the following example, for reading mpeg files.
% This graph description realizes a simple mpeg video player with ac3 audio.
% Use the -i option of clic to specify the mpeg video file.

MPEGReadNode ! MPEGDemuxNode
{
  { ["mpeg_video0"] ! MPEGVideoDecodeNode ! XDisplayNode }
  { ["ac3_audio0"] ! AC3DecodeNode ! PlaybackNode }
}
      
The MPEGDemuxNode demultiplexes incoming messages and forwards audio buffer to the "ac3_audio0" output jack and video buffer to the "mpeg_video0" output jack respectively. After the MPEGDemuxNode, braces encapsulates all branches connected to this node. Each branch itself is encapsulated in braces too and starts with the output jack tag of the MPEGDemuxNode, encapsulated in square brackets. This output jack is connected to the leading node of the branch. So in this example we have two branches. The first one consist in the MPEGVideoDecodeNode, connected to the XDisplayNode. The MPEGVideoDecodeNode is the leading node of this branch and is connected to output jack of the MPEGDemuxNode with jack tag "mpeg_video0". The second branch consist in the AC3DecodeNode connected to the PlaybackNode. The leading node of this branch is the AC3DecodeNode which is connected to the output jack of the MPEGDemuxNode with jack tag "mpeg_audio0".

To add a multiplexer node is very similar to a demultiplexer, as seen in the following example.

% This graph description converts an mpeg video file with ac3
% audio into an avi file. 
% Unfortunately the flow graph doesn't work because the FFMpegEncodeNode
% requires a bitrate.

MPEGReadNode ! MPEGDemuxNode
{
  {
    ["mpeg_video0"] !
    MPEGVideoDecodeNode !
    FFMpegEncodeNode !
    ["video"]
  }
  {
    ["ac3_audio0"] !
    ["audio"]
  }
} AVMuxNode ! AVIWriteNode
      
This example can be used to convert an mpeg file into an avi file with DivX-video and ac3 audio. So the first branch consist in an MPEGVideoDecodeNode which is connected to the FFMpegEncodeNode. The input of the first node in this branch, the MPEGVideoDecodeNode, is connected to the output jack of the MPEGDemuxNode with jack tag "mpeg_video0". The output of the last node in this branch, the FFMpegVideoEncodeNode, is connected to the input jack of the AVMuxNode with jack tag "video". The second branch has no nodes. In this branch output of the MPEGDemuxNode jack with jack tag "ac3_audio0" is connected to the input jack of AVmuxNode with jack tag "audio". So the audio buffers are directly passed through from the MPEGDemuxNode to the AVMuxNode without any conversion.

The syntax of this example is correct but the flow graph can not run because the FFMpegEncodeNode needs the encoding bitrate which is specified in the connection format. So we need a possibility to (partially) specify a connection format that is used between two nodes. The statement Format prefaced by the character '@' is used to specify the connection format. This statement expects a comma separated list of format types, which are defined in the Format.hpp followed by a corresponding value. A sole exception is the format type which is written as a single string. Note: The connection format must be specified in front of the connection symbol (!). The following example shows how to define the connection format including the format type and the bitrate of the FFMpegEncodeNode.

% This graph description converts an mpeg video file with ac3 audio
% into an avi file. Furthermore the desired bitrate of the video is
% specified using the connection format.
% Use the -i option of clic to specify the mpeg video file and -o option
% to specify the name of the output file.

MPEGReadNode ! MPEGDemuxNode
{
 {
   ["mpeg_video0"]  !
   MPEGVideoDecodeNode !
   FFMpegEncodeNode @ Format ("video/mpeg4", bitrate = 1200000) !
   ["video"]
 }
 {
   ["ac3_audio0"] !
   ["audio"]
 }
} AVMuxNode ! AVIWriteNode
     

To run this flow graph, copy the graph description into a file, e.g.mpeg_to_avi.gd, an enter

./clic mpeg_to_avi.gd -i /home/bob/video/movie.mpeg -o /home/bob/video/movie.avi
    

whereas the option -i specifies the input file and -o the output file.

Furthermore you can specify two additional parameters to set the transport protocol used to transmit data between two nodes, which is especially useful if they are running on different hosts. Both parameters are prefaced by the character '@' as well. To configure a specific transport protocol used for instream communication the parameter setBufferStrategy and setEventStrategy can be used, as seen in the following graph description.

% This graph description describes a simple MP3 player which specifies the 
% used transport protocols between the nodes.
% Use the -i option of clic to specify the MP3 file 
     
MP3ReadNode         @ setEventStrategy("TCPStrategy") 
                    @ setBufferStrategy("RTPStrategy") !
MPEGAudioDecodeNode @ setBufferStrategy("RTPStrategy") !
PlaybackNode
    
The parameter setBufferStrategy specifies the transport protocol used to transmit multimedia buffers and the parameter setEventStrategy how to transport instream events. In this example the multimedia protocol RTP is used to transmit the MP3 buffers and the reliable TCP protocol to transmit instream events. To transport buffers between the MPEGAudioDecodeNode and PlaybackNode, the RTP protocol is used, but no protocol for instream events is specified. If one of these parameters or both are not set, the default transport strategy proposed by the NMM middleware is used, which is a LocalStrategy to transport buffers and events between nodes in the same address space efficiently via pointer forwarding and TCPStrategy between nodes running on different hosts or address spaces.