[vlc-devel] Fwd: Re: access_demux versus access2 - trying to understand how to write a VCD plugin

Dermot McGahon dermot at dspsrv.com
Mon May 30 17:30:44 CEST 2005


Would you consider adding this information to the wiki?


------- Forwarded message -------
From: "Laurent Aimar" <fenrir at via.ecp.fr>
To: vlc-devel at videolan.org
Subject: [vlc-devel] Re: access_demux versus access2 - trying to  
understand how to write a VCD plugin
Date: Thu, 23 Dec 2004 15:44:03 -0000

On Thu, Dec 23, 2004, R. Bernstein wrote:
> Since the first time I looked at videolan in to write a VCD plugin
> with playback control, a great deal seems to have changed.
> One thing that hasn't is the lack of developer information or
> documentation. So I look at close source code and the two things that
> seem the most relevant are dvdnav.c and v4l.c.
> The things that the VCD plugin needs to do (which it doesn't right
> now) is detect changes in streams between still-frame MPEGs and motion
> MPEGs which may have different aspect ratios. Also it needs to handle
> key events.
> Looking at dvdnav.c and v4l.c I see neither uses
> set_capability("access2") like the VCD and CDDA plugins are, but
> set_capability("access_demux") instead. It seems like they provide
> both the input reading part ("access") as well as the some demuxing
> part at least to be able to signal the kinds of stream changes and
> input events mentioned above.

The general(main) architecture of vlc input is

  access_t -> stream_t -> demux_t -> es_out_t

You have
  access_t : it does the reading part ('protocol' specific, like http,  
  demux_t  : it understands a format of encapsulation (like AVI, MPEG-PS),
             it extracts the elementary stream(s), and it handles the  

The core provides:
  stream_t : it is the glue between access_t and demux_t (and add a layer
             of abstraction). It also adds a buffering system.
  es_out_t : it handles the ES selection, the packetization and decoding  
             it converts PTS/DTS given by demuxer in nice system date, and
             it controls the speed of the input (es_out_Send() is blocking).

  This way work swell when a demuxer has a really simple relation with the
access. But some time, the access part (reading) and the demuxer part
(demuxing and seeking) are really tied together. For those cases, a
access_demux_t can be used instead:

  access_demux_t -> es_out_t

  (No more access and no more stream_t).
  The input core will see the access_demux_t as a demux_t except for a few
control (access_demux_t->pf_control).
  The field access_demux_t->s is NULL as it has to do the reading part  
  The access_demux_t should provide (as all demuxers):
   - pf_demux: it will read data, demux them and send them to es_out_t.
   - pf_control: various demuxer controls, that the input will call.
  A few DEMUX_* are mandatory (see include/vlc_demux.h)

> Lastly question is on es_out_Control (a static inline function which
> mostly calls out->pf_control) and the other es_out_* routines. How
> does one understand what do what they require or how to use, I guess
> specifically for MPEG streams.

About es_out_t <-> demux_t the general case will be:
  es_format_t fmt;
  es_out_id_t *p_es;

  // First, declare the ES (at anytime, but the best for user/interface, is
the earlier)

  es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( 'm', 'p', 'g', 'a' ) );
  fmt.XXX = XXX;
  p_es = es_out_Add( p_demux->out, &fmt );

  // Now when demuxing:

  // If you know that you have a discontinuity (but no need after a seek,  
  input core takes care of that case) then reset the PCR
  if( i_have_detected_a_discontinuity )
      es_out_Control( p_demux->out, p_es, ES_CONTROL_RESET_PCR );

  // You have to send PCR (one a least before the first packet).
  if( i_have_a_new_pcr )
     int64_t i_pcr = my_pcr_in_microsecond;
     es_out_Control( p_demux->out, p_es, ES_CONTROL_SET_PCR, i_pcr );

  // Send data to the decoder (if no decoder, then the data will be  
  // Fill the block_t with the right info before.
  block_t *p_data;
  p_data = block_New( p_demux, my_data_size );
  p_data->i_buffer = my_buffer_size; // (not mandatory, block_New does it).
  memcpy( p_data->p_buffer, my_data, my_data_size );
  if( i_have_a_new_dts )
      p_data->i_dts = my_dts_in_microsecond;
  if( i_have_a_new_pts )
      p_data->i_pts = my_pts_in_microsecond;
  if( is_video_trakc && i_know_the_data_frame_type )
     if( is_i_frame )
         p_data->i_flags |= BLOCK_FALG_TYPE_I;
     else if( is_p_frame )
         p_data->i_flags |= BLOCK_FALG_TYPE_P;
     else if( is_b_frame )
         p_data->i_flags |= BLOCK_FALG_TYPE_B;
     else if( i_only_know_it_is_not_a_key_frame )
         p_data->i_flags |= BLOCK_FALG_TYPE_PB;

  if( i_have_the_sample_length )
      p_data->i_length = my_length_in_microsecond;

  es_out_Send( p_demux->out, p_es, p_data );

  You can do a es_out_Del( p_demux->out, p_es ) to remove a specific ES
  before the end of the input stream.
  (The core will remove all remaining ES after unloading the  
at the end).

(All others ES_OUT_CONTROL_* are used by the core, and you don't need  
Have a look at include/vlc_es_out.h).

  I hope this will help. If you have others questions, don't hesitate.
(but I won't be able to answer before january).

This is the vlc-devel mailing-list, see http://www.videolan.org/vlc/
To unsubscribe, please read http://developers.videolan.org/lists.html

More information about the vlc-devel mailing list