1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ps.c,v 1.12 2003/04/13 20:00:21 fenrir Exp $
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Eric Petit <titer@videolan.org>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
24 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
30 #include <sys/types.h>
37 #include <vlc/input.h>
48 /*****************************************************************************
50 *****************************************************************************/
51 static int Open ( vlc_object_t * );
52 static void Close ( vlc_object_t * );
54 static int Capability(sout_mux_t *, int, void *, void * );
55 static int AddStream( sout_mux_t *, sout_input_t * );
56 static int DelStream( sout_mux_t *, sout_input_t * );
57 static int Mux ( sout_mux_t * );
59 static void SetWBE ( uint8_t *p, uint16_t v )
61 p[0] = ( v >> 8 )&0xff;
64 static void SetDWBE( uint8_t *p, uint32_t v )
66 SetWBE( p, ( v >> 16 )&0xffff );
67 SetWBE( p + 2, v & 0xffff );
69 #define ADD_DWBE( p_buff, v ) \
70 SetDWBE( (p_buff)->p_buffer + i_buffer, (v) ); \
73 /*****************************************************************************
75 *****************************************************************************/
77 set_description( _("PS muxer") );
78 set_capability( "sout mux", 50 );
80 set_callbacks( Open, Close );
83 typedef struct ps_stream_s
106 /*****************************************************************************
108 *****************************************************************************/
109 static int Open( vlc_object_t *p_this )
111 sout_mux_t *p_mux = (sout_mux_t*)p_this;
112 sout_mux_sys_t *p_sys;
114 msg_Info( p_mux, "Open" );
116 p_sys = malloc( sizeof( sout_mux_sys_t ) );
118 p_mux->pf_capacity = Capability;
119 p_mux->pf_addstream = AddStream;
120 p_mux->pf_delstream = DelStream;
122 p_mux->p_sys = p_sys;
123 p_mux->i_preheader = 30; // really enough for a pes header
125 p_sys->i_stream_id_mpga = 0xc0;
126 p_sys->i_stream_id_a52 = 0x80;
127 p_sys->i_stream_id_mpgv = 0xe0;
128 p_sys->i_audio_bound = 0;
129 p_sys->i_video_bound = 0;
130 p_sys->i_system_header = 0;
131 p_sys->i_pes_count = 0;
136 /*****************************************************************************
138 *****************************************************************************/
140 static void Close( vlc_object_t * p_this )
142 sout_mux_t *p_mux = (sout_mux_t*)p_this;
143 sout_mux_sys_t *p_sys = p_mux->p_sys;
145 sout_buffer_t *p_end;
147 msg_Info( p_mux, "Close" );
149 p_end = sout_BufferNew( p_mux->p_sout, 4 );
150 SetDWBE( p_end->p_buffer, 0x01b9 );
152 sout_AccessOutWrite( p_mux->p_access, p_end );
157 static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_answer )
161 case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME:
162 *(vlc_bool_t*)p_answer = VLC_TRUE;
163 return( SOUT_MUX_CAP_ERR_OK );
165 return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );
169 static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
171 sout_mux_sys_t *p_sys = p_mux->p_sys;
172 ps_stream_t *p_stream;
174 msg_Dbg( p_mux, "adding input" );
175 p_input->p_sys = (void*)p_stream = malloc( sizeof( ps_stream_t ) );
177 switch( p_input->p_fmt->i_cat )
181 switch( p_input->p_fmt->i_fourcc )
183 case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
184 p_stream->i_stream_id = p_sys->i_stream_id_mpgv;
185 p_sys->i_stream_id_mpgv++;
186 p_sys->i_video_bound++;
193 switch( p_input->p_fmt->i_fourcc )
195 case VLC_FOURCC( 'a', '5', '2', ' ' ):
196 case VLC_FOURCC( 'a', '5', '2', 'b' ):
197 p_stream->i_stream_id = p_sys->i_stream_id_a52 | ( 0xbd << 8 );
198 p_sys->i_stream_id_a52++;
199 p_sys->i_audio_bound++;
201 case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
202 p_stream->i_stream_id = p_sys->i_stream_id_mpga;
203 p_sys->i_stream_id_mpga++;
204 p_sys->i_audio_bound++;
215 msg_Dbg( p_mux, "adding input stream_id:0x%x [OK]", p_stream->i_stream_id );
219 static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
221 ps_stream_t *p_stream =(ps_stream_t*)p_input->p_sys;
223 msg_Dbg( p_mux, "removing input" );
228 return( VLC_SUCCESS );
231 static int MuxWritePackHeader( sout_mux_t *p_mux,
234 sout_buffer_t *p_hdr;
238 i_src = i_dts * 9 / 100;
240 p_hdr = sout_BufferNew( p_mux->p_sout, 18 );
241 bits_initwrite( &bits, 14, p_hdr->p_buffer );
242 bits_write( &bits, 32, 0x01ba );
243 bits_write( &bits, 2, 0x01 ); // FIXME ??
244 bits_write( &bits, 3, ( i_src >> 30 )&0x07 );
245 bits_write( &bits, 1, 1 );
246 bits_write( &bits, 15, ( i_src >> 15 )&0x7fff );
247 bits_write( &bits, 1, 1 );
248 bits_write( &bits, 15, i_src&0x7fff );
249 bits_write( &bits, 1, 1 );
251 bits_write( &bits, 9, 0 ); // src extention
252 bits_write( &bits, 1, 1 );
254 bits_write( &bits, 22, 0/8/50); // FIXME
255 bits_write( &bits, 1, 1 );
256 bits_write( &bits, 1, 1 );
257 bits_write( &bits, 5, 0x1f ); // FIXME reserved
258 bits_write( &bits, 3, 0 ); // stuffing bytes
260 sout_AccessOutWrite( p_mux->p_access, p_hdr );
265 static int MuxWriteSystemHeader( sout_mux_t *p_mux )
267 sout_mux_sys_t *p_sys = p_mux->p_sys;
268 sout_buffer_t *p_hdr;
271 p_hdr = sout_BufferNew( p_mux->p_sout, 12 );
273 bits_initwrite( &bits, 12, p_hdr->p_buffer );
274 bits_write( &bits, 32, 0x01bb );
275 bits_write( &bits, 16, 12 - 6);
276 bits_write( &bits, 1, 1 );
277 bits_write( &bits, 22, 0 ); // FIXME rate bound
278 bits_write( &bits, 1, 1 );
280 bits_write( &bits, 6, p_sys->i_audio_bound );
281 bits_write( &bits, 1, 0 ); // fixed flag
282 bits_write( &bits, 1, 0 ); // CSPS flag
283 bits_write( &bits, 1, 0 ); // system audio lock flag
284 bits_write( &bits, 1, 0 ); // system video lock flag
286 bits_write( &bits, 1, 1 ); // marker bit
288 bits_write( &bits, 5, p_sys->i_video_bound );
289 bits_write( &bits, 1, 0 ); // packet rate restriction flag
290 bits_write( &bits, 7, 0x7f ); // reserved bits
292 /* FIXME missing stream_id ... */
294 sout_AccessOutWrite( p_mux->p_access, p_hdr );
299 /* return stream number to be muxed */
300 static int MuxGetStream( sout_mux_t *p_mux,
308 for( i = 0, i_dts = 0, i_stream = -1; i < p_mux->i_nb_inputs; i++ )
312 p_fifo = p_mux->pp_inputs[i]->p_fifo;
314 if( p_fifo->i_depth > 1 )
316 sout_buffer_t *p_buf;
318 p_buf = sout_FifoShow( p_fifo );
319 if( i_stream < 0 || p_buf->i_dts < i_dts )
321 i_dts = p_buf->i_dts;
327 return( -1 ); // wait that all fifo have at least 2 packets
333 *pi_stream = i_stream;
344 static int Mux ( sout_mux_t *p_mux )
346 sout_mux_sys_t *p_sys = p_mux->p_sys;
352 sout_input_t *p_input;
353 ps_stream_t *p_stream;
355 sout_buffer_t *p_data;
357 if( MuxGetStream( p_mux, &i_stream, &i_dts ) < 0 )
359 return( VLC_SUCCESS );
362 p_input = p_mux->pp_inputs[i_stream];
363 p_fifo = p_input->p_fifo;
364 p_stream = (ps_stream_t*)p_input->p_sys;
366 if( p_sys->i_pes_count % 30 == 0)
368 MuxWritePackHeader( p_mux, i_dts );
371 if( p_sys->i_pes_count % 300 == 0 )
373 // MuxWriteSystemHeader( p_sout );
376 p_data = sout_FifoGet( p_fifo );
377 E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1);
378 sout_AccessOutWrite( p_mux->p_access, p_data );
380 p_sys->i_pes_count++;