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