In this document we describe how we can obtain various properties
of the pipeline we are running.

we have 5 possible ways to get information, each one of these
methods focus on one particular property of the pipeline.

 - caps: this is a description of the media type that flows between
         2 pads.
 - metadata: non essential extra (human readable) information about
         the stream, like author, copyright, name etc..
 - streaminfo: information about the stream as encoded into the
         stream itself.
 - pad/element queries: information about the stream as it is being
         processed.
 - pad/element convert: information about the relation between formats
         in a streams as it is being processed.

note that element properties are not included in this list. Element
properties are only used to configure the codec/element.

caps, metadata, streaminfo are supposed to remain fairly static during
the stream. The queries/converts can be done on demand.  The reason
for this is that caps/metadata/streaminfo is quite expensive and 
could degrade pipeline performance.


Caps.
-----

Caps are automatically set on pads by the core when two pads agree
on a media type. This automatically means that the caps are fixed.

Since caps is a property of the pad and the g_object_notify() mechanism
is used to signal a change, the user can either connect a "notify" 
signal handler to the pad or connect to the "deep_notify" signal on
a parent pipeline.

The caps notifications are useful if you want to know what kind of
media is passing through pads. You can, for example, report to the
user how the video or audiosink is configured or what kind of
media some plugin is producing/accepting.

So, always use the caps to find out the channels/samplerate/size
of the media.


Metadata
--------

Metadata is a GstCaps element property (named "metadata") that contains
additional information encoded into the stream that doesn't say anything
about the media type of the stream itself.

Metadata are typically human readable information like author, copyright,
title, ... and can be displayed by the application as-is.

An element with a "metadata" property is supposed to g_object_notify that
property when the metadata changes so that the app can connect a signal
handler to the property or use the "deep_notify" signal to get the 
notification.


Streaminfo
----------

Streaminfo is a GstCaps element property (named "streaminfo") that contains
additional information about the stream that is not stricly required to
specify the media type of the stream.

Streaminfo is typically the length, bitrate, framerate, flags, ... of the
stream. 

It is important to note that this information should be derived from the 
stream itself and might not be correct for the pipeline being processed.
Let's illustrate this with an example:

 - an mp3 stream has an id3 tags that contains the length of the stream 
   (TLEN).
 - we cut the mp3 stream in half

 The actual length doesn't match the stated length as encoded in the id3
 tags, so the TLEN tag should be put in the streaminfo and the actual
 length should be queried with a pad_query.

So, be careful when showing streaminfo as-is in an app.

Queries
-------

Queries can be performed on pads and elements and are used to get 
information about the current stream. The value is a single gint64
in a specific format. 

example:

 - the query (GST_QUERY_TOTAL, GST_FORMAT_TIME) will return the total
   amount of time this pad/element will run.

 - the query (GST_QUERY_POSITION, GST_FORMAT_UNITS) will return the 
   current position of the stream expressed in units (units are samples,
   frames, bytes, ... depending on the media type of the stream)

two methods exist to perform a query:

 - gboolean gst_pad_query (GstPad *pad, GstQueryType type, 
                           GstFormat *format, gint64 *value);

and:

 - gboolean gst_element_query (GstElement *element, GstQueryType type, 
                               GstFormat *format, gint64 *value);

if you want to get the total duration of a stream or the current position,
you need to use a pad query. A pad query can fail (method returns FALSE),
this usually means that the duration is not known or that not enough data
has been processed to report the correct value.

the possible queries that can be performed on a pad/element can be obtained
with

 - const GstQueryType* gst_pad_get_query_types (GstPad *pad);
 
and

 - const GstQueryType* gst_element_get_query_types (GstElement *element);

These functions return an array of GstQueryTypes (last element == 0). you
can loop over the array to see what is supported or do 

 - gboolean gst_queries_contains (const GstQueryType *types, GstQueryType type);

to see if a specific format is contained in the list.

The value reported by a pad query can be considered correct or 
as-good-as-can-be. Elements that support pad queries must do the best
they can to report correct values.


Convert
-------

The convert functions are used to query an element/pad for the relationship
between two formats that it supports. For example:

suppose we want to know how many frames a particular video decoder will
produce in one second, we ask it to convert its concept of 1 SECOND into
1 UNIT (frames in the context of video). so,

 GstFormat format = GST_FORMAT_UNITS;
 
 res = gst_pad_convert (pad, GST_FORMAT_TIME, GST_SECOND,
                        &format, &value);

if res == TRUE, value will contain the framerate of the video, of course 
this framerate will only contain the integral part. If you want more
accuracy, use 1000 * GST_SECOND and divide the result by 1000 to get
a fractional part.

All other neat things can be done too, look at the typical cdplayer
plugin for example. It defines a new format "track". Now you can
ask it to convert a TRACK to TIME like this:


 GstFormat format = GST_FORMAT_TIME;
 track_format = gst_format_get_by_nick ("track");
 res = gst_pad_convert (pad, track_format, 1,
                        &format, &value);


This will convert 1 track to a time. of course we didn't (couldn't) specify
which track, but that's not a problem if you understand how the stream is
divided into different formats:

Take the total stream as containing bytes (indicated with + in figure) we 
can subdivide the (byte)stream in different formats.


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ... bytes
!   !   !   !   !   !   !   !   !   !   !   !   !   !   !   !   !    ... samples (units)
!                   !               !                   !            ... buffers
!                            !                                !      ... time
!                                                              !     ... track

The raw bytestream can be grouped in samples for example (for 16 bit stereo
int audio, 4 bytes == 1 sample) or we can divide it into time 
(44100 samples == 176400 bytes == 1 second) or into tracks 
(1 track could be 17640000 bytes or 100 seconds or 4410000 samples)

It is important to know that the stream starts at position 0 (for all formats)
and ends at position X (expressed in a specific format). now take this stream
divided into the track format:

0        200         500       700          1000
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .. bytes
! track0  ! track1    ! track2  ! track3     ! ...

if we now perform a pad convert from 100 bytes to the track format, we
get the value 0, as the region 0-100 bytes is contained in track0.
if we perform a pad convert from 600 bytes to track, we get the value
2, as track0->track2 contains the bytes 0-500.

We can also do: convert track1 to bytes, then we get 200. If we do
convert track2 to bytes, we get 500. Note that the conversions are
always performed relative to 0, so if we convert track2 to bytes, we
always get the number of bytes from track0->track2.

If we want to get the number of bytes of one particular track, we have
to subtract two convert values. Look at the following figure to understand
this. The --- defines the region we want to convert.


0        200         500       700          1000
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .. bytes
! track0  ! track1    ! track2  ! track3     ! ...

-----------             track1 -> bytes (1) (size of track0)

----------------------  track2 -> bytes (2) (size of track0 and track1)

           -----------  (2) - (1) = total bytes for track 1

Another example would be to get the bitrate of a decoder plugin, consider the
following example:

     (------------)
     ! mad        !
  - sink         src -
     (------------)

The element has a sinkpad that will take N bytes as input to produce M
samples (units) on its srcpad.
The rate at which it takes bytes is defined as the byterate of the 
stream (bitrate == byterate * 8). So, we do:

 GstFormat format = GST_FORMAT_BYTES;
 gint64 value;
 
 gst_pad_convert (mad->sinkpad, GST_FORMAT_TIME, GST_SECOND,
                  &format, &value);

..and we get the number of bytes this plugin takes in each second.
Again, note that this value is relative to 0, you can get an average
of a specific period by using the same subtract trick as above.


Element Properties
------------------

Element properties are used to configure an element. They should not be
used to describe media info, metadata fields, streaminfo fields or anything
other that doesn't involve codec configuration.

Several reasons:

 - metadata requires dynamic properties (one for each tag). This cannot be done
   with GObject properties.
 - you cannot signal a logical group of related properties (exposing stuff like
   samplerate/channels/encoding/... in different element properties is not a
   good idea.
 - stuff like length an position depend on the pads of the element, you cannot
   sanely expose a property for each pad to describe this.
 - element properties can only report stuff with one type. If your property
   exposes something like "total_length", you cannot make it both report this
   in time/bytes/samples/frames...
 - impossible to sanely implement convert with element properties.

