[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
Hi,
Would you consider adding this information to the wiki?
Dermot.
--
------- 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,
file).
demux_t : it understands a format of encapsulation (like AVI, MPEG-PS),
it extracts the elementary stream(s), and it handles the
seeking
part.
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
part.
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
itself.
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,
the
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
discarded)
// 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
demux/access_demux
at the end).
(All others ES_OUT_CONTROL_* are used by the core, and you don't need
them).
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