1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: ps.c,v 1.1 2002/12/14 21:32:41 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_addstream = AddStream;
120 p_sout->pf_mux_delstream = DelStream;
121 p_sout->pf_mux = Mux;
122 p_sout->p_mux_data = (void*)p_mux;
124 p_mux->i_stream_id_mpga = 0xc0;
125 p_mux->i_stream_id_a52 = 0x80;
126 p_mux->i_stream_id_mpgv = 0xe0;
127 p_mux->i_audio_bound = 0;
128 p_mux->i_video_bound = 0;
129 p_mux->i_system_header = 0;
130 p_mux->i_pes_count = 0;
135 /*****************************************************************************
137 *****************************************************************************/
139 static void Close( vlc_object_t * p_this )
141 sout_instance_t *p_sout = (sout_instance_t*)p_this;
142 sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
143 sout_buffer_t *p_end;
145 msg_Info( p_sout, "Close" );
147 p_end = sout_BufferNew( p_sout, 4 );
148 SetDWBE( p_end->p_buffer, 0x01b9 );
150 p_sout->pf_write( p_sout, p_end );
154 p_sout->p_mux_data = NULL;
158 static int AddStream( sout_instance_t *p_sout, sout_input_t *p_input )
160 sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
161 ps_stream_t *p_stream;
163 msg_Dbg( p_sout, "adding input", p_sout );
164 p_input->p_mux_data = (void*)p_stream = malloc( sizeof( ps_stream_t ) );
166 switch( p_input->input_format.i_cat )
169 p_stream->i_stream_id = p_mux->i_stream_id_mpgv;
170 p_mux->i_stream_id_mpgv++;
171 p_mux->i_video_bound++;
174 if( p_input->input_format.i_fourcc == VLC_FOURCC( 'a', '5', '2', ' ' ) )
176 p_stream->i_stream_id = p_mux->i_stream_id_a52;
177 p_mux->i_stream_id_a52++;
181 p_stream->i_stream_id = p_mux->i_stream_id_mpga;
182 p_mux->i_stream_id_mpga++;
184 p_mux->i_audio_bound++;
191 msg_Dbg( p_sout, "adding input stream_id:0x%x [OK]", p_stream->i_stream_id, p_sout );
195 static int DelStream( sout_instance_t *p_sout, sout_input_t *p_input )
197 ps_stream_t *p_stream =(ps_stream_t*)p_input->p_mux_data;
199 msg_Dbg( p_sout, "removing input" );
207 static int MuxWritePackHeader( sout_instance_t *p_sout,
210 sout_buffer_t *p_hdr;
214 i_src = i_dts * 9 / 100;
216 p_hdr = sout_BufferNew( p_sout, 18 );
217 bits_initwrite( &bits, 14, p_hdr->p_buffer );
218 bits_write( &bits, 32, 0x01ba );
219 bits_write( &bits, 2, 0x01 ); // FIXME ??
220 bits_write( &bits, 3, ( i_src >> 30 )&0x07 );
221 bits_write( &bits, 1, 1 );
222 bits_write( &bits, 15, ( i_src >> 15 )&0x7fff );
223 bits_write( &bits, 1, 1 );
224 bits_write( &bits, 15, i_src&0x7fff );
225 bits_write( &bits, 1, 1 );
227 bits_write( &bits, 9, 0 ); // src extention
228 bits_write( &bits, 1, 1 );
230 bits_write( &bits, 22, 0/8/50); // FIXME
231 bits_write( &bits, 1, 1 );
232 bits_write( &bits, 1, 1 );
233 bits_write( &bits, 5, 0x1f ); // FIXME reserved
234 bits_write( &bits, 3, 0 ); // stuffing bytes
236 p_sout->pf_write( p_sout, p_hdr );
241 static int MuxWriteSystemHeader( sout_instance_t *p_sout )
243 sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
244 sout_buffer_t *p_hdr;
247 p_hdr = sout_BufferNew( p_sout, 12 );
249 bits_initwrite( &bits, 12, p_hdr->p_buffer );
250 bits_write( &bits, 32, 0x01bb );
251 bits_write( &bits, 16, 12 - 6);
252 bits_write( &bits, 1, 1 );
253 bits_write( &bits, 22, 0 ); // FIXME rate bound
254 bits_write( &bits, 1, 1 );
256 bits_write( &bits, 6, p_mux->i_audio_bound );
257 bits_write( &bits, 1, 0 ); // fixed flag
258 bits_write( &bits, 1, 0 ); // CSPS flag
259 bits_write( &bits, 1, 0 ); // system audio lock flag
260 bits_write( &bits, 1, 0 ); // system video lock flag
262 bits_write( &bits, 1, 1 ); // marker bit
264 bits_write( &bits, 5, p_mux->i_video_bound );
265 bits_write( &bits, 1, 0 ); // packet rate restriction flag
266 bits_write( &bits, 7, 0x7f ); // reserved bits
268 /* FIXME missing stream_id ... */
270 p_sout->pf_write( p_sout, p_hdr );
275 /* return stream number to be muxed */
276 static int MuxGetStream( sout_instance_t *p_sout,
284 for( i = 0, i_dts = 0, i_stream = -1; i < p_sout->i_nb_inputs; i++ )
288 p_fifo = p_sout->pp_inputs[i]->p_fifo;
290 if( p_fifo->i_depth > 1 )
292 sout_buffer_t *p_buf;
294 p_buf = sout_FifoShow( p_fifo );
295 if( i_stream < 0 || p_buf->i_dts < i_dts )
297 i_dts = p_buf->i_dts;
303 return( -1 ); // wait that all fifo have at least 2 packets
309 *pi_stream = i_stream;
320 static int Mux ( sout_instance_t *p_sout )
322 sout_mux_t *p_mux = (sout_mux_t*)p_sout->p_mux_data;
328 sout_input_t *p_input;
329 ps_stream_t *p_stream;
331 sout_buffer_t *p_data;
333 if( MuxGetStream( p_sout, &i_stream, &i_dts ) < 0 )
338 p_input = p_sout->pp_inputs[i_stream];
339 p_fifo = p_input->p_fifo;
340 p_stream = (ps_stream_t*)p_input->p_mux_data;
342 if( p_mux->i_pes_count % 30 == 0)
344 MuxWritePackHeader( p_sout, i_dts );
347 if( p_mux->i_pes_count % 300 == 0 )
349 // MuxWriteSystemHeader( p_sout );
352 p_data = sout_FifoGet( p_fifo );
353 EStoPES( p_sout, &p_data, p_data, p_stream->i_stream_id, 1);
354 p_sout->pf_write( p_sout, p_data );
356 p_mux->i_pes_count++;