]> git.sesse.net Git - vlc/blob - src/input/input_file.c
. input fichier en ligne de commande (le reste a du p�ter, c'est pas
[vlc] / src / input / input_file.c
1 /*****************************************************************************
2  * input_file.c: functions to read from a file
3  *****************************************************************************
4  * Copyright (C) 1999, 2000 VideoLAN
5  *
6  * Authors:
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  * 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 /*****************************************************************************
24  * Preamble
25  *****************************************************************************/
26 #include "defs.h"
27
28 #include <stdio.h>
29 #include <unistd.h>                                               /* close() */
30 #include <sys/types.h>                        /* on BSD, uio.h needs types.h */
31 #include <sys/uio.h>                                            /* "input.h" */
32 #include <sys/stat.h>                                    /* fstat, off_t ... */
33 #include <netinet/in.h>                                           /* ntohl() */
34 #include <fcntl.h>                                                 /* open() */
35 #include <malloc.h>                                      /* malloc, read ... */
36 #include <string.h>
37
38 #include "config.h"
39 #include "common.h"
40 #include "threads.h"
41 #include "mtime.h"
42 #include "intf_msg.h"
43
44 #include "main.h"
45
46 #include "input.h"
47 #include "input_file.h"
48
49 #define BUF_SIZE (797*3)
50
51 #define PS_METHOD 1
52 #define TS_METHOD 2
53
54 #define TS_PACKET_SIZE 188
55 #define TS_IN_UDP 7
56
57 #define MAX_AUDIO_CHANNEL 15
58 #define MAX_SUBTITLES_CHANNEL 31
59 #define NO_SUBTITLES 255
60
61 #define REQUESTED_AC3          0
62 #define REQUESTED_MPEG         1
63 #define REQUESTED_LPCM         2
64 #define REQUESTED_NOAUDIO    255
65
66 #define PS_BUFFER_SIZE 16384
67 #define NO_PES 0
68 #define AUDIO_PES 1
69 #define VIDEO_PES 2
70 #define AC3_PES 3
71 #define SUBTITLE_PES 4
72 #define LPCM_PES 5
73 #define PRIVATE_PES 6
74 #define UNKNOWN_PES 12
75
76 #define PCR_PID 0x20 /* 0x20 == first video stream
77                       * 0x40 == first audio stream */
78
79 typedef u8 file_ts_packet[TS_PACKET_SIZE];
80 typedef file_ts_packet udp_packet[TS_IN_UDP];
81
82 typedef struct synchro_struct
83 {
84     mtime_t     delta_clock;
85     mtime_t     slope;
86     mtime_t     last_pcr_time;
87     
88     file_ts_packet *last_pcr;
89 } synchro_t;
90
91 typedef struct in_data_s
92 {
93     int start, end;
94     vlc_mutex_t lock;
95     vlc_cond_t notfull;
96     vlc_cond_t notempty;
97     udp_packet buf[BUF_SIZE+1];
98 } in_data_t;
99
100 typedef struct own_pcr_s
101 {
102     int start, end;
103     vlc_mutex_t lock;
104     file_ts_packet *buf[(BUF_SIZE+1)*TS_IN_UDP+1];
105 } own_pcr_t;
106
107 typedef struct options_s
108 {
109     unsigned int pcr_pid;
110     u8 i_file_type;
111     int in; 
112     char **playlist;
113     int i_list_index;
114 } options_t;
115
116 typedef struct s_ps
117 {
118     unsigned int pat_counter;
119     unsigned int pmt_counter;
120
121     /*
122      * These 3 parameters are passed 
123      * as command line arguments
124      */
125     unsigned int audio_channel;
126     unsigned int subtitles_channel;
127     unsigned int audio_type;
128
129     /* 
130      * 16 audio mpeg streams
131      * 16 audio AV3 streams
132      * 16 video mpeg streams
133      * 32 subtitle streams
134      */
135     unsigned int media_counter[0x100];
136     unsigned int association_table[0x100];
137     unsigned int found_streams;
138
139     unsigned int found_pts;
140
141     unsigned int ts_to_write;
142     unsigned int ts_written;
143     unsigned int sent_ts;
144
145     unsigned char *ps_data;
146     unsigned char *ps_end;
147     unsigned char *ps_buffer;
148
149     unsigned int pes_id;
150     unsigned int private_id;
151     unsigned int has_pts;
152     unsigned int pcr_pid;
153
154     unsigned int pes_type;
155     unsigned int pes_size;
156     unsigned int to_skip;
157     unsigned int offset;
158 } ps_t;
159
160 typedef struct input_file_s
161 {
162     boolean_t    b_die; /* b_die flag for the disk thread */
163     vlc_thread_t disk_thread;
164
165     synchro_t    synchro;
166     ps_t         ps;
167     in_data_t    in_data;
168     options_t    options;
169     own_pcr_t    own_pcr;
170 } input_file_t;
171
172 /* local prototypes */
173 void ps_fill( input_file_t * p_if, boolean_t wait );
174 ssize_t safe_read(options_t *p_options, unsigned char *buf, int count);
175 void input_DiskThread( input_file_t * p_if );
176 int init_synchro( input_file_t * p_if );
177
178 input_file_t input_file;
179
180 /******************************************************************************
181  * ConvertPCRTime : extracts and converts the PCR time in microseconds
182  ******************************************************************************/
183
184 s64 ConvertPCRTime(file_ts_packet *pcr_buff)
185 {
186     return( (((((s64)U32_AT(((u8*)pcr_buff)+6)) << 1) | (((u8*)pcr_buff)[10] >> 7)) * 300) / 27 );
187 }
188
189 /******************************************************************************
190  * wait_a_moment : Compute how long we must wait before sending a TS packet
191  ******************************************************************************/
192
193 static void wait_a_moment( input_file_t * p_if, file_ts_packet *ts)
194 {
195     synchro_t * p_synchro = &input_file.synchro;
196     
197     static int retard_count = 0;
198     static s64 wait_max = 0;
199     s64 sendtime; /* the date at which the TS packet should be sent */
200     s64 wait;
201     
202     sendtime = p_synchro->last_pcr_time + p_synchro->delta_clock +
203         p_synchro->slope * ((ts - p_synchro->last_pcr + (BUF_SIZE+1)*TS_IN_UDP) % ((BUF_SIZE+1)*TS_IN_UDP)); 
204     wait = sendtime - mdate();
205     if( wait > 0 )
206     { 
207         retard_count = 0;
208         if(wait > 100000)
209         {
210             intf_DbgMsg( "input warning: wait time may be too long : %Ld\n", wait );
211             return;
212         }
213         msleep( wait );
214     }
215     else
216     {
217         if( wait < wait_max )
218         {
219             wait_max = wait;
220         }
221         retard_count++;
222         if( retard_count == 16 )
223         {
224             retard_count = 0;
225         }
226     }
227 }
228
229 /******************************************************************************
230  * adjust : Adjust the encoder clock & remove the PCR from own_pcr
231  ******************************************************************************/
232
233 static void adjust( input_file_t * p_if, file_ts_packet *ts )
234 {
235     synchro_t * p_synchro = &p_if->synchro;
236     own_pcr_t * p_own_pcr = &p_if->own_pcr;
237     file_ts_packet *next_pcr;
238     int no_discontinuity = 1;
239     
240     if( ((u8*)ts)[5] & 0x80 )
241     {
242         /* There is a discontinuity - I recalculate the delta */
243         p_synchro->delta_clock = mdate() - ConvertPCRTime(ts);
244         intf_DbgMsg( "input warning: clock discontinuity\n" );
245         no_discontinuity = 0;
246     }
247     else
248     {
249         p_synchro->last_pcr = ts;
250         p_synchro->last_pcr_time = ConvertPCRTime( ts );
251     }
252         
253     vlc_mutex_lock(&p_own_pcr->lock);
254     p_own_pcr->start++;
255     p_own_pcr->start %= (BUF_SIZE+1)*TS_IN_UDP+1;
256     
257     /* If we have 2 consecutiv PCR, we can reevaluate slope */
258     if( (p_own_pcr->start != p_own_pcr->end) &&
259         no_discontinuity &&
260         !((((u8*) next_pcr = p_own_pcr->buf[p_own_pcr->start]))[5] & 0x80))
261     {
262         s64 current_pcr_time = ConvertPCRTime(ts);
263         s64 next_pcr_time =    ConvertPCRTime(next_pcr);
264         
265         if( (next_pcr_time - current_pcr_time < 0) || (next_pcr_time - current_pcr_time > 700000))
266         {
267             intf_DbgMsg( "input warning: possible discontinuity\n" );
268             p_synchro->delta_clock = mdate() - next_pcr_time;
269         }
270         else
271         {
272             p_synchro->slope = (next_pcr_time - current_pcr_time) /
273                 ((next_pcr - ts + (BUF_SIZE+1)*TS_IN_UDP) % ((BUF_SIZE+1)*TS_IN_UDP));
274         }
275     }
276     
277     vlc_mutex_unlock(&p_own_pcr->lock);
278 }
279
280 /*****************************************************************************
281  * file_next : Opens the next available file
282  *****************************************************************************/
283
284 int file_next( options_t *options )
285 {
286     /* the check for index == 0 should be done _before_ */
287     options->i_list_index--;
288     
289     if( options->in != -1 )
290     {
291             close( options->in );
292     }
293
294     if( !strcmp( options->playlist[options->i_list_index], "-" ) )
295     {
296         /* read stdin */
297         return ( options->in = 0 );
298     }
299     else
300     {
301         /* read the actual file */
302         fprintf( stderr, "Playing file %s\n",
303                  options->playlist[options->i_list_index] );
304         return ( options->in = open( options->playlist[options->i_list_index],
305                                      O_RDONLY | O_NDELAY ) );
306     }
307 }
308
309 /*****************************************************************************
310  * safe_read : Buffered reading method
311  *****************************************************************************/
312
313 ssize_t safe_read( options_t *options, unsigned char *buf, int count )
314 {
315     int ret, cnt=0;
316     
317     while( cnt < count )
318     {
319         ret = read( options->in, buf + cnt, count - cnt );
320     
321         if( ret < 0 )
322             return ret;
323     
324         if( ret == 0 )
325         {
326             /* zero means end of file */
327             if( options->i_list_index )
328             {
329                 file_next( options );
330             }
331             else
332             {
333                 break;
334             }
335         }
336     
337         cnt += ret;
338     }
339
340     return cnt;
341 }
342
343 /******************************************************************************
344  * keep_pcr : Put a TS packet in the fifo if it owns a PCR
345  ******************************************************************************/
346
347 int keep_pcr(int pcr_pid, file_ts_packet *ts)
348 {
349     own_pcr_t * p_own_pcr =   &input_file.own_pcr;
350
351 #define p ((u8 *)ts)
352     if ((p[3] & 0x20) && p[4] && (p[5] & 0x10)
353         && ((((p[1]<<8)+p[2]) & 0x1FFF) == pcr_pid))
354     {
355         /* adaptation_field_control is set, adaptation_field_lenght is not 0,
356          * PCR_flag is set, pid == pcr_pid */
357         vlc_mutex_lock(&p_own_pcr->lock);
358         p_own_pcr->buf[p_own_pcr->end++] = ts;
359         p_own_pcr->end %= (BUF_SIZE+1)*TS_IN_UDP+1;
360         vlc_mutex_unlock(&p_own_pcr->lock);
361         return 1;
362     } 
363     else
364         return 0;
365 #undef p
366 }
367
368 /******************************************************************************
369  * get_pid : gets a pid from a PES type
370  ******************************************************************************/
371
372 int get_pid (ps_t *p_ps)
373 {
374     int i, tofind, delta;
375     char* type;
376
377     switch( p_ps->pes_type )
378     {
379         case VIDEO_PES:
380             delta = 0x20; /* 0x20 - 0x2f */
381             type = "MPEG video";
382             tofind = p_ps->pes_id;
383             break;
384         case AUDIO_PES:
385             delta = 0x40; /* 0x40 - 0x5f */
386             type = "MPEG audio";
387             tofind = p_ps->pes_id;
388             break;
389         /* XXX: 0x64 is for the PMT, so don't take it !!! */
390         case AC3_PES:
391             delta = 0x80; /* 0x80 - 0x8f */
392             type = "MPEG private (AC3 audio)";
393             tofind = p_ps->private_id;
394             break;
395         case LPCM_PES:
396             delta = 0x90; /* 0x90 - 0x9f */
397             type = "MPEG private (LPCM audio)";
398             tofind = p_ps->private_id;
399             break;
400         case SUBTITLE_PES:
401             delta = 0xa0; /* 0xa0 - 0xbf */
402             type = "MPEG private (DVD subtitle)";
403             tofind = p_ps->private_id;
404             break;
405         default:
406             return(-1);
407
408     }
409
410     i = delta + (tofind & 0x1f);
411
412     if( p_ps->association_table[i] == 0)
413     {
414         intf_Msg( "Found %s stream at 0x%.2x, allocating PID 0x%.2x\n",
415                   type, tofind, i );
416         p_ps->association_table[i] = 1;
417     }
418
419     return ( i );
420
421 }
422
423 /******************************************************************************
424  * write_media_ts : writes a ts packet from a ps stream
425  ******************************************************************************/
426
427 void write_media_ts(ps_t *ps, unsigned char *ts, unsigned int pid)
428 {
429     int i,j;
430     s64 clock;
431     long int extclock;
432
433     /* if offset == 0, it means we haven't examined the PS yet */
434     if (ps->offset == 0)
435     {
436         if (ps->pes_size < 184) {
437
438             ts[0] = 0x47;    /* sync_byte */
439             ts[1] = 0x40;    /* payload_unit_start_indicator si début de PES */
440             ts[2] = pid;
441
442             ts[3] = 0x30 + (ps->media_counter[pid] & 0x0f);
443             ts[4] = 184 - ps->pes_size - 1;
444             ts[5] = 0x00;
445             for (i=6 ; i < 188 - ps->pes_size ; i++) ts[i]=0xFF; /* facultatif ? */
446             memcpy(ts + 188 - ps->pes_size, ps->ps_data, ps->pes_size);
447             
448             /* this PS is finished, next time we'll pick a new one */
449             ps->pes_type = NO_PES;
450             ps->ps_data += ps->pes_size;
451             ps->offset += ps->pes_size;
452             return;
453
454         }
455     }
456
457     /* now we still can have offset == 0, but size is initialized */
458     
459     ts[0] = 0x47;                /* sync_byte */
460     ts[1] = (ps->offset == 0) ? 0x40 : 0x00;    /* payload_unit_start_indicator si début de PES */
461     ts[2] = pid;
462
463     if ( (ps->offset == 0) && (ps->has_pts == 0xc0) && (ps->pcr_pid == pid) )
464     {
465
466         ts[3] = 0x30 + (ps->media_counter[pid] & 0x0f);
467         ts[4] = 0x07;            /* taille de l'adaptation field */
468         ts[5] = 0x50;            /* rtfm */
469         
470         /* on va lire le PTS */
471         clock = ( ((s64)(ps->ps_data[9] & 0x0E) << 29) |
472             (((s64)U16_AT(ps->ps_data + 10) << 14) - (1 << 14)) |
473             ((s64)U16_AT(ps->ps_data + 12) >> 1) );
474         
475         ps->has_pts = 0;
476
477         extclock = 0x000;
478         ts[6] = (clock & 0x1fe000000) >> 25;    /* ---111111110000000000000000000000000 */
479         ts[7] = (clock & 0x001fe0000) >> 17;    /* ---000000001111111100000000000000000 */
480         ts[8] = (clock & 0x00001fe00) >>  9;    /* ---000000000000000011111111000000000 */
481         ts[9] = (clock & 0x0000001fe) >>  1;    /* ---000000000000000000000000111111110 */
482             
483         ts[10] = 0x7e + ((clock & 0x01) << 7) + ((extclock & 0x100) >> 8);
484         ts[11] = extclock & 0xff;
485     
486         memcpy(ts + 4 + 8, ps->ps_data, 184 - 8);
487             
488         ts[15] = 0xe0; /* FIXME : we don't know how to choose program yet */
489          
490         ps->offset += 184 - 8;
491         ps->ps_data += 184 - 8;
492     }
493     else if (ps->offset <= ps->pes_size - 184)
494     {
495             
496         ts[3] = 0x10 + (ps->media_counter[pid] & 0x0f);
497         memcpy(ts + 4, ps->ps_data, 184);
498
499         ps->offset += 184;
500         ps->ps_data += 184;
501    
502     }
503     else
504     {
505             
506         j = ps->pes_size - ps->offset;
507         ts[3] = 0x30 + (ps->media_counter[pid] & 0x0f);
508         ts[4] = 184 - j - 1;
509         ts[5] = 0x00;
510         for (i=6 ; i < 188 - j ; i++) ts[i]=0xFF; /* facultatif ? */
511         memcpy(ts + 4 + 184 - j, ps->ps_data, j);
512         ps->offset += j; /* offset = size */
513         ps->ps_data += j; /* offset = size */
514
515         /* the PES is finished */
516         ps->pes_type = NO_PES;
517         ps->sent_ts++;
518
519     }
520
521 }
522
523 /******************************************************************************
524  * write_pat : writes a program association table
525  ******************************************************************************/
526
527 void write_pat(ps_t *ps, unsigned char *ts)
528 {
529     int i;
530
531     ts[0] = 0x47;        /* sync_byte */
532     ts[1] = 0x40;
533     ts[2] = 0x00;        /* PID = 0x0000 */
534     ts[3] = 0x10 + (ps->pat_counter & 0x0f);
535     ts[4] = ts[5] = 0x00;
536     
537     ts[6] = 0xb0; /* */
538     ts[7] = 0x11; /* section_length = 0x011 */
539
540     ts[8] = 0x00;
541     ts[9] = 0xb0; /* TS id = 0x00b0 */
542
543     ts[10] = 0xc1;
544     /* section # and last section # */
545     ts[11] = ts[12] = 0x00;
546
547     /* Network PID (useless) */
548     ts[13] = ts[14] = 0x00; ts[15] = 0xe0; ts[16] = 0x10;
549
550     /* Program Map PID */
551     ts[17] = 0x03; ts[18] = 0xe8; ts[19] = 0xe0; ts[20] = 0x64;
552
553     /* CRC */
554     ts[21] = 0x4d; ts[22] = 0x6a; ts[23] = 0x8b; ts[24] = 0x0f;
555
556     for (i=25 ; i < 188 ; i++) ts[i]=0xFF; /* facultatif ? */
557
558     ps->sent_ts++;
559 }
560
561 /******************************************************************************
562  * write_pmt : writes a program map table
563  ******************************************************************************/
564
565 void write_pmt(ps_t *ps, unsigned char *ts)
566 {
567     int i;
568     
569     ts[0] = 0x47;        /* sync_byte */
570     ts[1] = 0x40;
571     ts[2] = 0x0064;        /* PID = 0x0064 */
572     ts[3] = 0x10 + (ps->pmt_counter & 0x0f);
573     
574     ts[4] = 0x00;
575     ts[5] = 0x02;
576     
577     ts[6] = 0xb0; /* */
578     ts[7] = 0x34; /* section_length = 0x034 */
579
580     ts[8] = 0x03;
581     ts[9] = 0xe8; /* prog number */
582
583     ts[10] = 0xc1;
584     /* section # and last section # */
585     ts[11] = ts[12] = 0x00;
586
587     /* PCR PID */
588     ts[13] = 0xe0;
589     ts[14] = 0x20;
590
591     /* program_info_length == 0 */
592     ts[15] = 0xf0; ts[16] = 0x00;
593
594     /* Program Map / Video PID */
595     ts[17] = 0x02; /* stream type = video */
596     ts[18] = 0xe0; ts[19] = 0x20;
597     ts[20] = 0xf0; ts[21] = 0x09; /* es info length */
598
599     /* useless info */
600     ts[22] = 0x07; ts[23] = 0x04; ts[24] = 0x08; ts[25] = 0x80; ts[26] = 0x24;
601     ts[27] = 0x02; ts[28] = 0x11; ts[29] = 0x01; ts[30] = 0xfe;
602
603     switch ( ps->audio_type )
604     {
605     case 12 :
606     case REQUESTED_AC3 :
607         /* ac3 */
608         ts[31] = 0x81; /* stream type = audio */
609         ts[32] = 0xe0; ts[33] = 0x80 + ps->audio_channel;
610         ts[34] = 0xf0; ts[35] = 0x00; /* es info length */
611         break;
612
613     case REQUESTED_MPEG :
614         /* mpeg */
615         ts[31] = 0x04; /* stream type = audio */
616         ts[32] = 0xe0; ts[33] = 0x40 + ps->audio_channel;
617         ts[34] = 0xf0; ts[35] = 0x00; /* es info length */
618         break;
619
620     case REQUESTED_LPCM :
621         /* LPCM audio */
622         ts[31] = 0x81;
623         ts[32] = 0xe0; ts[33] = 0xa0 + ps->audio_channel;
624         ts[34] = 0xf0; ts[35] = 0x00; /* es info  length */
625         break;
626
627     default :
628         /* No audio */
629         ts[31] = 0x00;
630         ts[35] = 0x00; /* es info  length */
631     }
632
633     /* Subtitles */
634     if( ps->subtitles_channel == NO_SUBTITLES )
635     {
636         ts[36] = 0x00;
637         ts[37] = 0x00; ts[38] = 0x00;
638         ts[39] = 0xf0; ts[40] = 0x00; /* es info length */
639     }
640     else
641     {
642         ts[36] = 0x82;
643         ts[37] = 0xe0; ts[38] = 0xa0 + ( ps->subtitles_channel );
644         ts[39] = 0xf0; ts[40] = 0x00; /* es info length */
645     }
646
647     /* CRC FIXME: not calculated yet*/
648     ts[41] = 0x96; ts[42] = 0x70; ts[43] = 0x0b; ts[44] = 0x7c;
649
650     /* stuffing bytes */
651     for (i=45 ; i < 188 ; i++) ts[i]=0xff; /* facultatif ? */
652
653     ps->sent_ts++;
654 }
655
656
657 /******************************************************************************
658  * ps_thread
659  ******************************************************************************
660  * We use threading to allow cool non-blocking read from the disk. This
661  * implicit thread is the disk (producer) thread, it reads packets from
662  * the PS file on the disk, and stores them in a FIFO.
663  ******************************************************************************/
664
665 void ps_thread( input_file_t * p_if )
666 {
667     int i;
668     ps_t * p_ps =             &p_if->ps;
669     own_pcr_t * p_own_pcr =   &p_if->own_pcr;
670     in_data_t * p_in_data =   &p_if->in_data;
671  
672     /* Initialize the structures */
673     p_own_pcr->start = p_own_pcr->end = 0; /* empty FIFO */
674     vlc_mutex_init( &p_own_pcr->lock );
675     p_in_data->start = p_in_data->end = 0; /* empty FIFO */
676     vlc_mutex_init( &p_in_data->lock );
677     vlc_cond_init( &p_in_data->notfull );
678     vlc_cond_init( &p_in_data->notempty );
679     
680     p_ps->audio_type = main_GetIntVariable( INPUT_DVD_AUDIO_VAR, REQUESTED_AC3 );
681     p_ps->audio_channel = main_GetIntVariable( INPUT_DVD_CHANNEL_VAR, 0 );
682     p_ps->subtitles_channel = main_GetIntVariable( INPUT_DVD_SUBTITLE_VAR, 0 );
683
684     p_ps->pes_type = NO_PES;
685     p_ps->pes_id = 0;
686     p_ps->private_id = 0;
687     p_ps->pes_size = 0;
688     p_ps->to_skip = 0;
689     p_ps->pmt_counter = 0;
690     p_ps->pat_counter = 0;
691     for( i=0; i<256; i++ )
692         p_ps->association_table[i] = 0;
693     p_ps->offset = 0;
694     p_ps->found_pts = 0;
695     p_ps->found_streams = 0;
696     p_ps->pcr_pid = p_if->options.pcr_pid;
697
698     p_ps->ps_buffer = malloc(PS_BUFFER_SIZE);
699     /* those 2 addresses are initialized so that a new packet is read */
700     p_ps->ps_data = p_ps->ps_buffer + PS_BUFFER_SIZE - 1;
701     /* fix the first byte stuff */
702     p_ps->ps_data[0] = 0x00;
703     p_ps->ps_end = p_ps->ps_buffer + PS_BUFFER_SIZE;
704     
705     /* Fill the fifo until it is full */
706     ps_fill( p_if, 0 );
707     /* Launch the thread which fills the fifo */
708     vlc_thread_create( &p_if->disk_thread, "disk thread",
709                        (vlc_thread_func_t)input_DiskThread, p_if ); 
710     /* Init the synchronization XXX add error detection !!! */
711     init_synchro( p_if );
712 }
713
714 /******************************************************************************
715  * ps_read : ps reading method
716  ******************************************************************************/
717
718 ssize_t ps_read( options_t *p_options, ps_t * p_ps, void *ts )
719 {
720     int pid, readbytes = 0;
721     int datasize;
722     p_ps->ts_written = 0;
723   
724     while(p_ps->ts_to_write)
725     {   
726
727         /* if there's not enough data to send */
728         if((datasize = p_ps->ps_end - p_ps->ps_data) <= TS_PACKET_SIZE)
729         {
730             /* copy the remaining bits at the beginning of the PS buffer */
731             memmove ( p_ps->ps_buffer, p_ps->ps_data, datasize);
732             /* read some bytes */
733             readbytes = safe_read( p_options, p_ps->ps_buffer + datasize, PS_BUFFER_SIZE - datasize);
734
735             if(readbytes == 0)
736             {
737                 intf_ErrMsg ( "input: ps read error\n");
738                 return -1;
739             }
740             p_ps->ps_data = p_ps->ps_buffer;
741             p_ps->ps_end = p_ps->ps_data + datasize + readbytes;
742         }
743
744         //printf("offset is %x, pes total size is %x, to skip is %x\n", p_ps->offset, p_ps->pes_size, p_ps->to_skip );
745         if( p_ps->to_skip == 0 && p_ps->offset == p_ps->pes_size )
746         {
747             if( p_ps->ps_data[0] || p_ps->ps_data[1] || (p_ps->ps_data[2] != 0x01) )
748             {
749                 intf_ErrMsg ( "input error: not a startcode (0x%.2x%.2x%.2x instead of 0x000001)\n", p_ps->ps_data[0], p_ps->ps_data[1], p_ps->ps_data[2] );
750                 return -1;
751             }
752
753     p_ps->pes_type = NO_PES;
754     p_ps->offset = 0;
755             p_ps->pes_size = (p_ps->ps_data[4] << 8) + p_ps->ps_data[5] + 6;
756     p_ps->has_pts = p_ps->ps_data[7] & 0xc0;
757         }
758
759         /* if the actual data we have in pes_data is not a PES, then
760          * we read the next one. */
761         if( (p_ps->pes_type == NO_PES) && !p_ps->to_skip )
762         {
763     p_ps->pes_id = p_ps->ps_data[3];
764
765             if (p_ps->pes_id == 0xbd)
766             {
767                 p_ps->private_id = p_ps->ps_data[ 9 + p_ps->ps_data[8] ];
768                 if ((p_ps->private_id & 0xf0) == 0x80)
769                 {
770                     /* flux audio ac3 */
771                     p_ps->pes_type = AC3_PES;
772                 }
773                 else if ((p_ps->private_id & 0xf0) == 0x20)
774                 {
775                     /* subtitles */
776                     p_ps->pes_type = SUBTITLE_PES;
777                 }
778                 else
779                 {
780                     /* unknown private data */
781                     p_ps->pes_type = PRIVATE_PES;
782                 }
783             }
784             else if ((p_ps->pes_id & 0xe0) == 0xc0)
785             {
786                 /* flux audio */
787                 p_ps->pes_type = AUDIO_PES;
788                //write (1, p_ps->ps_data + 9 + p_ps->ps_data[8], 2048 - (9 + p_ps->ps_data[8]));
789             }
790             else if ((p_ps->pes_id & 0xf0) == 0xe0)
791             {
792                 /* flux video */
793                 p_ps->pes_type = VIDEO_PES;
794             }
795             else if (p_ps->pes_id == 0xba)
796             {
797                 p_ps->pes_type = NO_PES;
798                 p_ps->pes_size = 14; /* 8 extra characters after 0x000001ba**** */
799                 p_ps->to_skip = 14;
800             }
801             else
802             {
803                 p_ps->pes_type = UNKNOWN_PES;
804                 p_ps->to_skip = p_ps->pes_size;
805             }
806         }
807
808         if( p_ps->to_skip )
809         {
810             if( p_ps->to_skip < TS_PACKET_SIZE )
811             {
812                 p_ps->ps_data += p_ps->to_skip;
813                 p_ps->offset += p_ps->to_skip;
814                 p_ps->to_skip = 0;
815             }
816             else
817             {
818                 p_ps->ps_data += TS_PACKET_SIZE;
819                 p_ps->offset += TS_PACKET_SIZE;
820                 p_ps->to_skip -= TS_PACKET_SIZE;
821             }
822         }
823
824         /* now that we know what we have, we can either 
825          * write this packet's data in the buffer, skip it,
826          * or write a PMT or PAT table and wait for the next
827          * turn before writing the packet. */
828         switch (p_ps->sent_ts & 0xff)
829         {
830             case 0x80:
831                 write_pmt(p_ps,ts);
832                 p_ps->pmt_counter++;
833                 p_ps->ts_to_write--; p_ps->ts_written++; ts+=188;
834                 break;
835             case 0x00:
836                 write_pat(p_ps,ts);
837                 p_ps->pat_counter++;
838                 p_ps->ts_to_write--; p_ps->ts_written++; ts+=188;
839                 break;
840         }
841
842         /* if there's still no found PCR_PID, and no PTS in this PES, we trash it */
843         if (!p_ps->found_pts)
844         {
845             if (p_ps->has_pts)
846             {
847                 intf_Msg( "input: found a PTS, at last ...\n" );
848                 p_ps->found_pts = 1;
849             }
850             else
851                 p_ps->pes_type = NO_PES;
852         }
853
854         if (p_ps->ts_to_write)
855         {
856             switch(p_ps->pes_type)
857             {
858                 case VIDEO_PES:
859                 case AUDIO_PES:
860 case SUBTITLE_PES:
861                 case AC3_PES:
862                     pid = get_pid (p_ps);
863                     write_media_ts(p_ps, ts, pid);
864                     p_ps->ts_to_write--; p_ps->ts_written++; ts+=188;
865                     p_ps->media_counter[pid]++;
866                     break;
867                 case UNKNOWN_PES:
868                 default:
869                     p_ps->pes_type = NO_PES;
870                     break;
871             }
872         }
873     }
874
875     //p_ps->ps_data += TS_PACKET_SIZE;
876
877     return p_ps->ts_written;
878 }
879
880 /******************************************************************************
881  * ps_fill : Fill the data buffer with TS created from a PS file
882  ******************************************************************************/
883
884 void ps_fill( input_file_t * p_if, boolean_t wait )
885 {
886     in_data_t * p_in_data = &p_if->in_data;
887     ps_t * p_ps = &p_if->ps;
888     int i, how_many;
889     int pcr_flag;
890     file_ts_packet *ts;
891
892     /* How many TS packet for the next UDP packet */
893     how_many = TS_IN_UDP;
894
895     pcr_flag = 0;
896     /* for every single TS packet */
897     while( !p_if->b_die )
898     {        
899         /* wait until we have one free item to store the UDP packet read */
900         vlc_mutex_lock(&p_in_data->lock);
901         while((p_in_data->end+BUF_SIZE+1-p_in_data->start)%(BUF_SIZE+1) == BUF_SIZE )
902         {
903             /* The buffer is full */
904             if(wait)
905             {
906                 vlc_cond_wait(&p_in_data->notfull, &p_in_data->lock);
907                 if( p_if->b_die )
908                     return;
909             }
910             else
911             {
912                 vlc_mutex_unlock(&p_in_data->lock);
913                 if (!pcr_flag)
914                 {
915                     intf_ErrMsg( "input error: bad PCR PID\n" );
916                 }
917                 return;
918             }
919         }
920         vlc_mutex_unlock(&p_in_data->lock);
921         
922         /* read a whole UDP packet from the file */
923         p_ps->ts_to_write = how_many;
924         if(ps_read(&p_if->options, p_ps, ts = (file_ts_packet *)(p_in_data->buf + p_in_data->end)) != how_many)
925         {
926             msleep( 50000 ); /* XXX we need an INPUT_IDLE */
927             intf_ErrMsg( "input error: read() error\n" );
928         }
929         
930         /* Scan to mark TS packets containing a PCR */
931         for(i=0; i<how_many; i++, ts++)
932         {
933             pcr_flag |= keep_pcr(p_ps->pcr_pid, ts);
934         }
935         
936         vlc_mutex_lock(&p_in_data->lock);
937         p_in_data->end++;
938         p_in_data->end %= BUF_SIZE+1;
939         vlc_cond_signal(&p_in_data->notempty);
940         vlc_mutex_unlock(&p_in_data->lock);
941     }
942 }
943
944 int init_synchro( input_file_t * p_if )
945 {
946     int i, pcr_count;
947     int howmany = TS_IN_UDP;
948     file_ts_packet * ts;
949     synchro_t * p_synchro = &p_if->synchro;
950     in_data_t * p_in_data = &p_if->in_data;
951     own_pcr_t * p_own_pcr = &p_if->own_pcr; 
952     
953     p_synchro->slope = 0;
954     pcr_count = 0;
955     
956     /*
957      * Initialisation of the synchro mecanism : wait for 1 PCR
958      * to evaluate delta_clock
959      */
960
961     while( 1 )
962     {
963         vlc_mutex_lock( &p_in_data->lock );
964         
965         while( p_in_data->end == p_in_data->start )
966         {
967             vlc_cond_wait(&p_in_data->notempty, &p_in_data->lock);
968         }
969         /*
970         if( p_in_data->end == p_in_data->start )
971         {
972             intf_ErrMsg( "input error: init_synchro error, not enough PCR found\n" );
973             return( -1 );
974         }
975         */
976         vlc_mutex_unlock( &p_in_data->lock );
977         
978         ts = (file_ts_packet*)(p_in_data->buf + p_in_data->start);
979         for( i=0 ; i < howmany ; i++, ts++ )
980         {
981             if( ts  == p_own_pcr->buf[p_own_pcr->start] && !(((u8*)ts)[5] & 0x80) )
982             {
983                 p_synchro->last_pcr = ts;
984                 p_synchro->last_pcr_time = ConvertPCRTime( ts );
985                 p_synchro->delta_clock = mdate() - ConvertPCRTime(ts);
986                 adjust( p_if, ts );
987                 pcr_count++;
988             }
989         }
990         
991         vlc_mutex_lock( &p_in_data->lock );
992         p_in_data->start++;
993         p_in_data->start %= BUF_SIZE + 1;
994         vlc_cond_signal( &p_in_data->notfull );
995         vlc_mutex_unlock( &p_in_data->lock );
996         
997         if(pcr_count)
998             break; 
999     }
1000     return( 0 );
1001 }
1002
1003 /*****************************************************************************
1004  * input_DiskThread : main thread
1005  *****************************************************************************/
1006
1007 void input_DiskThread( input_file_t * p_if )
1008 {
1009     ps_fill( p_if, 1 );    
1010     vlc_thread_exit();
1011 }
1012
1013 /*****************************************************************************
1014  * input_FileOpen : open a file descriptor
1015  *****************************************************************************/
1016 int input_FileOpen( input_thread_t *p_input )
1017 {
1018     options_t * p_options = &input_file.options;
1019
1020     p_options->in = -1;
1021
1022     p_options->playlist = (char **)p_input->p_source;
1023     p_options->i_list_index = p_input->i_port;
1024
1025     if( file_next( p_options ) < 0 )
1026     {
1027         intf_ErrMsg( "input error: cannot open the file %s", p_input->p_source );
1028     }
1029
1030     input_file.b_die = 0;
1031     safe_read( p_options, &p_options->i_file_type, 1 );
1032     
1033     switch( p_options->i_file_type )
1034     {
1035     case 0x00:
1036         p_options->pcr_pid = PCR_PID;
1037         ps_thread( &input_file );
1038         break;
1039     case 0x47:
1040         intf_ErrMsg( "input error: ts files are not currently supported\n" );
1041         return( 1 );
1042     default:
1043         intf_ErrMsg( "input error: cannot determine stream type\n" );
1044         return( 1 );
1045     }
1046
1047     
1048 return( 0 );
1049 }
1050
1051 /*****************************************************************************
1052  * input_FileRead : read from a file
1053  *****************************************************************************/
1054 int input_FileRead( input_thread_t *p_input, const struct iovec *p_vector,
1055                     size_t i_count )
1056 {
1057     in_data_t * p_in_data = &input_file.in_data;
1058     synchro_t * p_synchro = &input_file.synchro;
1059     own_pcr_t * p_own_pcr = &input_file.own_pcr;
1060     int i, howmany;
1061     file_ts_packet * ts;
1062     
1063     /* XXX XXX XXX
1064      * End condition not verified, should put a flag in ps_fill
1065      */
1066     howmany = TS_IN_UDP;
1067
1068     vlc_mutex_lock( &p_in_data->lock );
1069     while( p_in_data->end == p_in_data->start )
1070     {
1071         if( !input_file.b_die )
1072             vlc_cond_wait( &p_in_data->notempty, &p_in_data->lock );
1073     }
1074     vlc_mutex_unlock( &p_in_data->lock );
1075
1076     ts = (file_ts_packet*)(p_in_data->buf + p_in_data->start);
1077     for( i=0 ; i < howmany ; i++, ts++ )
1078     {             
1079         if( p_synchro->slope && (i == howmany-1) )
1080         {
1081             wait_a_moment( &input_file, ts );
1082         }
1083         if( ts  == p_own_pcr->buf[p_own_pcr->start] )
1084         {
1085             /* the TS packet contains a PCR, so we try to adjust the clock */
1086             adjust( &input_file, ts );
1087         }
1088     }
1089
1090     for( i=0 ; i<howmany ; i++ )
1091     {
1092         memcpy( p_vector[i].iov_base, (char*)(ts - howmany + i), p_vector[i].iov_len );
1093     }
1094
1095     vlc_mutex_lock(&p_in_data->lock);
1096     p_in_data->start++;
1097     p_in_data->start %= BUF_SIZE + 1;
1098     vlc_cond_signal(&p_in_data->notfull);
1099     vlc_mutex_unlock(&p_in_data->lock);
1100     
1101     return( 188*howmany );
1102 }
1103
1104 /*****************************************************************************
1105  * input_FileClose : close a file descriptor
1106  *****************************************************************************/
1107 void input_FileClose( input_thread_t *p_input )
1108 {
1109     input_file.b_die = 1;
1110     vlc_cond_signal( &input_file.in_data.notfull );
1111     vlc_thread_join( input_file.disk_thread );
1112
1113     close( input_file.options.in );
1114 }