OpenMediaLib User and Development Guide
- OpenMediaLib User Development Guide
- Introduction
- High Level Use
- Reverse Polish Notation
- Applying RPN to Video/Audio
- Clip Modifications
- Compositing
- Playlists
- Stack Manipulations
- Advanced Stack Usage
- Aspect Ratio Considerations
- The Encoding Filter Graph
- Compositing Revisited
- Really, Really Advanced Stack Usage
- General Audio Issues
- Python
- Interpolation
- Threading
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( )
