<chapter><title>The Converter and the Reader</title>


<para>

The role of the couple (Reader, Converter) is to get raw data from
several medium (dvd, file, video encoder, satellite card), and to
convert it into valid TS packets. I choose to gather them in the same
section since they belong to the same thread.

Refer to <xref linkend="l-arch" endterm="t-arch"> to see the position of
converter between other parts of vls.

</para>

<sect1><title>The Converter</title>

<para>
The Converter - or MpegConverter - is a module that is responsible for
providing TS packets. Today, the modules implemented are ps2ts and
ts2ts, which functions talk by themselves.
</para>

<para>
As any modules in the VideoLAN server, the main class C_MpegConverter
is implemented in the main program : src/mpeg/converter.cpp . It is in
general better for a first overview to have a look at the .h defs (src/mpeg/converter.h) :
</para>

 <programlisting>
class C_MpegConverter : public C_Thread
{
public:
  (...)
  void Resume();
  void Suspend();
  void ShortPause();

protected:
  virtual void InitWork();
  virtual void StopWork();
  virtual void CleanWork();

  (...)
};
 </programlisting>

<para>
The C_MpegConverter inherits from the C_Thread, since it is the motor of
the source thread (Reader & Converter).
</para>

<para>
This class implements the basic functions of the converter, which
will be common to all the Converter modules (ps2ts, ts2ts). Resume(),
Suspend(), ShortPause() do all the common stuff to Init/Close the
Reader, and deal with the m_cCondition stuff for Suspending/Resuming the
streaming (see further).
</para>

<para>
But what is interesting are the virtual functions. In the present case,
they are declared as 'virtual' since there are re-implementation of the
basic InitWork(), StopWork() and CleanWork() of the C_Thread class. But
there are also virtuals as every Converter module will also re-implement
them : that will contitute the essence of a module. All the differences
between the modules will take place in thoses functions, and that's why
MpegConverter modules have been created.
</para>

<para>
As the C_MpegConverter inherits from C_Thread, the thread has to
be created. This is made in the Input modules (for example in the
Localinput.cpp, OnStartStreaming) :
</para>

<programlisting>
 // Create the converter
 C_MpegConverterModule* pConverterModule = (C_MpegConverterModule*)
                               C_Application::GetModuleManager()
                                       ->GetModule("mpegconverter",
                                                   strConverterType);
(...)
 pConverter = pConverterModule->NewMpegConverter(cConfig);
  // Create the Thread
 pConverter->Create();
</programlisting>

<para>
That's why we can say that the Input spawns the Converter (as well as
other parts of the TS chain : Reader, Streamer).
</para>

<para>
To suspend a stream, we use the thread structure : we block the
condition m_cCondition.
</para>

</sect1>

<sect1><title>Interfaces</title>
<para>
The two interfaces are Reader and the SyncFifo (to the TsStreamer).
</para>

<simplesect><title>Reader-Converter</title>

<para>
The member m_pReader is a reference to the MpegReader module used in
the streaming chain. This value is initialized during the creation
of the Converter, in the appropriate Input Module (have a look in
C_LocalInput::OnStartStreaming for example).
</para>

<para>
<mediaobject>
  <imageobject>
    <imagedata fileref="readerconv.eps" format="EPS" scalefit="1" scale="60">
  </imageobject>
  <imageobject>
    <imagedata fileref="readerconv.jpg" format="JPG">
  </imageobject>
  <textobject>
    <phrase>Sequence diagram</phrase>
  </textobject>
</mediaobject>
</para>


<para>
So, to get data, the converter makes direct calls to the Reader :
</para>

<programlisting>
 m_pReader->Read();
 m_pReader->Seek();
</programlisting>
</simplesect>

<simplesect><title>Converter SyncFifo</title>
<para>
The SyncFifo is called in the converter m_pHandler. m_pHandler is
declared in converter.h as an interface : I_TsPacketHandler, which is
the mother class of C_SyncFifo.
</para>

<para>
<mediaobject>
  <imageobject>
    <imagedata fileref="convfifo.eps" format="EPS" scalefit="1" scale="60">
  </imageobject>
  <imageobject>
    <imagedata fileref="convfifo.jpg" format="JPG">
  </imageobject>
  <textobject>
    <phrase>Sequence diagram</phrase>
  </textobject>
</mediaobject>
</para>

<para>
We call it SyncFifo because it is a fifo which is thread-safe, and allows synchro between source thread and consumer thread. Moreover, the I_TsPacketHandler used is declared as C_SyncFifo in the Input modules :
</para>

<programlisting>
C_SyncFifo* pBuffer;
(...)
cConfig.m_pHandler = pBuffer;
</programlisting>

<para>
So, the packet is send to the SyncFifo using the command : 
</para>

<programlisting>
m_pHandler->HandlePacket(pPacket);
</programlisting>

<para>
If for some reason the packet has to be trashed (pre-parsing, end of
stream, read error....), then the call to m_pHandler->HandlePacket() is
not made. However, one should not forget to set it back available in the
TsProvider though the command :
</para>

<programlisting>
m_pTsProvider->ReleasePacket(pPacket);
</programlisting>
</simplesect>
</sect1>

<sect1><title>The Reader</title>
<para>

There is not much to say more than reading the code... All the interest
locates in the implementation of Read() and Seek().

</para>
</sect1>

</chapter>

