[vlc-devel] Re: access_demux versus access2 - trying to understand how to write a VCD plugin
R. Bernstein
rocky at panix.com
Fri Dec 24 06:32:35 CET 2004
Thanks for the more high-level overview. It helps quite a bit,
although, alas, a full-feature VCD plugin is going to be a bit more
involved. (Even if it is cleaner and more doable than it was a year
ago). Happy Holiday!
Laurent Aimar writes:
> 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).
>
> --
> fenrir
>
> --
> This is the vlc-devel mailing-list, see http://www.videolan.org/vlc/
> To unsubscribe, please read http://developers.videolan.org/lists.html
--
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