OpenMediaLib User and Development Guide

Putting it All Together

It is acknowledged that the above is rather abstract, so let's continue by making it a bit more concrete. We'll take a traditional video editor as our application and model it into the RPN filter graph system:

track 1: +------------------------+                        +------------------+
         |   input1               |                        |input3            |
         +------------------------+                        +------------------+
         |   filter               |                        |filter            |
         +------------------------+                        +------------------+

track 2:               +----------------------------------+
                       |               input2             |
                       +----------------------------------+

We interpret it as 4 filter graphs:

          /--- FG0 ---//--- FG1 ---//------- FG2 ---------//------ FG3 -------/

We also typically composite the results on to a background or canvas (typically, this is just a black image – you can picture this as being introduced as track 0 and it'll stretch for the duration of the longest track [track 1 in this case]).

Internally, we hook up our graphs as follows:

    FG0: bg input1 filter:filter filter:composite

    FG1: bg input1 filter:filter input2 filter:composite filter:composite

    FG2: bg input2 filter:composite

    FG3: bg input3 filter:filter filter:composite

Notes:

1) the FGs need to be constructed on demand (ie: when you cross from one section to the next) 2) in order to satisfy 1, we need to be able to construct and deconstruct the graphs to reuse the same objects 3) the objects in the multitrack are not the physical nodes - they're proxies which allow the identification of the node

Interfaces:

input_type:

		// Property object
		pcos::property_container properties( )

		// Basic information
		virtual const openpluginlib::wstring get_uri( ) const = 0;
		virtual const openpluginlib::wstring get_mime_type( ) const = 0;
		virtual bool has_video( ) const = 0;
		virtual bool has_audio( ) const = 0;

		// Audio/Visual
		virtual int get_frames( ) const = 0;
		virtual bool is_seekable( ) const = 0;

		// Visual
		virtual int get_video_streams( ) const = 0;
		
		// Audio
		virtual int get_audio_streams( ) const = 0;

		// Set video and audio streams
		virtual bool set_video_stream( const int ) { return false; }
		virtual bool set_audio_stream( const int ) { return false; }

		void set_process_flags( int flags )
		int get_process_flags( )

		// Default seek functionality
		virtual void seek( const int position, const bool relative = false )
		virtual int get_position( ) const

		// Virtual frame fetch method
		virtual frame_type_ptr fetch( ) = 0;

		// Allow the app to refresh a cached frame
		virtual void refresh_cache( frame_type_ptr ) { }
store_type:

		// Property object
		pcos::property_container properties( )

		// Initialise method
		virtual bool init( )

		// Push a frame to the store
		virtual bool push( frame_type_ptr ) = 0;

		// Tell the store to flush all pending frames, while returning the
		// one that was pending. The default implementation applies when 
		// the store doesn't queue frames.
		virtual frame_type_ptr flush( )

		// Playout all queued frames and return when done. The default
		// implementation applies when the store doesn't queue frames.
		virtual void complete( )

		// Allows the store to dictate when it is running empty (ie: any
		// realtime store such as an audio player or device feed needs more
		// frames in order to provide smooth playout)
		virtual bool empty( )
filter_type: