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