OpenMediaLib User and Development Guide

The Encoding Filter Graph

While image scaling and aspect ratio are crucial considerations from the encoding cycle, that is only part of the problem of encoding.

A couple of other factors play their part in the process – frame rate and audio sampling also need to be considered.

OML provides some additional filters for these and the following general form of a filter graph is used to encode any number of clips to a fixed frame rate:

composite
  colour:
  deinterlace
    playlist
      frame_rate
        clip
          resampler
            conform
              <input1>
      frame_rate
        clip
          resampler
            conform
              <input2>

NB: frame_rate is a temporary filter which carries out frame rate conversion via a drop and dupe approach – proper pulldown filters can (and should) be implemented.

Note that this 'all in one' graph isn't strictly necessary, and might not be ideal in all cases – in its favour it has the following advantage - by constructing one graph, there is a known number of frames for the entire content, and progress can easily be shown for the whole.

From a resource utilisation point of view, it might be better to consider creating a graph for each clip and thus, progress can be shown for each clip (or if the durations of the inputs are known in advance, progress can be computed for the whole). As shown in a later section, the breakdown of large multitrack projects works in much the same way.

As should be clear from the details previously, the full graph can be constructed using the following pseudo python code which assumes in/out points are correctly provided:

rpn.push_args( [ “colour:”, “fps_num=25”, “fps_den=1”, “width=720”, “height=576”, “sar_num=59”, “sar_den=54” ] )
count = 0
for v in videos:
	rpn.push_args( [ v.file ] )
	rpn.push_args( [ “filter:conform” ] )
	rpn.push_args( [ “filter:resampler”, “frequency=48000”, “channels=2” ] )
	rpn.push_args( [ “filter:clip”, “in=%i” % v.in, “out=%i” % v.out ] )
	rpn.push_args( [ “filter:frame_rate”, “fps_num=25”, “fps_num=1” ] )
	count += 1
rpn.push_args( [ “filter:playlist”, “slots=%i” % count ] )
rpn.push_args( [ “filter:deinterlace”, “filter:composite”, “slot=1” ] )

Note the frame rate properties are stipulated at multiple points in the graph – the net result is that each video file is 'normalised' individually and independently before being composited on to the single background node.

This should also bring up a fundamental point about the rpn logic – although it has its roots firmly in the Forth language, it makes absolutely no attempt to replicate Forth's flow control logic – this is provided by the hosting language (in this case, Python).

Also note – this graph is built 'blind' – we don't know and don't care if it consists entirely of files which contain both audio and video or not, and the same graph can be used to output audio or video only (without the additional processing requirements of the superfluous component).

In terms of use, the following essentially reiterates the loop from the opening hello world example but shows where the process request would be placed:

input = rpn.pop( )
input.set_process_flags( openmedialib.audio |  openmedialib.image )
frame = input.fetch( )
store = openmedialib.create_store( “output.mpg”, frame )
if store.init( ):
	i = 1
	while i < input.get_frames( ):
		if not store.push( frame ): break
		input.seek( i, False )
		frame = input.fetch( )
		i += 1
	store.complete( )