1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ps.c,v 1.7 2003/02/24 10:45:55 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>
42 #elif defined( _MSC_VER ) && defined( _WIN32 ) && !defined( UNDER_CE )
50 /*****************************************************************************
52 *****************************************************************************/
53 static int Open ( vlc_object_t * );
54 static void Close ( vlc_object_t * );
56 static int AddStream( sout_instance_t *, sout_input_t * );
57 static int DelStream( sout_instance_t *, sout_input_t * );
58 static int Mux ( sout_instance_t * );
60 static void SetWBE ( uint8_t *p, uint16_t v )
62 p[0] = ( v >> 8 )&0xff;
65 static void SetDWBE( uint8_t *p, uint32_t v )
67 SetWBE( p, ( v >> 16 )&0xffff );
68 SetWBE( p + 2, v & 0xffff );
70 #define ADD_DWBE( p_buff, v ) \
71 SetDWBE( (p_buff)->p_buffer + i_buffer, (v) ); \
74 /*****************************************************************************
76 *****************************************************************************/
78 set_description( _("PS muxer") );
79 set_capability( "sout mux", 50 );
81 set_callbacks( Open, Close );
84 typedef struct ps_stream_s
92 typedef struct sout_mux_s
107 /*****************************************************************************
109 *****************************************************************************/
110 static int Open( vlc_object_t *p_this )
112 sout_instance_t *p_sout = (sout_instance_t*)p_this;
115 msg_Info( p_sout, "Open" );
117 p_mux = malloc( sizeof( sout_mux_t ) );
119 p_sout->pf_mux_capacity = NULL;
120 p_sout->pf_mux_addstream = AddStream;
121 p_sout->pf_mux_delstream = DelStream;
122 p_sout->pf_mux = Mux;
123 p_sout->p_mux_data = (void*)p_mux;
124 p_sout->i_mux_preheader = 30; // really enough for a pes header
126 p_mux->i_stream_id_mpga = 0xc0;
127 p_mux->i_stream_id_a52 = 0x80;
128 p_mux->i_stream_id_mpgv = 0xe0;
129 p_mux->i_audio_bound = 0;
130 p_mux->i_video_bound = 0;
131 p_mux->i_system_header = 0;
132 p_mux->i_pes_count = 0;
137 /*****************************************************************************
139 *****************************************************************************/
141 static void Close( vlc_object_t * p_this )
143 sout_instance_t *p_sout = (sout_instance_t*)p_this;
144 sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
145 sout_buffer_t *p_end;
147 msg_Info( p_sout, "Close" );
149 p_end = sout_BufferNew( p_sout, 4 );
150 SetDWBE( p_end->p_buffer, 0x01b9 );
152 sout_AccessOutWrite( p_sout->p_access, p_end );
156 p_sout->p_mux_data = NULL;
160 static int AddStream( sout_instance_t *p_sout, sout_input_t *p_input )
162 sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
163 ps_stream_t *p_stream;
165 msg_Dbg( p_sout, "adding input" );
166 p_input->p_mux_data = (void*)p_stream = malloc( sizeof( ps_stream_t ) );
168 switch( p_input->input_format.i_cat )
172 switch( p_input->input_format.i_fourcc )
174 case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
175 p_stream->i_stream_id = p_mux->i_stream_id_mpgv;
176 p_mux->i_stream_id_mpgv++;
177 p_mux->i_video_bound++;
184 switch( p_input->input_format.i_fourcc )
186 case VLC_FOURCC( 'a', '5', '2', ' ' ):
187 case VLC_FOURCC( 'a', '5', '2', 'b' ):
188 p_stream->i_stream_id = p_mux->i_stream_id_a52 | ( 0xbd << 8 );
189 p_mux->i_stream_id_a52++;
190 p_mux->i_audio_bound++;
192 case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
193 p_stream->i_stream_id = p_mux->i_stream_id_mpga;
194 p_mux->i_stream_id_mpga++;
195 p_mux->i_audio_bound++;
206 msg_Dbg( p_sout, "adding input stream_id:0x%x [OK]", p_stream->i_stream_id );
210 static int DelStream( sout_instance_t *p_sout, sout_input_t *p_input )
212 ps_stream_t *p_stream =(ps_stream_t*)p_input->p_mux_data;
214 msg_Dbg( p_sout, "removing input" );
222 static int MuxWritePackHeader( sout_instance_t *p_sout,
225 sout_buffer_t *p_hdr;
229 i_src = i_dts * 9 / 100;
231 p_hdr = sout_BufferNew( p_sout, 18 );
232 bits_initwrite( &bits, 14, p_hdr->p_buffer );
233 bits_write( &bits, 32, 0x01ba );
234 bits_write( &bits, 2, 0x01 ); // FIXME ??
235 bits_write( &bits, 3, ( i_src >> 30 )&0x07 );
236 bits_write( &bits, 1, 1 );
237 bits_write( &bits, 15, ( i_src >> 15 )&0x7fff );
238 bits_write( &bits, 1, 1 );
239 bits_write( &bits, 15, i_src&0x7fff );
240 bits_write( &bits, 1, 1 );
242 bits_write( &bits, 9, 0 ); // src extention
243 bits_write( &bits, 1, 1 );
245 bits_write( &bits, 22, 0/8/50); // FIXME
246 bits_write( &bits, 1, 1 );
247 bits_write( &bits, 1, 1 );
248 bits_write( &bits, 5, 0x1f ); // FIXME reserved
249 bits_write( &bits, 3, 0 ); // stuffing bytes
251 sout_AccessOutWrite( p_sout->p_access, p_hdr );
256 static int MuxWriteSystemHeader( sout_instance_t *p_sout )
258 sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
259 sout_buffer_t *p_hdr;
262 p_hdr = sout_BufferNew( p_sout, 12 );
264 bits_initwrite( &bits, 12, p_hdr->p_buffer );
265 bits_write( &bits, 32, 0x01bb );
266 bits_write( &bits, 16, 12 - 6);
267 bits_write( &bits, 1, 1 );
268 bits_write( &bits, 22, 0 ); // FIXME rate bound
269 bits_write( &bits, 1, 1 );
271 bits_write( &bits, 6, p_mux->i_audio_bound );
272 bits_write( &bits, 1, 0 ); // fixed flag
273 bits_write( &bits, 1, 0 ); // CSPS flag
274 bits_write( &bits, 1, 0 ); // system audio lock flag
275 bits_write( &bits, 1, 0 ); // system video lock flag
277 bits_write( &bits, 1, 1 ); // marker bit
279 bits_write( &bits, 5, p_mux->i_video_bound );
280 bits_write( &bits, 1, 0 ); // packet rate restriction flag
281 bits_write( &bits, 7, 0x7f ); // reserved bits
283 /* FIXME missing stream_id ... */
285 sout_AccessOutWrite( p_sout->p_access, p_hdr );
290 /* return stream number to be muxed */
291 static int MuxGetStream( sout_instance_t *p_sout,
299 for( i = 0, i_dts = 0, i_stream = -1; i < p_sout->i_nb_inputs; i++ )
303 p_fifo = p_sout->pp_inputs[i]->p_fifo;
305 if( p_fifo->i_depth > 1 )
307 sout_buffer_t *p_buf;
309 p_buf = sout_FifoShow( p_fifo );
310 if( i_stream < 0 || p_buf->i_dts < i_dts )
312 i_dts = p_buf->i_dts;
318 return( -1 ); // wait that all fifo have at least 2 packets
324 *pi_stream = i_stream;
335 static int Mux ( sout_instance_t *p_sout )
337 sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
343 sout_input_t *p_input;
344 ps_stream_t *p_stream;
346 sout_buffer_t *p_data;
348 if( MuxGetStream( p_sout, &i_stream, &i_dts ) < 0 )
353 p_input = p_sout->pp_inputs[i_stream];
354 p_fifo = p_input->p_fifo;
355 p_stream = (ps_stream_t*)p_input->p_mux_data;
357 if( p_mux->i_pes_count % 30 == 0)
359 MuxWritePackHeader( p_sout, i_dts );
362 if( p_mux->i_pes_count % 300 == 0 )
364 // MuxWriteSystemHeader( p_sout );
367 p_data = sout_FifoGet( p_fifo );
368 E_( EStoPES )( p_sout, &p_data, p_data, p_stream->i_stream_id, 1);
369 sout_AccessOutWrite( p_sout->p_access, p_data );
371 p_mux->i_pes_count++;