00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdlib.h>
00028
00029 #include <vlc/vlc.h>
00030 #include <vlc/input.h>
00031
00032 #include "ps.h"
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 static int Open ( vlc_object_t * );
00043 static int OpenAlt( vlc_object_t * );
00044 static void Close ( vlc_object_t * );
00045
00046 vlc_module_begin();
00047 set_description( _("PS demuxer") );
00048 set_category( CAT_INPUT );
00049 set_subcategory( SUBCAT_INPUT_DEMUX );
00050 set_capability( "demux2", 1 );
00051 set_callbacks( Open, Close );
00052 add_shortcut( "ps" );
00053
00054 add_submodule();
00055 set_description( _("PS demuxer") );
00056 set_capability( "demux2", 9 );
00057 set_callbacks( OpenAlt, Close );
00058 vlc_module_end();
00059
00060
00061
00062
00063
00064 struct demux_sys_t
00065 {
00066 ps_psm_t psm;
00067 ps_track_t tk[PS_TK_COUNT];
00068
00069 int64_t i_scr;
00070 int i_mux_rate;
00071
00072 vlc_bool_t b_lost_sync;
00073 };
00074
00075 static int Demux ( demux_t *p_demux );
00076 static int Control( demux_t *p_demux, int i_query, va_list args );
00077
00078 static int ps_pkt_resynch( stream_t *, uint32_t *pi_code );
00079 static block_t *ps_pkt_read ( stream_t *, uint32_t i_code );
00080
00081
00082
00083
00084 static int Open( vlc_object_t *p_this )
00085 {
00086 demux_t *p_demux = (demux_t*)p_this;
00087 demux_sys_t *p_sys;
00088
00089 uint8_t *p_peek;
00090
00091 if( stream_Peek( p_demux->s, &p_peek, 4 ) < 4 )
00092 {
00093 msg_Err( p_demux, "cannot peek" );
00094 return VLC_EGENERIC;
00095 }
00096
00097 if( p_peek[0] != 0 || p_peek[1] != 0 ||
00098 p_peek[2] != 1 || p_peek[3] < 0xb9 )
00099 {
00100 msg_Warn( p_demux, "this does not look like an MPEG PS stream, "
00101 "continuing anyway" );
00102 }
00103
00104
00105 p_demux->pf_demux = Demux;
00106 p_demux->pf_control = Control;
00107 p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
00108
00109
00110 p_sys->i_mux_rate = 0;
00111 p_sys->i_scr = -1;
00112 p_sys->b_lost_sync = VLC_FALSE;
00113
00114 ps_psm_init( &p_sys->psm );
00115 ps_track_init( p_sys->tk );
00116
00117
00118
00119 return VLC_SUCCESS;
00120 }
00121
00122 static int OpenAlt( vlc_object_t *p_this )
00123 {
00124 demux_t *p_demux = (demux_t*)p_this;
00125 uint8_t *p_peek;
00126
00127 if( stream_Peek( p_demux->s, &p_peek, 4 ) < 4 )
00128 {
00129 msg_Err( p_demux, "cannot peek" );
00130 return VLC_EGENERIC;
00131 }
00132
00133 if( p_peek[0] != 0 || p_peek[1] != 0 ||
00134 p_peek[2] != 1 || p_peek[3] < 0xb9 )
00135 {
00136 if( !p_demux->b_force ) return VLC_EGENERIC;
00137 }
00138
00139 return Open( p_this );
00140 }
00141
00142
00143
00144
00145 static void Close( vlc_object_t *p_this )
00146 {
00147 demux_t *p_demux = (demux_t*)p_this;
00148 demux_sys_t *p_sys = p_demux->p_sys;
00149 int i;
00150
00151 for( i = 0; i < PS_TK_COUNT; i++ )
00152 {
00153 ps_track_t *tk = &p_sys->tk[i];
00154 if( tk->b_seen )
00155 {
00156 es_format_Clean( &tk->fmt );
00157 if( tk->es ) es_out_Del( p_demux->out, tk->es );
00158 }
00159 }
00160
00161 ps_psm_destroy( &p_sys->psm );
00162
00163 free( p_sys );
00164 }
00165
00166
00167
00168
00169 static int Demux( demux_t *p_demux )
00170 {
00171 demux_sys_t *p_sys = p_demux->p_sys;
00172 int i_ret, i_id, i_mux_rate;
00173 uint32_t i_code;
00174 block_t *p_pkt;
00175
00176 i_ret = ps_pkt_resynch( p_demux->s, &i_code );
00177 if( i_ret < 0 )
00178 {
00179 return 0;
00180 }
00181 else if( i_ret == 0 )
00182 {
00183 if( !p_sys->b_lost_sync )
00184 msg_Warn( p_demux, "garbage at input, trying to resync..." );
00185
00186 p_sys->b_lost_sync = VLC_TRUE;
00187 return 1;
00188 }
00189
00190 if( p_sys->b_lost_sync ) msg_Warn( p_demux, "found sync code" );
00191 p_sys->b_lost_sync = VLC_FALSE;
00192
00193 if( ( p_pkt = ps_pkt_read( p_demux->s, i_code ) ) == NULL )
00194 {
00195 return 0;
00196 }
00197
00198 switch( i_code )
00199 {
00200 case 0x1b9:
00201 block_Release( p_pkt );
00202 break;
00203
00204 case 0x1ba:
00205 if( !ps_pkt_parse_pack( p_pkt, &p_sys->i_scr, &i_mux_rate ) )
00206 {
00207
00208
00209 if( i_mux_rate > 0 ) p_sys->i_mux_rate = i_mux_rate;
00210 }
00211 block_Release( p_pkt );
00212 break;
00213
00214 case 0x1bb:
00215 if( !ps_pkt_parse_system( p_pkt, &p_sys->psm, p_sys->tk ) )
00216 {
00217 int i;
00218 for( i = 0; i < PS_TK_COUNT; i++ )
00219 {
00220 ps_track_t *tk = &p_sys->tk[i];
00221
00222 if( tk->b_seen && !tk->es && tk->fmt.i_cat != UNKNOWN_ES )
00223 {
00224 tk->es = es_out_Add( p_demux->out, &tk->fmt );
00225 }
00226 }
00227 }
00228 block_Release( p_pkt );
00229 break;
00230
00231 case 0x1bc:
00232 if( p_sys->psm.i_version == 0xFFFF )
00233 msg_Dbg( p_demux, "contains a PSM");
00234
00235 ps_psm_fill( &p_sys->psm, p_pkt, p_sys->tk, p_demux->out );
00236 block_Release( p_pkt );
00237 break;
00238
00239 default:
00240 if( (i_id = ps_pkt_id( p_pkt )) >= 0xc0 )
00241 {
00242 ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(i_id)];
00243
00244 if( !tk->b_seen )
00245 {
00246 if( !ps_track_fill( tk, &p_sys->psm, i_id ) )
00247 {
00248 tk->es = es_out_Add( p_demux->out, &tk->fmt );
00249 }
00250 else
00251 {
00252 msg_Dbg( p_demux, "es id=0x%x format unknown", i_id );
00253 }
00254 tk->b_seen = VLC_TRUE;
00255 }
00256
00257
00258
00259 if( tk->b_seen &&
00260 ( tk->fmt.i_codec == VLC_FOURCC('o','g','t',' ') ||
00261 tk->fmt.i_codec == VLC_FOURCC('c','v','d',' ') ) )
00262 {
00263 p_sys->i_scr = -1;
00264 }
00265
00266 if( p_sys->i_scr > 0 )
00267 es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_scr );
00268
00269 p_sys->i_scr = -1;
00270
00271 if( tk->b_seen && tk->es &&
00272 !ps_pkt_parse_pes( p_pkt, tk->i_skip ) )
00273 {
00274 es_out_Send( p_demux->out, tk->es, p_pkt );
00275 }
00276 else
00277 {
00278 block_Release( p_pkt );
00279 }
00280 }
00281 else
00282 {
00283 block_Release( p_pkt );
00284 }
00285 break;
00286 }
00287
00288 return 1;
00289 }
00290
00291
00292
00293
00294 static int Control( demux_t *p_demux, int i_query, va_list args )
00295 {
00296 demux_sys_t *p_sys = p_demux->p_sys;
00297 double f, *pf;
00298 int64_t i64, *pi64;
00299
00300 switch( i_query )
00301 {
00302 case DEMUX_GET_POSITION:
00303 pf = (double*) va_arg( args, double* );
00304 i64 = stream_Size( p_demux->s );
00305 if( i64 > 0 )
00306 {
00307 *pf = (double)stream_Tell( p_demux->s ) / (double)i64;
00308 }
00309 else
00310 {
00311 *pf = 0.0;
00312 }
00313 return VLC_SUCCESS;
00314
00315 case DEMUX_SET_POSITION:
00316 f = (double) va_arg( args, double );
00317 i64 = stream_Size( p_demux->s );
00318
00319 es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
00320
00321 return stream_Seek( p_demux->s, (int64_t)(i64 * f) );
00322
00323 case DEMUX_GET_TIME:
00324 pi64 = (int64_t*)va_arg( args, int64_t * );
00325 if( p_sys->i_mux_rate > 0 )
00326 {
00327 *pi64 = (int64_t)1000000 * ( stream_Tell( p_demux->s ) / 50 ) /
00328 p_sys->i_mux_rate;
00329 return VLC_SUCCESS;
00330 }
00331 *pi64 = 0;
00332 return VLC_EGENERIC;
00333
00334 case DEMUX_GET_LENGTH:
00335 pi64 = (int64_t*)va_arg( args, int64_t * );
00336 if( p_sys->i_mux_rate > 0 )
00337 {
00338 *pi64 = (int64_t)1000000 * ( stream_Size( p_demux->s ) / 50 ) /
00339 p_sys->i_mux_rate;
00340 return VLC_SUCCESS;
00341 }
00342 *pi64 = 0;
00343 return VLC_EGENERIC;
00344
00345 case DEMUX_SET_TIME:
00346 case DEMUX_GET_FPS:
00347 default:
00348 return VLC_EGENERIC;
00349 }
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 static int ps_pkt_resynch( stream_t *s, uint32_t *pi_code )
00361 {
00362 uint8_t *p_peek;
00363 int i_peek;
00364 int i_skip;
00365
00366 if( stream_Peek( s, &p_peek, 4 ) < 4 )
00367 {
00368 return -1;
00369 }
00370 if( p_peek[0] == 0 && p_peek[1] == 0 && p_peek[2] == 1 &&
00371 p_peek[3] >= 0xb9 )
00372 {
00373 *pi_code = 0x100 | p_peek[3];
00374 return 1;
00375 }
00376
00377 if( ( i_peek = stream_Peek( s, &p_peek, 512 ) ) < 4 )
00378 {
00379 return -1;
00380 }
00381 i_skip = 0;
00382
00383 for( ;; )
00384 {
00385 if( i_peek < 4 )
00386 {
00387 break;
00388 }
00389 if( p_peek[0] == 0 && p_peek[1] == 0 && p_peek[2] == 1 &&
00390 p_peek[3] >= 0xb9 )
00391 {
00392 *pi_code = 0x100 | p_peek[3];
00393 return stream_Read( s, NULL, i_skip ) == i_skip ? 1 : -1;
00394 }
00395
00396 p_peek++;
00397 i_peek--;
00398 i_skip++;
00399 }
00400 return stream_Read( s, NULL, i_skip ) == i_skip ? 0 : -1;
00401 }
00402
00403 static block_t *ps_pkt_read( stream_t *s, uint32_t i_code )
00404 {
00405 uint8_t *p_peek;
00406 int i_peek = stream_Peek( s, &p_peek, 14 );
00407 int i_size = ps_pkt_size( p_peek, i_peek );
00408
00409 if( i_size <= 6 && p_peek[3] > 0xba )
00410 {
00411
00412 i_size = 6;
00413 for( ;; )
00414 {
00415 i_peek = stream_Peek( s, &p_peek, i_size + 1024 );
00416 if( i_peek <= i_size + 4 )
00417 {
00418 return NULL;
00419 }
00420 while( i_size <= i_peek - 4 )
00421 {
00422 if( p_peek[i_size] == 0x00 && p_peek[i_size+1] == 0x00 &&
00423 p_peek[i_size+2] == 0x01 && p_peek[i_size+3] >= 0xb9 )
00424 {
00425 return stream_Block( s, i_size );
00426 }
00427 i_size++;
00428 }
00429 }
00430 }
00431 else
00432 {
00433
00434 return stream_Block( s, i_size );
00435 }
00436
00437 return NULL;
00438 }