1 /*****************************************************************************
2 * input_file.c: functions to read from a file
3 *****************************************************************************
4 * Copyright (C) 1999, 2000 VideoLAN
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.
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.
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 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
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 ... */
50 #include "input_file.h"
52 #define BUF_SIZE (797*3)
57 #define TS_PACKET_SIZE 188
60 #define MAX_AUDIO_CHANNEL 15
61 #define MAX_SUBTITLES_CHANNEL 31
62 #define NO_SUBTITLES 255
64 #define PS_BUFFER_SIZE 16384
67 #define AUDIO_PES 0x01
68 #define VIDEO_PES 0x02
70 #define SUBTITLE_PES 0x04
72 #define PRIVATE_PES 0x06
73 #define UNKNOWN_PES 0x12
75 #define PCR_PID 0x20 /* 0x20 == first video stream
76 * 0x40 == first audio stream */
78 typedef u8 file_ts_packet[TS_PACKET_SIZE];
79 typedef file_ts_packet udp_packet[TS_IN_UDP];
81 typedef struct synchro_struct
85 mtime_t last_pcr_time;
87 file_ts_packet *last_pcr;
90 typedef struct in_data_s
96 udp_packet buf[BUF_SIZE+1];
99 typedef struct own_pcr_s
103 file_ts_packet *buf[(BUF_SIZE+1)*TS_IN_UDP+1];
106 typedef struct options_s
108 unsigned int pcr_pid;
115 unsigned int pat_counter;
116 unsigned int pmt_counter;
119 * These 3 parameters are passed
120 * as command line arguments
122 unsigned int audio_channel;
123 unsigned int subtitles_channel;
124 unsigned int audio_type;
127 * 16 audio mpeg streams
128 * 16 audio AV3 streams
129 * 16 video mpeg streams
130 * 32 subtitle streams
132 unsigned int media_counter[0x100];
133 unsigned int association_table[0x100];
134 unsigned int found_streams;
136 unsigned int found_pts;
138 unsigned int ts_to_write;
139 unsigned int ts_written;
140 unsigned int sent_ts;
142 unsigned char *ps_data;
143 unsigned char *ps_end;
144 unsigned char *ps_buffer;
147 unsigned int private_id;
148 unsigned int has_pts;
149 unsigned int pcr_pid;
151 unsigned int pes_type;
152 unsigned int pes_size;
153 unsigned int to_skip;
157 typedef struct input_file_s
159 boolean_t b_die; /* b_die flag for the disk thread */
160 vlc_thread_t disk_thread;
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 );
175 input_file_t input_file;
177 /******************************************************************************
178 * ConvertPCRTime : extracts and converts the PCR time in microseconds
179 ******************************************************************************/
181 s64 ConvertPCRTime(file_ts_packet *pcr_buff)
183 return( (((((s64)U32_AT(((u8*)pcr_buff)+6)) << 1) | (((u8*)pcr_buff)[10] >> 7)) * 300) / 27 );
186 /******************************************************************************
187 * wait_a_moment : Compute how long we must wait before sending a TS packet
188 ******************************************************************************/
190 static void wait_a_moment( input_file_t * p_if, file_ts_packet *ts)
192 synchro_t * p_synchro = &input_file.synchro;
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 */
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();
207 intf_DbgMsg( "input warning: wait time may be too long : %Ld\n", wait );
214 if( wait < wait_max )
219 if( retard_count == 16 )
226 /******************************************************************************
227 * adjust : Adjust the encoder clock & remove the PCR from own_pcr
228 ******************************************************************************/
230 static void adjust( input_file_t * p_if, file_ts_packet *ts )
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;
237 if( ((u8*)ts)[5] & 0x80 )
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;
246 p_synchro->last_pcr = ts;
247 p_synchro->last_pcr_time = ConvertPCRTime( ts );
250 vlc_mutex_lock(&p_own_pcr->lock);
252 p_own_pcr->start %= (BUF_SIZE+1)*TS_IN_UDP+1;
254 /* If we have 2 consecutiv PCR, we can reevaluate slope */
255 if( (p_own_pcr->start != p_own_pcr->end) &&
257 !((((u8*) next_pcr = p_own_pcr->buf[p_own_pcr->start]))[5] & 0x80))
259 s64 current_pcr_time = ConvertPCRTime(ts);
260 s64 next_pcr_time = ConvertPCRTime(next_pcr);
262 if( (next_pcr_time - current_pcr_time < 0) || (next_pcr_time - current_pcr_time > 700000))
264 intf_DbgMsg( "input warning: possible discontinuity\n" );
265 p_synchro->delta_clock = mdate() - next_pcr_time;
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));
274 vlc_mutex_unlock(&p_own_pcr->lock);
277 /*****************************************************************************
278 * file_next : Opens the next available file
279 *****************************************************************************/
281 int file_next( options_t *options )
283 p_playlist_t p_playlist = p_main->p_playlist;
285 /* the check for index == 0 has to be done _before_ */
286 p_playlist->i_index--;
288 if( options->in != -1 )
290 close( options->in );
293 if( !strcmp( p_playlist->p_list[ p_playlist->i_index ], "-" ) )
296 return ( options->in = 0 );
300 /* read the actual file */
301 intf_Msg( "Playing file %s\n",
302 p_playlist->p_list[ p_playlist->i_index ] );
305 open( p_playlist->p_list[ p_playlist->i_index ],
306 O_RDONLY | O_NONBLOCK );
308 return ( options->in );
312 /*****************************************************************************
313 * safe_read : Buffered reading method
314 *****************************************************************************/
316 ssize_t safe_read( options_t *options, unsigned char *buf, int count )
322 ret = read( options->in, buf + cnt, count - cnt );
329 /* zero means end of file */
330 if( p_main->p_playlist->i_index )
332 file_next( options );
346 /******************************************************************************
347 * keep_pcr : Put a TS packet in the fifo if it owns a PCR
348 ******************************************************************************/
350 int keep_pcr(int pcr_pid, file_ts_packet *ts)
352 own_pcr_t * p_own_pcr = &input_file.own_pcr;
355 if ((p[3] & 0x20) && p[4] && (p[5] & 0x10)
356 && ((((p[1]<<8)+p[2]) & 0x1FFF) == pcr_pid))
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);
371 /******************************************************************************
372 * get_pid : gets a pid from a PES type
373 ******************************************************************************/
375 int get_pid (ps_t *p_ps)
377 int i, tofind, delta;
380 switch( p_ps->pes_type )
383 delta = 0x20; /* 0x20 - 0x2f */
385 tofind = p_ps->pes_id;
388 delta = 0x40; /* 0x40 - 0x5f */
390 tofind = p_ps->pes_id;
392 /* XXX: 0x64 is for the PMT, so don't take it !!! */
394 delta = 0x80; /* 0x80 - 0x8f */
395 type = "MPEG private (AC3 audio)";
396 tofind = p_ps->private_id;
399 delta = 0x90; /* 0x90 - 0x9f */
400 type = "MPEG private (LPCM audio)";
401 tofind = p_ps->private_id;
404 delta = 0xa0; /* 0xa0 - 0xbf */
405 type = "MPEG private (DVD subtitle)";
406 tofind = p_ps->private_id;
413 i = delta + (tofind & 0x1f);
415 if( p_ps->association_table[i] == 0)
417 intf_Msg( "Found %s stream at 0x%.2x, allocating PID 0x%.2x\n",
419 p_ps->association_table[i] = 1;
426 /******************************************************************************
427 * write_media_ts : writes a ts packet from a ps stream
428 ******************************************************************************/
430 void write_media_ts(ps_t *ps, unsigned char *ts, unsigned int pid)
436 /* if offset == 0, it means we haven't examined the PS yet */
439 if (ps->pes_size < 184) {
441 ts[0] = 0x47; /* sync_byte */
442 ts[1] = 0x40; /* payload_unit_start_indicator si début de PES */
445 ts[3] = 0x30 + (ps->media_counter[pid] & 0x0f);
446 ts[4] = 184 - ps->pes_size - 1;
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);
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;
460 /* now we still can have offset == 0, but size is initialized */
462 ts[0] = 0x47; /* sync_byte */
463 ts[1] = (ps->offset == 0) ? 0x40 : 0x00; /* payload_unit_start_indicator si début de PES */
466 if ( (ps->offset == 0) && (ps->has_pts == 0xc0) && (ps->pcr_pid == pid) )
469 ts[3] = 0x30 + (ps->media_counter[pid] & 0x0f);
470 ts[4] = 0x07; /* taille de l'adaptation field */
471 ts[5] = 0x50; /* rtfm */
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) );
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 */
486 ts[10] = 0x7e + ((clock & 0x01) << 7) + ((extclock & 0x100) >> 8);
487 ts[11] = extclock & 0xff;
489 memcpy(ts + 4 + 8, ps->ps_data, 184 - 8);
491 ts[15] = 0xe0; /* FIXME : we don't know how to choose program yet */
493 ps->offset += 184 - 8;
494 ps->ps_data += 184 - 8;
496 else if (ps->offset <= ps->pes_size - 184)
499 ts[3] = 0x10 + (ps->media_counter[pid] & 0x0f);
500 memcpy(ts + 4, ps->ps_data, 184);
509 j = ps->pes_size - ps->offset;
510 ts[3] = 0x30 + (ps->media_counter[pid] & 0x0f);
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 */
518 /* the PES is finished */
519 ps->pes_type = NO_PES;
526 /******************************************************************************
527 * write_pat : writes a program association table
528 ******************************************************************************/
530 void write_pat(ps_t *ps, unsigned char *ts)
534 ts[0] = 0x47; /* sync_byte */
536 ts[2] = 0x00; /* PID = 0x0000 */
537 ts[3] = 0x10 + (ps->pat_counter & 0x0f);
538 ts[4] = ts[5] = 0x00;
541 ts[7] = 0x11; /* section_length = 0x011 */
544 ts[9] = 0xb0; /* TS id = 0x00b0 */
547 /* section # and last section # */
548 ts[11] = ts[12] = 0x00;
550 /* Network PID (useless) */
551 ts[13] = ts[14] = 0x00; ts[15] = 0xe0; ts[16] = 0x10;
553 /* Program Map PID */
554 ts[17] = 0x03; ts[18] = 0xe8; ts[19] = 0xe0; ts[20] = 0x64;
557 ts[21] = 0x4d; ts[22] = 0x6a; ts[23] = 0x8b; ts[24] = 0x0f;
559 for (i=25 ; i < 188 ; i++) ts[i]=0xFF; /* facultatif ? */
564 /******************************************************************************
565 * write_pmt : writes a program map table
566 ******************************************************************************/
568 void write_pmt(ps_t *ps, unsigned char *ts)
572 ts[0] = 0x47; /* sync_byte */
574 ts[2] = 0x0064; /* PID = 0x0064 */
575 ts[3] = 0x10 + (ps->pmt_counter & 0x0f);
581 ts[7] = 0x34; /* section_length = 0x034 */
584 ts[9] = 0xe8; /* prog number */
587 /* section # and last section # */
588 ts[11] = ts[12] = 0x00;
594 /* program_info_length == 0 */
595 ts[15] = 0xf0; ts[16] = 0x00;
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 */
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;
606 switch ( ps->audio_type )
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 */
616 case REQUESTED_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 */
623 case REQUESTED_LPCM :
626 ts[32] = 0xe0; ts[33] = 0xa0 + ps->audio_channel;
627 ts[34] = 0xf0; ts[35] = 0x00; /* es info length */
633 ts[35] = 0x00; /* es info length */
637 if( ps->subtitles_channel == NO_SUBTITLES )
640 ts[37] = 0x00; ts[38] = 0x00;
641 ts[39] = 0xf0; ts[40] = 0x00; /* es info length */
646 ts[37] = 0xe0; ts[38] = 0xa0 + ( ps->subtitles_channel );
647 ts[39] = 0xf0; ts[40] = 0x00; /* es info length */
650 /* CRC FIXME: not calculated yet*/
651 ts[41] = 0x96; ts[42] = 0x70; ts[43] = 0x0b; ts[44] = 0x7c;
654 for (i=45 ; i < 188 ; i++) ts[i]=0xff; /* facultatif ? */
660 /******************************************************************************
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 ******************************************************************************/
668 void ps_thread( input_file_t * p_if )
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;
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 );
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 );
687 p_ps->pes_type = NO_PES;
689 p_ps->private_id = 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;
698 p_ps->found_streams = 0;
699 p_ps->pcr_pid = p_if->options.pcr_pid;
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;
708 /* Fill the fifo until it is full */
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 );
717 /******************************************************************************
718 * ps_read : ps reading method
719 ******************************************************************************/
721 ssize_t ps_read( options_t *p_options, ps_t * p_ps, void *ts )
723 int pid, readbytes = 0;
725 p_ps->ts_written = 0;
727 while(p_ps->ts_to_write)
730 /* if there's not enough data to send */
731 if((datasize = p_ps->ps_end - p_ps->ps_data) <= TS_PACKET_SIZE)
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);
740 intf_ErrMsg ( "input: ps read error\n");
743 p_ps->ps_data = p_ps->ps_buffer;
744 p_ps->ps_end = p_ps->ps_data + datasize + readbytes;
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 )
750 if( p_ps->ps_data[0] || p_ps->ps_data[1] || (p_ps->ps_data[2] != 0x01) )
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] );
756 p_ps->pes_type = NO_PES;
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;
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 )
766 p_ps->pes_id = p_ps->ps_data[3];
768 if (p_ps->pes_id == 0xbd)
770 p_ps->private_id = p_ps->ps_data[ 9 + p_ps->ps_data[8] ];
771 if ((p_ps->private_id & 0xf0) == 0x80)
774 p_ps->pes_type = AC3_PES;
776 else if ((p_ps->private_id & 0xf0) == 0x20)
779 p_ps->pes_type = SUBTITLE_PES;
783 /* unknown private data */
784 p_ps->pes_type = PRIVATE_PES;
787 else if ((p_ps->pes_id & 0xe0) == 0xc0)
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]));
793 else if ((p_ps->pes_id & 0xf0) == 0xe0)
796 p_ps->pes_type = VIDEO_PES;
798 else if (p_ps->pes_id == 0xba)
800 p_ps->pes_type = NO_PES;
801 p_ps->pes_size = 14; /* 8 extra characters after 0x000001ba**** */
806 p_ps->pes_type = UNKNOWN_PES;
807 p_ps->to_skip = p_ps->pes_size;
813 if( p_ps->to_skip < TS_PACKET_SIZE )
815 p_ps->ps_data += p_ps->to_skip;
816 p_ps->offset += p_ps->to_skip;
821 p_ps->ps_data += TS_PACKET_SIZE;
822 p_ps->offset += TS_PACKET_SIZE;
823 p_ps->to_skip -= TS_PACKET_SIZE;
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)
836 p_ps->ts_to_write--; p_ps->ts_written++; ts+=188;
841 p_ps->ts_to_write--; p_ps->ts_written++; ts+=188;
845 /* if there's still no found PCR_PID, and no PTS in this PES, we trash it */
846 if (!p_ps->found_pts)
850 intf_Msg( "input: found a PTS, at last ...\n" );
854 p_ps->pes_type = NO_PES;
857 if (p_ps->ts_to_write)
859 switch(p_ps->pes_type)
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]++;
872 p_ps->pes_type = NO_PES;
878 //p_ps->ps_data += TS_PACKET_SIZE;
880 return p_ps->ts_written;
883 /******************************************************************************
884 * ps_fill : Fill the data buffer with TS created from a PS file
885 ******************************************************************************/
887 void ps_fill( input_file_t * p_if, boolean_t wait )
889 in_data_t * p_in_data = &p_if->in_data;
890 ps_t * p_ps = &p_if->ps;
895 /* How many TS packet for the next UDP packet */
896 how_many = TS_IN_UDP;
899 /* for every single TS packet */
900 while( !p_if->b_die )
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 )
906 /* The buffer is full */
909 vlc_cond_wait(&p_in_data->notfull, &p_in_data->lock);
915 vlc_mutex_unlock(&p_in_data->lock);
918 intf_ErrMsg( "input error: bad PCR PID\n" );
923 vlc_mutex_unlock(&p_in_data->lock);
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 )
929 msleep( 50000 ); /* XXX we need an INPUT_IDLE */
930 intf_ErrMsg( "input error: read() error\n" );
934 /* Scan to mark TS packets containing a PCR */
935 for( i = 0 ; i < how_many ; i++ , ts++ )
937 pcr_flag |= keep_pcr( p_ps->pcr_pid, ts );
940 vlc_mutex_lock( &p_in_data->lock );
942 p_in_data->end %= BUF_SIZE + 1;
943 vlc_cond_signal( &p_in_data->notempty );
944 vlc_mutex_unlock( &p_in_data->lock );
948 int init_synchro( input_file_t * p_if )
951 int howmany = TS_IN_UDP;
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;
957 p_synchro->slope = 0;
961 * Initialisation of the synchro mecanism : wait for 1 PCR
962 * to evaluate delta_clock
967 vlc_mutex_lock( &p_in_data->lock );
969 while( p_in_data->end == p_in_data->start )
971 vlc_cond_wait(&p_in_data->notempty, &p_in_data->lock);
974 vlc_mutex_unlock( &p_in_data->lock );
976 ts = (file_ts_packet*)(p_in_data->buf + p_in_data->start);
977 for( i=0 ; i < howmany ; i++, ts++ )
979 if( ts == p_own_pcr->buf[p_own_pcr->start] && !(((u8*)ts)[5] & 0x80) )
981 p_synchro->last_pcr = ts;
982 p_synchro->last_pcr_time = ConvertPCRTime( ts );
983 p_synchro->delta_clock = mdate() - ConvertPCRTime(ts);
989 vlc_mutex_lock( &p_in_data->lock );
991 p_in_data->start %= BUF_SIZE + 1;
992 vlc_cond_signal( &p_in_data->notfull );
993 vlc_mutex_unlock( &p_in_data->lock );
1001 /*****************************************************************************
1002 * input_DiskThread : main thread
1003 *****************************************************************************/
1005 void input_DiskThread( input_file_t * p_if )
1011 /*****************************************************************************
1012 * input_FileOpen : open a file descriptor
1013 *****************************************************************************/
1014 int input_FileOpen( input_thread_t *p_input )
1016 options_t * p_options = &input_file.options;
1020 if( file_next( p_options ) < 0 )
1022 intf_ErrMsg( "input error: cannot open the file %s", p_input->p_source );
1025 input_file.b_die = 0;
1026 safe_read( p_options, &p_options->i_file_type, 1 );
1028 switch( p_options->i_file_type )
1031 p_options->pcr_pid = PCR_PID;
1032 ps_thread( &input_file );
1035 intf_ErrMsg( "input error: ts files are not currently supported\n" );
1038 intf_ErrMsg( "input error: cannot determine stream type\n" );
1046 /*****************************************************************************
1047 * input_FileRead : read from a file
1048 *****************************************************************************/
1049 int input_FileRead( input_thread_t *p_input, const struct iovec *p_vector,
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;
1056 file_ts_packet * ts;
1059 * End condition not verified, should put a flag in ps_fill
1061 howmany = TS_IN_UDP;
1063 vlc_mutex_lock( &p_in_data->lock );
1064 while( p_in_data->end == p_in_data->start )
1066 if( !input_file.b_die )
1067 vlc_cond_wait( &p_in_data->notempty, &p_in_data->lock );
1069 vlc_mutex_unlock( &p_in_data->lock );
1071 ts = (file_ts_packet*)(p_in_data->buf + p_in_data->start);
1072 for( i=0 ; i < howmany ; i++, ts++ )
1074 if( p_synchro->slope && (i == howmany-1) )
1076 wait_a_moment( &input_file, ts );
1078 if( ts == p_own_pcr->buf[p_own_pcr->start] )
1080 /* the TS packet contains a PCR, so we try to adjust the clock */
1081 adjust( &input_file, ts );
1085 for( i=0 ; i<howmany ; i++ )
1087 memcpy( p_vector[i].iov_base, (char*)(ts - howmany + i), p_vector[i].iov_len );
1090 vlc_mutex_lock(&p_in_data->lock);
1092 p_in_data->start %= BUF_SIZE + 1;
1093 vlc_cond_signal(&p_in_data->notfull);
1094 vlc_mutex_unlock(&p_in_data->lock);
1096 return( 188*howmany );
1099 /*****************************************************************************
1100 * input_FileClose : close a file descriptor
1101 *****************************************************************************/
1102 void input_FileClose( input_thread_t *p_input )
1104 input_file.b_die = 1;
1105 vlc_cond_signal( &input_file.in_data.notfull );
1106 vlc_thread_join( input_file.disk_thread );
1108 close( input_file.options.in );