]> git.sesse.net Git - vlc/blob - modules/demux/ps.c
Revert the so-called whitelisting commits that are actually blacklisting
[vlc] / modules / demux / ps.c
1 /*****************************************************************************
2  * ps.c: Program Stream demux module for VLC.
3  *****************************************************************************
4  * Copyright (C) 2004 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27
28 #include <vlc/vlc.h>
29 #include <vlc_demux.h>
30
31 #include "ps.h"
32
33 /* TODO:
34  *  - re-add pre-scanning.
35  *  - ...
36  */
37
38 #define TIME_TEXT N_("Trust MPEG timestamps")
39 #define TIME_LONGTEXT N_("Normally we use the timestamps of the MPEG files " \
40     "to calculate position and duration. However sometimes this might not " \
41     "be usable. Disable this option to calculate from the bitrate instead." )
42
43 /*****************************************************************************
44  * Module descriptor
45  *****************************************************************************/
46 static int  OpenForce( vlc_object_t * );
47 static int  Open   ( vlc_object_t * );
48 static void Close  ( vlc_object_t * );
49
50 vlc_module_begin();
51     set_description( _("MPEG-PS demuxer") );
52     set_category( CAT_INPUT );
53     set_subcategory( SUBCAT_INPUT_DEMUX );
54     set_capability( "demux2", 1 );
55     set_callbacks( OpenForce, Close );
56     add_shortcut( "ps" );
57
58     add_bool( "ps-trust-timestamps", VLC_TRUE, NULL, TIME_TEXT,
59                  TIME_LONGTEXT, VLC_TRUE );
60
61     add_submodule();
62     set_description( _("MPEG-PS demuxer") );
63     set_capability( "demux2", 8 );
64     set_callbacks( Open, Close );
65 vlc_module_end();
66
67 /*****************************************************************************
68  * Local prototypes
69  *****************************************************************************/
70
71 struct demux_sys_t
72 {
73     ps_psm_t    psm;
74     ps_track_t  tk[PS_TK_COUNT];
75
76     int64_t     i_scr;
77     int         i_mux_rate;
78     int64_t     i_length;
79     int         i_time_track;
80     int64_t     i_current_pts;
81
82     vlc_bool_t  b_lost_sync;
83     vlc_bool_t  b_have_pack;
84     vlc_bool_t  b_seekable;
85 };
86
87 static int Demux  ( demux_t *p_demux );
88 static int Control( demux_t *p_demux, int i_query, va_list args );
89
90 static int      ps_pkt_resynch( stream_t *, uint32_t *pi_code );
91 static block_t *ps_pkt_read   ( stream_t *, uint32_t i_code );
92
93 /*****************************************************************************
94  * Open
95  *****************************************************************************/
96 static int OpenCommon( vlc_object_t *p_this, vlc_bool_t b_force )
97 {
98     demux_t     *p_demux = (demux_t*)p_this;
99     demux_sys_t *p_sys;
100
101     const uint8_t *p_peek;
102
103     if( stream_Peek( p_demux->s, &p_peek, 4 ) < 4 )
104     {
105         msg_Err( p_demux, "cannot peek" );
106         return VLC_EGENERIC;
107     }
108
109     if( memcmp( p_peek, "\x00\x00\x01", 3 ) || ( p_peek[3] < 0xb9 ) )
110     {
111         if( !b_force )
112             return VLC_EGENERIC;
113
114         msg_Warn( p_demux, "this does not look like an MPEG PS stream, "
115                   "continuing anyway" );
116     }
117
118     /* Fill p_demux field */
119     p_demux->pf_demux = Demux;
120     p_demux->pf_control = Control;
121     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
122
123     /* Init p_sys */
124     p_sys->i_mux_rate = 0;
125     p_sys->i_scr      = -1;
126     p_sys->i_length   = -1;
127     p_sys->i_current_pts = (mtime_t) 0;
128     p_sys->i_time_track = -1;
129
130     p_sys->b_lost_sync = VLC_FALSE;
131     p_sys->b_have_pack = VLC_FALSE;
132     p_sys->b_seekable  = VLC_FALSE;
133
134     stream_Control( p_demux->s, STREAM_CAN_SEEK, &p_sys->b_seekable );
135
136     ps_psm_init( &p_sys->psm );
137     ps_track_init( p_sys->tk );
138
139     /* TODO prescanning of ES */
140
141     return VLC_SUCCESS;
142 }
143
144 static int OpenForce( vlc_object_t *p_this )
145 {
146     return OpenCommon( p_this, VLC_TRUE );
147 }
148
149 static int Open( vlc_object_t *p_this )
150 {
151     return OpenCommon( p_this, ((demux_t *)p_this)->b_force );
152 }
153
154 /*****************************************************************************
155  * Close
156  *****************************************************************************/
157 static void Close( vlc_object_t *p_this )
158 {
159     demux_t     *p_demux = (demux_t*)p_this;
160     demux_sys_t *p_sys = p_demux->p_sys;
161     int i;
162
163     for( i = 0; i < PS_TK_COUNT; i++ )
164     {
165         ps_track_t *tk = &p_sys->tk[i];
166         if( tk->b_seen )
167         {
168             es_format_Clean( &tk->fmt );
169             if( tk->es ) es_out_Del( p_demux->out, tk->es );
170         }
171     }
172
173     ps_psm_destroy( &p_sys->psm );
174
175     free( p_sys );
176 }
177
178 static int Demux2( demux_t *p_demux, vlc_bool_t b_end )
179 {
180     demux_sys_t *p_sys = p_demux->p_sys;
181     int i_ret, i_id;
182     uint32_t i_code;
183     block_t *p_pkt;
184
185     i_ret = ps_pkt_resynch( p_demux->s, &i_code );
186     if( i_ret < 0 )
187     {
188         return 0;
189     }
190     else if( i_ret == 0 )
191     {
192         if( !p_sys->b_lost_sync )
193             msg_Warn( p_demux, "garbage at input, trying to resync..." );
194
195         p_sys->b_lost_sync = VLC_TRUE;
196         return 1;
197     }
198
199     if( p_sys->b_lost_sync ) msg_Warn( p_demux, "found sync code" );
200     p_sys->b_lost_sync = VLC_FALSE;
201
202     if( ( p_pkt = ps_pkt_read( p_demux->s, i_code ) ) == NULL )
203     {
204         return 0;
205     }
206     if( (i_id = ps_pkt_id( p_pkt )) >= 0xc0 )
207     {
208         ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(i_id)];
209         if( !ps_pkt_parse_pes( p_pkt, tk->i_skip ) )
210         {
211             if( b_end && p_pkt->i_pts > tk->i_last_pts )
212             {
213                 tk->i_last_pts = p_pkt->i_pts;
214             }
215             else if ( tk->i_first_pts == -1 )
216             {
217                 tk->i_first_pts = p_pkt->i_pts;
218             }
219         }
220     }
221     block_Release( p_pkt );
222     return 1;
223 }
224
225 static void FindLength( demux_t *p_demux )
226 {
227     demux_sys_t *p_sys = p_demux->p_sys;
228     int64_t i_current_pos = -1, i_size = 0, i_end = 0;
229     int i;
230
231     if( !var_CreateGetInteger( p_demux, "ps-trust-timestamps" ) )
232         return;
233
234     if( p_sys->i_length == -1 ) /* First time */
235     {
236         p_sys->i_length = 0;
237         /* Check beginning */
238         i = 0;
239         i_current_pos = stream_Tell( p_demux->s );
240         while( !p_demux->b_die && i < 40 && Demux2( p_demux, VLC_FALSE ) > 0 ) i++;
241
242         /* Check end */
243         i_size = stream_Size( p_demux->s );
244         i_end = __MAX( 0, __MIN( 200000, i_size ) );
245         stream_Seek( p_demux->s, i_size - i_end );
246
247         while( !p_demux->b_die && Demux2( p_demux, VLC_TRUE ) > 0 );
248         if( i_current_pos >= 0 ) stream_Seek( p_demux->s, i_current_pos );
249     }
250
251     for( i = 0; i < PS_TK_COUNT; i++ )
252     {
253         ps_track_t *tk = &p_sys->tk[i];
254         if( tk->i_first_pts >= 0 && tk->i_last_pts > 0 )
255             if( tk->i_last_pts > tk->i_first_pts )
256             {
257                 int64_t i_length = (int64_t)tk->i_last_pts - tk->i_first_pts;
258                 if( i_length > p_sys->i_length )
259                 {
260                     p_sys->i_length = i_length;
261                     p_sys->i_time_track = i;
262                     msg_Dbg( p_demux, "we found a length of: "I64Fd, p_sys->i_length );
263                 }
264             }
265     }
266 }
267
268 /*****************************************************************************
269  * Demux:
270  *****************************************************************************/
271 static int Demux( demux_t *p_demux )
272 {
273     demux_sys_t *p_sys = p_demux->p_sys;
274     int i_ret, i_id, i_mux_rate;
275     uint32_t i_code;
276     block_t *p_pkt;
277
278     i_ret = ps_pkt_resynch( p_demux->s, &i_code );
279     if( i_ret < 0 )
280     {
281         return 0;
282     }
283     else if( i_ret == 0 )
284     {
285         if( !p_sys->b_lost_sync )
286             msg_Warn( p_demux, "garbage at input, trying to resync..." );
287
288         p_sys->b_lost_sync = VLC_TRUE;
289         return 1;
290     }
291
292     if( p_sys->b_lost_sync ) msg_Warn( p_demux, "found sync code" );
293     p_sys->b_lost_sync = VLC_FALSE;
294
295     if( p_sys->i_length < 0 && p_sys->b_seekable )
296         FindLength( p_demux );
297
298     if( ( p_pkt = ps_pkt_read( p_demux->s, i_code ) ) == NULL )
299     {
300         return 0;
301     }
302
303     switch( i_code )
304     {
305     case 0x1b9:
306         block_Release( p_pkt );
307         break;
308
309     case 0x1ba:
310         if( !ps_pkt_parse_pack( p_pkt, &p_sys->i_scr, &i_mux_rate ) )
311         {
312             if( !p_sys->b_have_pack ) p_sys->b_have_pack = VLC_TRUE;
313             /* done later on to work around bad vcd/svcd streams */
314             /* es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_scr ); */
315             if( i_mux_rate > 0 ) p_sys->i_mux_rate = i_mux_rate;
316         }
317         block_Release( p_pkt );
318         break;
319
320     case 0x1bb:
321         if( !ps_pkt_parse_system( p_pkt, &p_sys->psm, p_sys->tk ) )
322         {
323             int i;
324             for( i = 0; i < PS_TK_COUNT; i++ )
325             {
326                 ps_track_t *tk = &p_sys->tk[i];
327
328                 if( tk->b_seen && !tk->es && tk->fmt.i_cat != UNKNOWN_ES )
329                 {
330                     tk->es = es_out_Add( p_demux->out, &tk->fmt );
331                 }
332             }
333         }
334         block_Release( p_pkt );
335         break;
336
337     case 0x1bc:
338         if( p_sys->psm.i_version == 0xFFFF )
339             msg_Dbg( p_demux, "contains a PSM");
340
341         ps_psm_fill( &p_sys->psm, p_pkt, p_sys->tk, p_demux->out );
342         block_Release( p_pkt );
343         break;
344
345     default:
346         if( (i_id = ps_pkt_id( p_pkt )) >= 0xc0 )
347         {
348             vlc_bool_t b_new = VLC_FALSE;
349             ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(i_id)];
350
351             if( !tk->b_seen )
352             {
353                 if( !ps_track_fill( tk, &p_sys->psm, i_id ) )
354                 {
355                     tk->es = es_out_Add( p_demux->out, &tk->fmt );
356                     b_new = VLC_TRUE;
357                 }
358                 else
359                 {
360                     msg_Dbg( p_demux, "es id=0x%x format unknown", i_id );
361                 }
362                 tk->b_seen = VLC_TRUE;
363             }
364
365             /* The popular VCD/SVCD subtitling WinSubMux does not
366              * renumber the SCRs when merging subtitles into the PES */
367             if( tk->b_seen &&
368                 ( tk->fmt.i_codec == VLC_FOURCC('o','g','t',' ') ||
369                   tk->fmt.i_codec == VLC_FOURCC('c','v','d',' ') ) )
370             {
371                 p_sys->i_scr = -1;
372             }
373
374             if( p_sys->i_scr > 0 )
375                 es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_scr );
376
377             p_sys->i_scr = -1;
378
379             if( tk->b_seen && tk->es &&
380                 !ps_pkt_parse_pes( p_pkt, tk->i_skip ) )
381             {
382                 if( !b_new && !p_sys->b_have_pack && tk->fmt.i_cat == AUDIO_ES && p_pkt->i_pts > 0 )
383                 {
384                     /* A hack to sync the A/V on PES files. */
385                     msg_Dbg( p_demux, "force SCR: "I64Fd, p_pkt->i_pts );
386                     es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_pkt->i_pts );
387                 }
388
389                 if( (int64_t)p_pkt->i_pts > p_sys->i_current_pts )
390                 {
391                     p_sys->i_current_pts = (int64_t)p_pkt->i_pts;
392                 }
393
394                 es_out_Send( p_demux->out, tk->es, p_pkt );
395             }
396             else
397             {
398                 block_Release( p_pkt );
399             }
400         }
401         else
402         {
403             block_Release( p_pkt );
404         }
405         break;
406     }
407
408     return 1;
409 }
410
411 /*****************************************************************************
412  * Control:
413  *****************************************************************************/
414 static int Control( demux_t *p_demux, int i_query, va_list args )
415 {
416     demux_sys_t *p_sys = p_demux->p_sys;
417     double f, *pf;
418     int64_t i64, *pi64;
419
420     switch( i_query )
421     {
422         case DEMUX_GET_POSITION:
423             pf = (double*) va_arg( args, double* );
424             i64 = stream_Size( p_demux->s );
425             if( i64 > 0 )
426             {
427                 *pf = (double)stream_Tell( p_demux->s ) / (double)i64;
428             }
429             else
430             {
431                 *pf = 0.0;
432             }
433             return VLC_SUCCESS;
434
435         case DEMUX_SET_POSITION:
436             f = (double) va_arg( args, double );
437             i64 = stream_Size( p_demux->s );
438             p_sys->i_current_pts = 0;
439             es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
440
441             return stream_Seek( p_demux->s, (int64_t)(i64 * f) );
442
443         case DEMUX_GET_TIME:
444             pi64 = (int64_t*)va_arg( args, int64_t * );
445             if( p_sys->i_time_track >= 0 && p_sys->i_current_pts > 0 )
446             {
447                 *pi64 = p_sys->i_current_pts - p_sys->tk[p_sys->i_time_track].i_first_pts;
448                 return VLC_SUCCESS;
449             }
450             if( p_sys->i_mux_rate > 0 )
451             {
452                 *pi64 = (int64_t)1000000 * ( stream_Tell( p_demux->s ) / 50 ) /
453                     p_sys->i_mux_rate;
454                 return VLC_SUCCESS;
455             }
456             *pi64 = 0;
457             return VLC_EGENERIC;
458
459         case DEMUX_GET_LENGTH:
460             pi64 = (int64_t*)va_arg( args, int64_t * );
461             if( p_sys->i_length > 0 )
462             {
463                 *pi64 = p_sys->i_length;
464                 return VLC_SUCCESS;
465             }
466             else if( p_sys->i_mux_rate > 0 )
467             {
468                 *pi64 = (int64_t)1000000 * ( stream_Size( p_demux->s ) / 50 ) /
469                     p_sys->i_mux_rate;
470                 return VLC_SUCCESS;
471             }
472             *pi64 = 0;
473             return VLC_EGENERIC;
474
475         case DEMUX_SET_TIME:
476             i64 = (int64_t)va_arg( args, int64_t );
477             if( p_sys->i_time_track >= 0 && p_sys->i_current_pts > 0 )
478             {
479                 int64_t i_now = p_sys->i_current_pts - p_sys->tk[p_sys->i_time_track].i_first_pts;
480                 int64_t i_pos = stream_Tell( p_demux->s );
481                 int64_t i_offset = i_pos / (i_now / 1000000) * ((i64 - i_now) / 1000000);
482                 stream_Seek( p_demux->s, i_pos + i_offset);
483
484                 es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
485                 return VLC_SUCCESS;
486             }
487             return VLC_EGENERIC;
488
489         case DEMUX_GET_FPS:
490         default:
491             return VLC_EGENERIC;
492     }
493 }
494
495 /*****************************************************************************
496  * Divers:
497  *****************************************************************************/
498
499 /* PSResynch: resynch on a system startcode
500  *  It doesn't skip more than 512 bytes
501  *  -1 -> error, 0 -> not synch, 1 -> ok
502  */
503 static int ps_pkt_resynch( stream_t *s, uint32_t *pi_code )
504 {
505     const uint8_t *p_peek;
506     int     i_peek;
507     int     i_skip;
508
509     if( stream_Peek( s, &p_peek, 4 ) < 4 )
510     {
511         return -1;
512     }
513     if( p_peek[0] == 0 && p_peek[1] == 0 && p_peek[2] == 1 &&
514         p_peek[3] >= 0xb9 )
515     {
516         *pi_code = 0x100 | p_peek[3];
517         return 1;
518     }
519
520     if( ( i_peek = stream_Peek( s, &p_peek, 512 ) ) < 4 )
521     {
522         return -1;
523     }
524     i_skip = 0;
525
526     for( ;; )
527     {
528         if( i_peek < 4 )
529         {
530             break;
531         }
532         if( p_peek[0] == 0 && p_peek[1] == 0 && p_peek[2] == 1 &&
533             p_peek[3] >= 0xb9 )
534         {
535             *pi_code = 0x100 | p_peek[3];
536             return stream_Read( s, NULL, i_skip ) == i_skip ? 1 : -1;
537         }
538
539         p_peek++;
540         i_peek--;
541         i_skip++;
542     }
543     return stream_Read( s, NULL, i_skip ) == i_skip ? 0 : -1;
544 }
545
546 static block_t *ps_pkt_read( stream_t *s, uint32_t i_code )
547 {
548     const uint8_t *p_peek;
549     int      i_peek = stream_Peek( s, &p_peek, 14 );
550     int      i_size = ps_pkt_size( p_peek, i_peek );
551
552     if( i_size <= 6 && p_peek[3] > 0xba )
553     {
554         /* Special case, search the next start code */
555         i_size = 6;
556         for( ;; )
557         {
558             i_peek = stream_Peek( s, &p_peek, i_size + 1024 );
559             if( i_peek <= i_size + 4 )
560             {
561                 return NULL;
562             }
563             while( i_size <= i_peek - 4 )
564             {
565                 if( p_peek[i_size] == 0x00 && p_peek[i_size+1] == 0x00 &&
566                     p_peek[i_size+2] == 0x01 && p_peek[i_size+3] >= 0xb9 )
567                 {
568                     return stream_Block( s, i_size );
569                 }
570                 i_size++;
571             }
572         }
573     }
574     else
575     {
576         /* Normal case */
577         return stream_Block( s, i_size );
578     }
579
580     return NULL;
581 }