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 ... */
46 #include "input_file.h"
48 #define BUF_SIZE (797*3)
53 #define TS_PACKET_SIZE 188
56 #define PS_BUFFER_SIZE 16384
61 #define SUBTITLE_PES 4
63 #define UNKNOWN_PES 12
65 #define PCR_PID 0x20 /* 0x20 == first video stream
66 * 0x40 == first audio stream */
68 typedef u8 file_ts_packet[TS_PACKET_SIZE];
69 typedef file_ts_packet udp_packet[TS_IN_UDP];
71 typedef struct synchro_struct
75 mtime_t last_pcr_time;
77 file_ts_packet *last_pcr;
80 typedef struct in_data_s
86 udp_packet buf[BUF_SIZE+1];
89 typedef struct own_pcr_s
93 file_ts_packet *buf[(BUF_SIZE+1)*TS_IN_UDP+1];
96 typedef struct options_s
105 unsigned int pat_counter;
106 unsigned int pmt_counter;
108 * 16 audio mpeg streams
109 * 16 audio AV3 streams
110 * 16 video mpeg streams
111 * 32 subtitle streams
113 unsigned int media_counter[0x100];
114 unsigned int association_table[0x100];
115 unsigned int found_streams;
117 unsigned int found_pts;
119 unsigned int ts_to_write;
120 unsigned int ts_written;
121 unsigned int sent_ts;
123 unsigned char *ps_data;
124 unsigned char *ps_end;
125 unsigned char *ps_buffer;
128 unsigned int private_id;
129 unsigned int has_pts;
130 unsigned int pcr_pid;
132 unsigned int pes_type;
133 unsigned int pes_size;
134 unsigned int to_skip;
138 typedef struct input_file_s
140 boolean_t b_die; /* b_die flag for the disk thread */
141 vlc_thread_t disk_thread;
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 );
156 input_file_t input_file;
158 /******************************************************************************
159 * ConvertPCRTime : extracts and converts the PCR time in microseconds
160 ******************************************************************************/
162 s64 ConvertPCRTime(file_ts_packet *pcr_buff)
164 return( (((((s64)U32_AT(((u8*)pcr_buff)+6)) << 1) | (((u8*)pcr_buff)[10] >> 7)) * 300) / 27 );
167 /******************************************************************************
168 * wait_a_moment : Compute how long we must wait before sending a TS packet
169 ******************************************************************************/
171 static void wait_a_moment( input_file_t * p_if, file_ts_packet *ts)
173 synchro_t * p_synchro = &input_file.synchro;
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 */
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();
188 intf_DbgMsg( "input warning: wait time may be too long : %Ld\n", wait );
195 if( wait < wait_max )
200 if( retard_count == 16 )
207 /******************************************************************************
208 * adjust : Adjust the encoder clock & remove the PCR from own_pcr
209 ******************************************************************************/
211 static void adjust( input_file_t * p_if, file_ts_packet *ts )
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;
218 if( ((u8*)ts)[5] & 0x80 )
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;
227 p_synchro->last_pcr = ts;
228 p_synchro->last_pcr_time = ConvertPCRTime( ts );
231 vlc_mutex_lock(&p_own_pcr->lock);
233 p_own_pcr->start %= (BUF_SIZE+1)*TS_IN_UDP+1;
235 /* If we have 2 consecutiv PCR, we can reevaluate slope */
236 if( (p_own_pcr->start != p_own_pcr->end) &&
238 !((((u8*) next_pcr = p_own_pcr->buf[p_own_pcr->start]))[5] & 0x80))
240 s64 current_pcr_time = ConvertPCRTime(ts);
241 s64 next_pcr_time = ConvertPCRTime(next_pcr);
243 if( (next_pcr_time - current_pcr_time < 0) || (next_pcr_time - current_pcr_time > 700000))
245 intf_DbgMsg( "input warning: possible discontinuity\n" );
246 p_synchro->delta_clock = mdate() - next_pcr_time;
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));
255 vlc_mutex_unlock(&p_own_pcr->lock);
258 /******************************************************************************
259 * safe_read : Buffered reading method
260 ******************************************************************************/
262 ssize_t safe_read(int fd, unsigned char *buf, int count)
268 ret = read(fd, buf+cnt, count-cnt);
279 /******************************************************************************
280 * keep_pcr : Put a TS packet in the fifo if it owns a PCR
281 ******************************************************************************/
283 int keep_pcr(int pcr_pid, file_ts_packet *ts)
285 own_pcr_t * p_own_pcr = &input_file.own_pcr;
288 if ((p[3] & 0x20) && p[4] && (p[5] & 0x10)
289 && ((((p[1]<<8)+p[2]) & 0x1FFF) == pcr_pid))
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);
304 /******************************************************************************
305 * get_pid : gets a pid from a PES type
306 ******************************************************************************/
308 int get_pid (ps_t *p_ps)
310 int i, tofind, delta;
312 switch( p_ps->pes_type )
316 tofind = p_ps->pes_id;
320 tofind = p_ps->pes_id;
324 tofind = p_ps->private_id;
328 tofind = p_ps->private_id;
334 /* look in the table if we can find one */
335 for ( i=delta; i < delta + 0x20; i++ )
337 if ( p_ps->association_table[i] == tofind )
340 if( !p_ps->association_table[i] )
344 /* we must allocate a new entry */
345 if (i == delta + 0x20)
348 p_ps->association_table[i] = tofind;
349 p_ps->media_counter[i] = 0;
351 intf_Msg( "input: allocated new PID 0x%.2x to stream ID 0x%.2x\n", i, tofind );
356 /******************************************************************************
357 * write_media_ts : writes a ts packet from a ps stream
358 ******************************************************************************/
360 void write_media_ts(ps_t *ps, unsigned char *ts, unsigned int pid)
366 /* if offset == 0, it means we haven't examined the PS yet */
369 if (ps->pes_size < 184) {
371 ts[0] = 0x47; /* sync_byte */
372 ts[1] = 0x40; /* payload_unit_start_indicator si début de PES */
375 ts[3] = 0x30 + (ps->media_counter[pid] & 0x0f);
376 ts[4] = 184 - ps->pes_size - 1;
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);
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;
390 /* now we still can have offset == 0, but size is initialized */
392 ts[0] = 0x47; /* sync_byte */
393 ts[1] = (ps->offset == 0) ? 0x40 : 0x00; /* payload_unit_start_indicator si début de PES */
396 if ( (ps->offset == 0) && (ps->has_pts == 0xc0) && (ps->pcr_pid == pid) )
399 ts[3] = 0x30 + (ps->media_counter[pid] & 0x0f);
400 ts[4] = 0x07; /* taille de l'adaptation field */
401 ts[5] = 0x50; /* rtfm */
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) );
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 */
416 ts[10] = 0x7e + ((clock & 0x01) << 7) + ((extclock & 0x100) >> 8);
417 ts[11] = extclock & 0xff;
419 memcpy(ts + 4 + 8, ps->ps_data, 184 - 8);
421 ts[15] = 0xe0; /* FIXME : we don't know how to choose program yet */
423 ps->offset += 184 - 8;
424 ps->ps_data += 184 - 8;
426 else if (ps->offset <= ps->pes_size - 184)
429 ts[3] = 0x10 + (ps->media_counter[pid] & 0x0f);
430 memcpy(ts + 4, ps->ps_data, 184);
439 j = ps->pes_size - ps->offset;
440 ts[3] = 0x30 + (ps->media_counter[pid] & 0x0f);
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 */
448 /* the PES is finished */
449 ps->pes_type = NO_PES;
456 /******************************************************************************
457 * write_pat : writes a program association table
458 ******************************************************************************/
460 void write_pat(ps_t *ps, unsigned char *ts)
464 ts[0] = 0x47; /* sync_byte */
466 ts[2] = 0x00; /* PID = 0x0000 */
467 ts[3] = 0x10 + (ps->pat_counter & 0x0f);
468 ts[4] = ts[5] = 0x00;
471 ts[7] = 0x11; /* section_length = 0x011 */
474 ts[9] = 0xb0; /* TS id = 0x00b0 */
477 /* section # and last section # */
478 ts[11] = ts[12] = 0x00;
480 /* Network PID (useless) */
481 ts[13] = ts[14] = 0x00; ts[15] = 0xe0; ts[16] = 0x10;
483 /* Program Map PID */
484 ts[17] = 0x03; ts[18] = 0xe8; ts[19] = 0xe0; ts[20] = 0x64;
487 ts[21] = 0x4d; ts[22] = 0x6a; ts[23] = 0x8b; ts[24] = 0x0f;
489 for (i=25 ; i < 188 ; i++) ts[i]=0xFF; /* facultatif ? */
494 /******************************************************************************
495 * write_pmt : writes a program map table
496 ******************************************************************************/
498 void write_pmt(ps_t *ps, unsigned char *ts)
502 ts[0] = 0x47; /* sync_byte */
504 ts[2] = 0x0064; /* PID = 0x0064 */
505 ts[3] = 0x10 + (ps->pmt_counter & 0x0f);
511 ts[7] = 0x34; /* section_length = 0x034 */
514 ts[9] = 0xe8; /* prog number */
517 /* section # and last section # */
518 ts[11] = ts[12] = 0x00;
524 /* program_info_length == 0 */
525 ts[15] = 0xf0; ts[16] = 0x00;
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 */
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;
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 */
542 ts[36] = 0x82; /* stream type = private */
543 ts[37] = 0xe0; ts[38] = 0x60; /* subtitles */
545 ts[36] = 0x81; /* stream type = private */
546 ts[37] = 0xe0; ts[38] = 0x80; /* ac3 audio */
548 ts[39] = 0xf0; ts[40] = 0x0f; /* es info length */
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;
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 */
558 for (i=60 ; i < 188 ; i++) ts[i]=0xFF; /* facultatif ? */
564 /******************************************************************************
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 ******************************************************************************/
572 void ps_thread( input_file_t * p_if )
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;
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 );
587 p_ps->pes_type = NO_PES;
589 p_ps->private_id = 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;
598 p_ps->found_streams = 0;
599 p_ps->pcr_pid = p_if->options.pcr_pid;
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;
608 /* Fill the fifo until it is full */
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 );
616 /******************************************************************************
617 * ps_read : ps reading method
618 ******************************************************************************/
620 ssize_t ps_read (int fd, ps_t * p_ps, void *ts)
622 int pid, readbytes = 0;
624 p_ps->ts_written = 0;
626 while(p_ps->ts_to_write)
629 /* if there's not enough data to send */
630 if((datasize = p_ps->ps_end - p_ps->ps_data) <= TS_PACKET_SIZE)
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);
639 intf_ErrMsg ( "input: ps read error\n");
642 p_ps->ps_data = p_ps->ps_buffer;
643 p_ps->ps_end = p_ps->ps_data + datasize + readbytes;
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 )
649 if( p_ps->ps_data[0] || p_ps->ps_data[1] || (p_ps->ps_data[2] != 0x01) )
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] );
655 p_ps->pes_type = NO_PES;
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;
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 )
665 p_ps->pes_id = p_ps->ps_data[3];
667 if (p_ps->pes_id == 0xbd)
669 p_ps->private_id = p_ps->ps_data[ 9 + p_ps->ps_data[8] ];
670 if ((p_ps->private_id & 0xf0) == 0x80)
673 p_ps->pes_type = AC3_PES;
675 else if ((p_ps->private_id & 0xf0) == 0x20)
678 p_ps->pes_type = SUBTITLE_PES;
682 /* unknown private data */
683 p_ps->pes_type = PRIVATE_PES;
686 else if ((p_ps->pes_id & 0xe0) == 0xc0)
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]));
692 else if ((p_ps->pes_id & 0xf0) == 0xe0)
695 p_ps->pes_type = VIDEO_PES;
697 else if (p_ps->pes_id == 0xba)
699 p_ps->pes_type = NO_PES;
700 p_ps->pes_size = 14; /* 8 extra characters after 0x000001ba**** */
705 p_ps->pes_type = UNKNOWN_PES;
706 p_ps->to_skip = p_ps->pes_size;
712 if( p_ps->to_skip < TS_PACKET_SIZE )
714 p_ps->ps_data += p_ps->to_skip;
715 p_ps->offset += p_ps->to_skip;
720 p_ps->ps_data += TS_PACKET_SIZE;
721 p_ps->offset += TS_PACKET_SIZE;
722 p_ps->to_skip -= TS_PACKET_SIZE;
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)
735 p_ps->ts_to_write--; p_ps->ts_written++; ts+=188;
740 p_ps->ts_to_write--; p_ps->ts_written++; ts+=188;
744 /* if there's still no found PCR_PID, and no PTS in this PES, we trash it */
745 if (!p_ps->found_pts)
749 intf_Msg( "input: found a PTS, at last ...\n" );
753 p_ps->pes_type = NO_PES;
756 if (p_ps->ts_to_write)
758 switch(p_ps->pes_type)
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]++;
771 p_ps->pes_type = NO_PES;
777 //p_ps->ps_data += TS_PACKET_SIZE;
779 return p_ps->ts_written;
782 /******************************************************************************
783 * ps_fill : Fill the data buffer with TS created from a PS file
784 ******************************************************************************/
786 void ps_fill( input_file_t * p_if, boolean_t wait )
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;
795 /* How many TS packet for the next UDP packet */
796 how_many = TS_IN_UDP;
799 /* for every single TS packet */
800 while( !p_if->b_die )
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 )
806 /* The buffer is full */
809 vlc_cond_wait(&p_in_data->notfull, &p_in_data->lock);
815 vlc_mutex_unlock(&p_in_data->lock);
818 intf_ErrMsg( "input error: bad PCR PID\n" );
823 vlc_mutex_unlock(&p_in_data->lock);
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)
829 msleep( 50000 ); /* XXX we need an INPUT_IDLE */
830 intf_ErrMsg( "input error: read() error\n" );
833 /* Scan to mark TS packets containing a PCR */
834 for(i=0; i<how_many; i++, ts++)
836 pcr_flag |= keep_pcr(p_ps->pcr_pid, ts);
839 vlc_mutex_lock(&p_in_data->lock);
841 p_in_data->end %= BUF_SIZE+1;
842 vlc_cond_signal(&p_in_data->notempty);
843 vlc_mutex_unlock(&p_in_data->lock);
847 int init_synchro( input_file_t * p_if )
850 int howmany = TS_IN_UDP;
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;
856 p_synchro->slope = 0;
860 * Initialisation of the synchro mecanism : wait for 1 PCR
861 * to evaluate delta_clock
866 vlc_mutex_lock( &p_in_data->lock );
868 while( p_in_data->end == p_in_data->start )
870 vlc_cond_wait(&p_in_data->notempty, &p_in_data->lock);
873 if( p_in_data->end == p_in_data->start )
875 intf_ErrMsg( "input error: init_synchro error, not enough PCR found\n" );
879 vlc_mutex_unlock( &p_in_data->lock );
881 ts = (file_ts_packet*)(p_in_data->buf + p_in_data->start);
882 for( i=0 ; i < howmany ; i++, ts++ )
884 if( ts == p_own_pcr->buf[p_own_pcr->start] && !(((u8*)ts)[5] & 0x80) )
886 p_synchro->last_pcr = ts;
887 p_synchro->last_pcr_time = ConvertPCRTime( ts );
888 p_synchro->delta_clock = mdate() - ConvertPCRTime(ts);
894 vlc_mutex_lock( &p_in_data->lock );
896 p_in_data->start %= BUF_SIZE + 1;
897 vlc_cond_signal( &p_in_data->notfull );
898 vlc_mutex_unlock( &p_in_data->lock );
906 /*****************************************************************************
907 * input_FileOpen : open a file descriptor
908 *****************************************************************************/
910 void input_DiskThread( input_file_t * p_if )
916 /*****************************************************************************
917 * input_FileOpen : open a file descriptor
918 *****************************************************************************/
919 int input_FileOpen( input_thread_t *p_input )
921 options_t * p_options = &input_file.options;
923 p_options->in = open( p_input->psz_source, O_RDONLY );
924 if( p_options->in < 0 )
926 intf_ErrMsg( "input error: cannot open the file %s", p_input->psz_source );
929 input_file.b_die = 0;
930 read( p_options->in, &p_options->i_file_type, 1 );
932 switch( p_options->i_file_type )
935 p_options->pcr_pid = PCR_PID;
936 ps_thread( &input_file );
939 intf_ErrMsg( "input error: ts files are not currently supported\n" );
942 intf_ErrMsg( "input error: cannot determine stream type\n" );
950 /*****************************************************************************
951 * input_FileRead : read from a file
952 *****************************************************************************/
953 int input_FileRead( input_thread_t *p_input, const struct iovec *p_vector,
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;
963 * End condition not verified, should put a flag in ps_fill
967 vlc_mutex_lock( &p_in_data->lock );
968 while( p_in_data->end == p_in_data->start )
970 if( !input_file.b_die )
971 vlc_cond_wait( &p_in_data->notempty, &p_in_data->lock );
973 vlc_mutex_unlock( &p_in_data->lock );
975 ts = (file_ts_packet*)(p_in_data->buf + p_in_data->start);
976 for( i=0 ; i < howmany ; i++, ts++ )
978 if( p_synchro->slope && (i == howmany-1) )
980 wait_a_moment( &input_file, ts );
982 if( ts == p_own_pcr->buf[p_own_pcr->start] )
984 /* the TS packet contains a PCR, so we try to adjust the clock */
985 adjust( &input_file, ts );
989 for( i=0 ; i<howmany ; i++ )
991 memcpy( p_vector[i].iov_base, (char*)(ts - howmany + i), p_vector[i].iov_len );
994 vlc_mutex_lock(&p_in_data->lock);
996 p_in_data->start %= BUF_SIZE + 1;
997 vlc_cond_signal(&p_in_data->notfull);
998 vlc_mutex_unlock(&p_in_data->lock);
1000 return( 188*howmany );
1003 /*****************************************************************************
1004 * input_FileClose : close a file descriptor
1005 *****************************************************************************/
1006 void input_FileClose( input_thread_t *p_input )
1008 input_file.b_die = 1;
1009 vlc_cond_signal( &input_file.in_data.notfull );
1010 vlc_thread_join( input_file.disk_thread );
1012 close( input_file.options.in );