Sunday, 30 January 2011

Analyse Xingmux Plugin

xingmux adds a Xing header to MP3 files. This contains information about the duration and size
of the file and a seek table and is very useful for getting an almost correct duration and better
seeking on VBR MP3 files.

This element will remove any existing Xing, LAME or VBRI headers from the beginning of the file.

Pad templates and the element details are registered with the plugin during the gst_xing_mux_base_init()

GStreamer uses a type system to ensure that the data passed between elements is in a recognized format

pad templates are registered during the gst_xing_mux_base_init () function. Pads are created from these
templates in the gst_xing_mux_init () function using gst_pad_new_from_template (). The
template can be retrieved from the element class using gst_element_class_get_pad_template()

method 1 and 2 are doing the same, but what's the difference?


1.
GstElementClass *klass = GST_ELEMENT_CLASS (xingmux_class);
gst_pad_new_from_template (gst_element_class_get_pad_template (klass,"sink"), "sink");
gst_pad_new_from_template (gst_element_class_get_pad_template (klass,"src"), "src");

2.
gst_pad_new_from_static_template (&gst_xing_mux_sink_template, "sink");
gst_pad_new_from_static_template (&gst_xing_mux_src_template, "src");

xingmux has a sinkpad and a srcpad, it supports mpeg version 1 audio, layer 1 to 3,
any channel at any samplerate


85 static GstStaticPadTemplate gst_xing_mux_sink_template =                                                                  
86 GST_STATIC_PAD_TEMPLATE ("sink",                                                                                          
87     GST_PAD_SINK,                                                                                                         
88     GST_PAD_ALWAYS,                                                                                                       
89     GST_STATIC_CAPS ("audio/mpeg, "                                                                                       
90         "mpegversion = (int) 1, " "layer = (int) [ 1, 3 ]")); 

initialise the class only once during the gst_xing_mux_class_init()
(specifying what signals, arguments and virtual functions the class has and setting up global state)

The primary and most important way of controlling how an element behaves, is through GObject
properties. GObject properties are defined in the _class_init () function.

gst_xing_mux_init()


  • initialize the new element
  • instantiate pads and add them to element
  • set pad calback functions
  • initialize instance structure

    gst_pad_set_setcaps_function()is called during caps negotiation,
    This is the process where the linked pads decide on the streamtype that will transfer

    Caps negotiation is the process where elements configure themselves and each other for streaming a
    particular media format over their pads.

    between them, here using
    gst_pad_set_setcaps_function (xing->sinkpad, GST_DEBUG_FUNCPTR (gst_pad_proxy_setcaps));

    If at all possible, your element should derive from one of the new base classes (Pre-made base classes).
    If you use a base class, you will rarely have to handle state changes yourself. All you have to do is
    override the base class’s start() and stop() virtual functions (might be called differently depending on the
    base class) and the base class will take care of everything for you.

    Do not g_assert for unhandled state changes; this is taken care of by the GstElement base class.

Test Pipeline:gst-launch-0.10 filesrc location=test.mp3 ! xingmux ! filesink location=test2.mp3

additional: function plugin_init() register the element when the plugin is loaded, is in the source file plugin.c under the same folder gst-plugins-ugly/gst/mpegaudioparse

meego play rmvb avi mp4 medio file

My notebook is Asus EeePC 1001px, with meego v1.1
If you can not play the Big_Buck_Bunny.ogv.

Check whether your notebook's hardware graphic acceleration is enabled:
glxinfo | grep "renderer string"
My EeePC output is: "/OpenGL renderer string: Mesa DRI Intel(R) IGD GEM 20100330 DEVELOPMENT x86/MMX/SSE2/ ".
If your output is: "/OpenGL renderer string: Software Rasterizer/", that means acceleration is not fully enabled, your graphics driver might not be capable. Maybe this is the reason that why your notebook can't play video.

For mp3,mp4,avi,rmvb and so on in meego, there's no non-free codecs gstreamer packages form Meego Official site. You can try this command to see the gstreamer related packages.
zypper se gst
In my notebook, there is only gst-plugins-bad-free, but no gst-plugins-bad. We downloaded the gstremer source from Gstreamer Official Website, built and installed to Our EeePC. Then I played non-free types quite smoothly.

Gstreamer Time & Sync

GstClock


Frist some introduce words:

absolute_time: the current time get from GstClock (monotonically increasing time)

running_time:the total time spent in the PLAYING state

base_time:defined as the absolute_time minus the running_time at the time when the pipeline is set to PLAYING

stream_time:the position in the stream(between 0 and the total duration)

GStreamer can use different clocks:


  • system time (with g_get_current_time() and with microsecond accuracy)
  • soundcards and other devices time(better, use get_clock in some elements to get a clock)
  • a network source based on packets received + timestamps in those packets (a typical example is an RTP source)

time is always expessed in nanoseconds, so I think there must have a conversion between different time types.

pipeline state and running_time:

  • NULL/READY, the running_time is undefined
  • PAUSED, the running_time remains at the time when it was last PAUSED
  • PLAYING, the running_time is the delta between the absolute_time and the base time
  • after a flushing seek, the running_time is set to 0(redistribute a new base_time to implement)

    running_time = absolute_time - base_time(In the PLAYING state)

GstBuffer

The GstBuffer timestamps and the preceeding NEW_SEGMENT event define a transformation of the buffer timestamps to running_time

B: GstBuffer

  • B.timestamp = buffer timestamp (GST_BUFFER_TIMESTAMP)

NS: NEWSEGMENT event preceeding the buffers

  • NS.start: start field in the NEWSEGMENT event
  • NS.stop: stop field in the NEWSEGMENT event
  • NS.rate: rate field of NEWSEGMENT event
  • NS.abs_rate: absolute value of rate field of NEWSEGMENT event(By default a pipeline will play from position 0 to
    the total duration of the media at a rate of 1.0)
  • NS.time: time field in the NEWSEGMENT event
  • NS.accum: total accumulated time of all previous NEWSEGMENT events. This field is kept in the GstSegment structure


    if (NS.rate > 0.0)
        B.running_time = (B.timestamp - NS.start) / NS.abs_rate + NS.accum
    else
        B.running_time = (NS.stop - B.timestamp) / NS.abs_rate + NS.accum
    

  • And we also got:

    stream_time = (B.timestamp - NS.start) * NS.abs_applied_rate + NS.time

  • This formula is typically used in sinks to report the current position in
    an accurate and efficient way:

    stream_time = (absolute_time - base_time - NS.accum) * NS.abs_rate * NS.abs_applied_rate + NS.time

Synchronisation

There are two ways to get the running_time:

  • using the clock and the element's base_time with:

    C.running_time = absolute_time - base_time

  • using the buffer timestamp and the preceeding NEWSEGMENT event as (assuming positive playback rate):

    B.running_time = (B.timestamp - NS.start) / NS.abs_rate + NS.accum

  • For synchronisation the following must hold:

    B.running_time = C.running_time

  • expaning:

    B.running_time = absolute_time - base_time

  • or:

    absolute_time = B.running_time + base_time

  • The absolute_time when a buffer with B.running_time should be played is noted with B.sync_time. Thus:

    B.sync_time = B.running_time + base_time