Added a drawing of a possible player architecture added plugin guidelines
authorWim Taymans <wim.taymans@gmail.com>
Sun, 23 Dec 2001 17:18:27 +0000 (17:18 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Sun, 23 Dec 2001 17:18:27 +0000 (17:18 +0000)
Original commit message from CVS:
Added a drawing of a possible player architecture
added plugin guidelines

docs/random/wtay/player.fig [new file with mode: 0644]
docs/random/wtay/plugin_guidelines [new file with mode: 0644]

diff --git a/docs/random/wtay/player.fig b/docs/random/wtay/player.fig
new file mode 100644 (file)
index 0000000..fa5c826
--- /dev/null
@@ -0,0 +1,33 @@
+#FIG 3.2
+Landscape
+Center
+Metric
+A4      
+100.00
+Single
+-2
+1200 2
+2 2 0 1 0 6 50 0 20 0.000 0 0 -1 0 0 5
+        5895 3465 8460 3465 8460 5175 5895 5175 5895 3465
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+        4905 1935 8640 1935 8640 5310 4905 5310 4905 1935
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+        2610 1935 4815 1935 4815 5310 2610 5310 2610 1935
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+        495 675 8685 675 8685 5400 495 5400 495 675
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+        675 1935 2430 1935 2430 3465 675 3465 675 1935
+4 0 0 50 0 0 12 0.0000 4 180 615 6210 3915 GstPlay\001
+4 0 0 50 0 0 12 0.0000 4 180 1485 6480 4455 - GStreamer (glib2)\001
+4 0 0 50 0 0 12 0.0000 4 180 1470 5130 2250 Bonobo Component\001
+4 0 0 50 0 0 12 0.0000 4 135 1275 5130 2700  - sliders/buttons\001
+4 0 0 50 0 0 12 0.0000 4 135 1260 5130 2925 - Gtk/Gnome etc\001
+4 0 0 50 0 0 12 0.0000 4 180 1245 5130 3150 - uses libgstplay\001
+4 0 0 50 0 0 12 0.0000 4 180 1095 2700 945 GstMediaPlay\001
+4 0 0 50 0 0 12 0.0000 4 180 1785 2745 1170 - app using components\001
+4 0 0 50 0 0 12 0.0000 4 180 1440 2700 2160 Bonobo component\001
+4 0 0 50 0 0 12 0.0000 4 180 1035 2700 2610 - playlist etc..\001
+4 0 0 50 0 0 12 0.0000 4 180 1395 855 2160 Other components\001
+4 0 0 50 0 0 12 0.0000 4 135 705 855 2610 - encoder\001
+4 0 0 50 0 0 12 0.0000 4 135 540 855 2835 - editor\001
+4 0 0 50 0 0 12 0.0000 4 60 240 855 3060 - ...\001
diff --git a/docs/random/wtay/plugin_guidelines b/docs/random/wtay/plugin_guidelines
new file mode 100644 (file)
index 0000000..2278f09
--- /dev/null
@@ -0,0 +1,295 @@
+
+This short document gives some guidelines to plugin writers.
+
+
+chain-based plugins
+===================
+
+ - the plugin has a chain function on each sink pad (can be the same function)
+
+! 
+! chain (GstPad *pad, GstBuffer *buffer) 
+! {
+!   MyElement *elem = MY_ELEMENT (gst_pad_get_parent (pad));
+!   GstBuffer *new_buffer;
+! 
+!   ...
+!   (process the buffer)
+!   ...
+! 
+!   /* you can push as many buffers (0 or more) as you want */
+!   while (!done) {
+!     ...
+!     (process some more
+!     ...
+!     gst_pad_push (elem->some_sink_pad, new_buffer);
+!     ...
+!     /* if you're like going to send a large amount of buffers
+!      * it's a good idea to call _yield from time to time after
+!      * the buffer has been pushed */
+!     (optional gst_element_yield (GST_ELEMENT (elem)); )
+!   }
+! }
+! 
+
+ - chain based functions are usually easy and recommended.
+ - use gst_element_yield if you are going to push a lot of buffers.
+
+
+
+loop-based plugins
+==================
+
+ - one loop function for the element.
+ - required for bytestream based plugins.
+
+simple case
+-----------
+  
+ - one pull at the start
+
+ - if you do something like this, you really should consider using a 
+   chain function as it can be significantly optimised by the scheduler.
+
+!
+! loop (GstElement *element) 
+! {
+!   MyElement *elem = MY_ELEMENT (element);
+!   GstBuffer *buffer;
+!   GstBuffer *new_buffer;
+! 
+!   buffer = gst_pad_pull (elem->sinkpad);
+!  
+!   ...
+!   (do something)
+!   ...
+!
+!   /* you can push as many buffers (0 or more) as you want */
+!   while (!done) {
+!     ...
+!     (process some more
+!     ...
+!     gst_pad_push (elem->some_sink_pad, new_buffer);
+!     ...
+!     /* if you're like going to send a large amount of buffers
+!      * it's a good idea to call _yield from time to time after
+!      * the buffer has been pushed */
+!     (optional gst_element_yield (GST_ELEMENT (elem)); )
+!   }
+! }
+!
+
+DONT!!
+
+- infinite loop
+
+!
+! loop (element)
+! {
+!   while (TRUE) {
+!     ...
+!     _pull ()
+!     ...
+!
+!     ...
+!     _push ()
+!     ...
+!   }
+! }
+!
+
+* you can fix this by either:
+
+ - setting the GST_ELEMENT_INFINITE_LOOP flag on the element. this is
+   not recommended, if all plugins in the pipeline (or depending on the
+   pipeline, some plugins) have this flag, the pipeline will not run.
+ - calling break; from time to time to get out of the loop. (duh, then
+   it's not an infinite loop anymore). beware that the next time the loop
+   function is called, it will be started from the top.
+ - calling gst_element_yield() from time to time (see NOTES). 
+ - this is fine (albeit rather useless, use a chain function):
+  !
+  ! loop (element)
+  ! {
+  !   ...
+  !   _pull ()
+  !   ...
+  !
+  !   ...
+  !   _push ()
+  !   ...
+  ! }
+  !
+ - so is this (albeit rather useless, consider removing the while and the _yield):
+  !
+  ! loop (element)
+  ! {
+  !   while (TRUE) {
+  !     ...
+  !     _pull ()
+  !     ...
+  !
+  !     ...
+  !     _push ()
+  !     ...
+  !     gst_element_yield (element);
+  !   }
+  ! }
+  !
+
+
+DONT!!
+
+- allocate data, loop, free data
+
+!
+! loop (element)
+! {
+!   
+!   (my funky malloc)
+!
+!   while (TRUE) {
+!
+!     ...
+!     _pull ()
+!     ...
+!
+!     ...
+!     _push ()
+!     ...
+!
+!     _yield ()
+!   }
+!
+!   (my funky free)
+!
+! }
+!
+
+ - the free will NEVER happen!.
+
+* You can fix this by:
+
+ - allocating/freeing data in the state change function
+ - you could think the following code would work too:
+  !
+  ! (*WRONG* example follows)
+  !
+  ! loop (element)
+  ! {
+  !   
+  !   (my funky malloc)
+  !
+  !   while (TRUE) {
+  !
+  !     ...
+  !     _pull ()
+  !     if (EOS)
+  !       break;
+  !
+  !     ...
+  !     _push ()
+  !     ...
+  !
+  !     _yield ()
+  !   }
+  !
+  !   (my funky free)
+  !
+  ! }
+  !
+   but it'll only free the data if the pipeline was shut down with
+   and EOS so don't try it. Besides, on EOS, a state change will happen
+   anyway so free the data there.
+
+
+bytestream/multiple pull case
+-----------------------------
+
+ - same as the simple case, but you can't use a chain based function unless
+   you want to make things a little harder then they should be.
+
+
+complicated case
+----------------
+
+ - push and pull are completely mixed.
+ - the flow is usually something like this:
+
+!
+! loop (element)
+! {
+!   
+!   while (TRUE) {
+!
+!     while (something) {
+!       ...
+!       do some _pull ()
+!       ...
+!       do some _push ()
+!       ...
+!       while (something_else) {
+!         ...
+!         if (testing)
+!           do some _pull ()
+!         ...
+!         do some _push ()
+!       }
+!     }
+!
+!     while (something_useful) {
+!       ...
+!       _push ()
+!       ...
+!     }
+!   }
+! }
+!
+(example made complicated on purpose, but vorbisdec comes close)
+
+ - you cannot call break to avoid infinite loops and there are loops that 
+   take a significant amount of time to execute, possibly pushing/pulling
+   a lot of buffers.
+
+* You can fix this by:
+
+ - inserting gst_element_yield () in sane places, don't exagerate because
+   every yield can potentially never return so you need to keep track of
+   allocations (see the NOTES below).
+
+
+NOTES:
+======
+
+ - a call to _yield() can never return. if you have data allocated on the
+   stack before the yield, keep a pointer to it in the element struct 
+   and free it in the state change function.
+
+
+IMPLEMENATION DETAILS
+=====================
+
+The infinite loops are only problematic if the scheduler chooses to select
+the plugin as an entry point in the chain. _yield() will be a nop if this is
+not the case. The scheduler will not select plugins with the INFINITE_LOOP
+flag set as entries in a chain.
+
+A _yield in an entry will hand over control to the main thread context, allowing
+state changes and other actions to be performed. It will basically exit the 
+_iterate() function. spending a long time in a loop will degrade app responsiveness
+because _iterate will take a long time.
+
+Calling yield, pulling, pushing can potentially never return because a state change
+might have happened, killing off execution of the plugin. pulling/pushing buffers
+will cause no leaks in this case because the core will free pending buffers in a
+state change to READY. The plugin must free allocated data/buffers itself in the state
+change function if the yield didn't retrun. 
+
+
+
+
+
+
+
+