other-base.xml 14.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
<chapter id="chapter-other-base" xreflabel="Pre-made base classes">
  <title>Pre-made base classes</title>
  <para>
    So far, we've been looking at low-level concepts of creating any type of
    &GStreamer; element. Now, let's assume that all you want is to create an
    simple audiosink that works exactly the same as, say,
    <quote>esdsink</quote>, or a filter that simply normalizes audio volume.
    Such elements are very general in concept and since they do nothing
    special, they should be easier to code than to provide your own scheduler
    activation functions and doing complex caps negotiation. For this purpose,
    &GStreamer; provides base classes that simplify some types of elements.
    Those base classes will be discussed in this chapter.
  </para>

  <sect1 id="section-base-sink" xreflabel="Writing a sink">
    <title>Writing a sink</title>
    <para>
      Sinks are special elements in &GStreamer;. This is because sink elements
      have to take care of <emphasis>preroll</emphasis>, which is the process
      that takes care that elements going into the
      <classname>GST_STATE_PAUSED</classname> state will have buffers ready
      after the state change. The result of this is that such elements can
      start processing data immediately after going into the
      <classname>GST_STATE_PLAYING</classname> state, without requiring to
      take some time to initialize outputs or set up decoders; all that is done
      already before the state-change to <classname>GST_STATE_PAUSED</classname>
      successfully completes.
    </para>
    <para>
      Preroll, however, is a complex process that would require the same
      code in many elements. Therefore, sink elements can derive from the
      <classname>GstBaseSink</classname> base-class, which does preroll and
      a few other utility functions automatically. The derived class only
      needs to implement a bunch of virtual functions and will work
      automatically.
    </para>
    <para>
      The <classname>GstBaseSink</classname> base-class specifies some
      limitations on elements, though:
    </para>
    <itemizedlist>
      <listitem>
        <para>
          It requires that the sink only has one sinkpad. Sink elements that
          need more than one sinkpad, cannot use this base-class.
        </para>
      </listitem>
      <listitem>
        <para>
          The base-class owns the pad, and specifies caps negotiation, data
          handling, pad allocation and such functions. If you need more than
          the ones provided as virtual functions, then you cannot use this
          base-class.
        </para>
      </listitem>
      <listitem>
        <para>
          By implementing the <function>pad_allocate ()</function> function,
          it is possible for upstream elements to use special memory, such
          as memory on the X server side that only the sink can allocate, or
          even hardware memory <function>mmap ()</function>'ed from the kernel.
          Note that in almost all cases, you will want to subclass the
          <classname>GstBuffer</classname> object, so that your own set of
          functions will be called when the buffer loses its last reference.
        </para>
      </listitem>
    </itemizedlist>
    <para>
      Sink elements can derive from <classname>GstBaseSink</classname> using
      the usual <classname>GObject</classname> type creation voodoo, or by
      using the convenience macro <function>GST_BOILERPLATE ()</function>:
    </para>
    <programlisting>
GST_BOILERPLATE_FULL (GstMySink, gst_my_sink, GstBaseSink, GST_TYPE_BASE_SINK);

[..]

static void
gst_my_sink_class_init (GstMySinkClass * klass)
{
  klass->set_caps = [..];
  klass->render = [..];
[..]
}
    </programlisting>
    <para>
      The advantages of deriving from <classname>GstBaseSink</classname> are
      numerous:
    </para>
    <itemizedlist>
      <listitem>
        <para>
          Derived implementations barely need to be aware of preroll, and do
          not need to know anything about the technical implementation
          requirements of preroll. The base-class does all the hard work.
        </para>
        <para>
          Less code to write in the derived class, shared code (and thus
          shared bugfixes).
        </para>
      </listitem>
    </itemizedlist>
    <para>
      There are also specialized base classes for audio and video, let's look
      at those a bit.
    </para>

    <sect2 id="section-base-audiosink" xreflabel="Writing an audio sink">
      <title>Writing an audio sink</title>
      <para>
        Essentially, audio sink implementations are just a special case of a
        general sink. There are two audio base classes that you can choose to
        derive from, depending on your needs:
        <classname>GstBaseAudiosink</classname> and
        <classname>GstAudioSink</classname>. The baseaudiosink provides full
        control over how synchronization and scheduling is handled, by using
        a ringbuffer that the derived class controls and provides. The
        audiosink base-class is a derived class of the baseaudiosink,
        implementing a standard ringbuffer implementing default
        synchronization and providing a standard audio-sample clock. Derived
        classes of this base class merely need to provide a <function>_open
        ()</function>, <function>_close ()</function> and a <function>_write
        ()</function> function implementation, and some optional functions.
        This should suffice for many sound-server output elements and even
        most interfaces. More demanding audio systems, such as Jack, would
        want to implement the <classname>GstBaseAudioSink</classname>
        base-class.
      </para>
      <para>
        The <classname>GstBaseAusioSink</classname> has little to no
        limitations and should fit virtually every implementation, but is
        hard to implement. The <classname>GstAudioSink</classname>, on the
        other hand, only fits those systems with a simple <function>open
        ()</function> / <function>close ()</function> / <function>write
        ()</function> API (which practically means pretty much all of them),
        but has the advantage that it is a lot easier to implement. The
        benefits of this second base class are large:
      </para>
      <itemizedlist>
        <listitem>
          <para>
            Automatic synchronization, without any code in the derived class.
          </para>
        </listitem>
        <listitem>
          <para>
            Also automatically provides a clock, so that other sinks (e.g. in
            case of audio/video playback) are synchronized.
          </para>
        </listitem>
        <listitem>
          <para>
            Features can be added to all audiosinks by making a change in the
Piotr Fusik's avatar
Piotr Fusik committed
154
            base class, which makes maintenance easy.
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
          </para>
        </listitem>
        <listitem>
          <para>
            Derived classes require only three small functions, plus some
            <classname>GObject</classname> boilerplate code.
          </para>
        </listitem>
      </itemizedlist>
      <para>
        In addition to implementing the audio base-class virtual functions,
        derived classes can (should) also implement the
        <classname>GstBaseSink</classname> <function>set_caps ()</function> and
        <function>get_caps ()</function> virtual functions for negotiation.
      </para>
    </sect2>

    <sect2 id="section-base-videosink" xreflabel="Writing a general sink">
      <title>Writing a video sink</title>
      <para>
        Writing a videosink can be done using the
        <classname>GstVideoSink</classname> base-class, which derives from
        <classname>GstBaseSink</classname> internally. Currently, it does
        nothing yet but add another compile dependency, so derived classes
        will need to implement all base-sink virtual functions. When they do
        this correctly, this will have some positive effects on the end user
        experience with the videosink:
      </para>
      <itemizedlist>
        <listitem>
          <para>
            Because of preroll (and the <function>preroll ()</function> virtual
            function), it is possible to display a video frame already when
            going into the <classname>GST_STATE_PAUSED</classname> state.
          </para>
        </listitem>
        <listitem>
          <para>
            By adding new features to <classname>GstVideoSink</classname>, it
            will be possible to add extensions to videosinks that affect all of
Piotr Fusik's avatar
Piotr Fusik committed
195
            them, but only need to be coded once, which is a huge maintenance
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
            benefit.
          </para>
        </listitem>
      </itemizedlist>
    </sect2>
  </sect1>

  <sect1 id="section-base-src" xreflabel="Writing a source">
    <title>Writing a source</title>
    <para>
      In the previous part, particularly <xref
      linkend="section-scheduling-randomxs"/>, we have learned that some types
      of elements can provide random access. This applies most definitely to
      source elements reading from a randomly seekable location, such as file
      sources. However, other source elements may be better described as a
      live source element, such as a camera source, an audio card source and
      such; those are not seekable and do not provide byte-exact access. For
      all such use cases, &GStreamer; provides two base classes:
      <classname>GstBaseSrc</classname> for the basic source functionality, and
      <classname>GstPushSrc</classname>, which is a non-byte exact source
      base-class. The pushsource base class itself derives from basesource as
      well, and thus all statements about the basesource apply to the
      pushsource, too.
    </para>
    <para>
      The basesrc class does several things automatically for derived classes,
      so they no longer have to worry about it:
    </para>
    <itemizedlist>
      <listitem>
        <para>
          Fixes to <classname>GstBaseSrc</classname> apply to all derived
          classes automatically.
        </para>
      </listitem>
      <listitem>
        <para>
          Automatic pad activation handling, and task-wrapping in case we get
          assigned to start a task ourselves.
        </para>
      </listitem>
    </itemizedlist>
    <para>
      The <classname>GstBaseSrc</classname> may not be suitable for all cases,
      though; it has limitations:
    </para>
    <itemizedlist>
      <listitem>
        <para>
          There is one and only one sourcepad. Source elements requiring
          multiple sourcepads cannot use this base-class.
        </para>
      </listitem>
      <listitem>
        <para>
          Since the base-class owns the pad and derived classes can only
          control it as far as the virtual functions allow, you are limited
          to the functionality provided by the virtual functions. If you need
          more, you cannot use this base-class.
        </para>
      </listitem>
    </itemizedlist>
    <para>
      It is possible to use special memory, such as X server memory pointers
      or <function>mmap ()</function>'ed memory areas, as data pointers in
      buffers returned from the <function>create()</function> virtual function.
      In almost all cases, you will want to subclass
      <classname>GstBuffer</classname> so that your own set of functions can
      be called when the buffer is destroyed.
    </para>

    <sect2 id="section-base-audiosrc" xreflabel="Writing an audio source">
      <title>Writing an audio source</title>
      <para>
        An audio source is nothing more but a special case of a pushsource.
        Audio sources would be anything that reads audio, such as a source
        reading from a soundserver, a kernel interface (such as ALSA) or a
        test sound / signal generator. &GStreamer; provides two base classes,
        similar to the two audiosinks described in <xref
        linkend="section-base-audiosink"/>; one is ringbuffer-based, and
        requires the derived class to take care of its own scheduling,
        synchronization and such. The other is based on this
        <classname>GstBaseAudioSrc</classname> and is called
        <classname>GstAudioSrc</classname>, and provides a simple
        <function>open ()</function>, <function>close ()</function> and
        <function>read ()</function> interface, which is rather simple to
        implement and will suffice for most soundserver sources and audio
        interfaces (e.g. ALSA or OSS) out there.
      </para>
      <para>
        The <classname>GstAudioSrc</classname> base-class has several benefits
        for derived classes, on top of the benefits of the
        <classname>GstPushSrc</classname> base-class that it is based on:
      </para>
      <itemizedlist>
        <listitem>
          <para>
            Does syncronization and provides a clock.
          </para>
        </listitem>
        <listitem>
          <para>
            New features can be added to it and will apply to all derived
            classes automatically.
          </para>
        </listitem>
      </itemizedlist>
    </sect2>
  </sect1>

  <sect1 id="section-base-transform"
      xreflabel="Writing a transformation element">
    <title>Writing a transformation element</title>
    <para>
      A third base-class that &GStreamer; provides is the
      <classname>GstBaseTransform</classname>. This is a base class for
      elements with one sourcepad and one sinkpad which act as a filter
      of some sort, such as volume changing, audio resampling, audio format
      conversion, and so on and so on. There is quite a lot of bookkeeping
      that such elements need to do in order for things such as buffer
      allocation forwarding, passthrough, in-place processing and such to all
      work correctly. This base class does all that for you, so that you just
      need to do the actual processing.
    </para>
    <para>
      Since the <classname>GstBaseTransform</classname> is based on the 1-to-1
      model for filters, it may not apply well to elements such as decoders,
      which may have to parse properties from the stream. Also, it will not
      work for elements requiring more than one sourcepad or sinkpad.
    </para>
  </sect1>
</chapter>