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