source: svn/trunk/zas_dstar/pdrivers/pd_dmx.c @ 76

Last change on this file since 76 was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
File size: 65.5 KB
RevLine 
[2]1/******************************************************************************
2 *_Copyright (c) 2009 Digital Stream Technology Inc. All Rights Reserved.
3 *
4 * Module:      pd_dmx.c
5 *
6 * Description
7 *      Pseudo Driver for Demux
8 *
9 * @author Junku Park (hwatk@dstreamtech.com)
10 * @version $Revision: 1.2 $
11 *
12 ******************************************************************************/
13
14#include "dsthalcfg.h"
15#include "dsthallocal.h"
16#include "dsthalerror.h"
17#include "dstoslayer.h"
18#include "dsthaldtv.h"
19#include "pd_dmx.h"
20#include "pd_dmx_priv.h"
21
22#include <stdio.h>
23#include <stdarg.h>
24#include <string.h>
25#include <stdlib.h>
26#include <stdint.h>
27#include <unistd.h>
28
29#include <dvbpsi/dvbpsi.h>
30#include <dvbpsi/psi.h>
31#include <dvbpsi/pat.h>
32
33#ifdef DMALLOC   
34#include <dmalloc.h>   
35#endif   
36
37#include "mpeg2.h"
38
39/******************************************************************************
40 * Global variable declaration
41 ******************************************************************************/
42#define SAVE_ON_FILE    1
43
44#undef USE_MPEG2DEC
45#define USE_MPEG2DEC 0
46
47#ifndef USE_MPEG2DEC
48#error USE_MPEG2DEC is not defined!
49#endif
50/******************************************************************************
51 * Imported variable declaration
52 ******************************************************************************/
53
54/******************************************************************************
55 * Imported function declaration
56 ******************************************************************************/
57
58/******************************************************************************
59 * Local definitions
60 ******************************************************************************/
61#define LOCK_PD_DMX_MUTEX()     do { \
62                if ( OS_TakeMutex(s_DrvDmxMutex) != 0 ) { \
63                        printf("|%s| MUTEX ERROR, LINE=%d\n", __FUNCTION__, __LINE__); \
64                        goto done; \
65                } \
66        } while (0)
67
68#define UNLOCK_PD_DMX_MUTEX()   do { \
69                if ( OS_GiveMutex(s_DrvDmxMutex) != 0 ) { \
70                        printf("|%s| MUTEX ERROR, LINE=%d\n", __FUNCTION__, __LINE__); \
71                } \
72        } while (0)
73       
74#define DMX_LIST_INIT(pfirst)           do { (pfirst) = NULL; } while(0)
75
76#define DMX_LIST_ADD(pfirst,pnew)       do {                                        \
77                                            if ( (pfirst) )                         \
78                                            {                                       \
79                                                (pnew)->pNext = (pfirst);           \
80                                                (pfirst) = (pnew);                  \
81                                            }                                       \
82                                            else                                    \
83                                            {                                       \
84                                                (pfirst) = (pnew);                  \
85                                            }                                       \
86                                        } while (0)
87                                       
88#define DMX_LIST_DEL(pfirst,pcur,pdel)  do {                                        \
89                                            if ( (pfirst) != (pdel) )               \
90                                            {                                       \
91                                                (pcur) = (pfirst);                  \
92                                                while ( (pcur)->pNext != (pdel) )   \
93                                                    (pcur) = (pcur)->pNext;         \
94                                                (pcur)->pNext = (pdel)->pNext;      \
95                                            }                                       \
96                                            else                                    \
97                                            {                                       \
98                                                (pfirst) = (pdel)->pNext;           \
99                                            }                                       \
100                                        } while (0)
101
102/******************************************************************************
103 * Local typedefs
104 ******************************************************************************/
105typedef struct
106{
107    DS_U8                 i_objectTypeIndication;
108    DS_U8                 i_streamType;
109    DS_BOOL                  b_upStream;
110    DS_U32                i_bufferSizeDB;
111    DS_U32                i_maxBitrate;
112    DS_U32                i_avgBitrate;
113
114    int                     i_decoder_specific_info_len;
115    DS_U8                 *p_decoder_specific_info;
116
117} decoder_config_descriptor_t;
118
119typedef struct
120{
121    DS_BOOL                    b_useAccessUnitStartFlag;
122    DS_BOOL                    b_useAccessUnitEndFlag;
123    DS_BOOL                    b_useRandomAccessPointFlag;
124    DS_BOOL                    b_useRandomAccessUnitsOnlyFlag;
125    DS_BOOL                    b_usePaddingFlag;
126    DS_BOOL                    b_useTimeStampsFlags;
127    DS_BOOL                    b_useIdleFlag;
128    DS_BOOL                    b_durationFlag;
129    DS_U32                i_timeStampResolution;
130    DS_U32                i_OCRResolution;
131    DS_U8                 i_timeStampLength;
132    DS_U8                 i_OCRLength;
133    DS_U8                 i_AU_Length;
134    DS_U8                 i_instantBitrateLength;
135    DS_U8                 i_degradationPriorityLength;
136    DS_U8                 i_AU_seqNumLength;
137    DS_U8                 i_packetSeqNumLength;
138
139    DS_U32                i_timeScale;
140    DS_U16                i_accessUnitDuration;
141    DS_U16                i_compositionUnitDuration;
142
143    DS_U64                i_startDecodingTimeStamp;
144    DS_U64                i_startCompositionTimeStamp;
145
146} sl_config_descriptor_t;
147
148typedef struct
149{
150    DS_BOOL                    b_ok;
151    DS_U16                i_es_id;
152
153    DS_BOOL                    b_streamDependenceFlag;
154    DS_BOOL                    b_OCRStreamFlag;
155    DS_U8                 i_streamPriority;
156
157    char                    *psz_url;
158
159    DS_U16                i_dependOn_es_id;
160    DS_U16                i_OCR_es_id;
161
162    decoder_config_descriptor_t    dec_descr;
163    sl_config_descriptor_t         sl_descr;
164
165} es_mpeg4_descriptor_t;
166
167typedef struct
168{
169    DS_U8                 i_iod_label, i_iod_label_scope;
170
171    /* IOD */
172    DS_U16                i_od_id;
173    char                    *psz_url;
174
175    DS_U8                 i_ODProfileLevelIndication;
176    DS_U8                 i_sceneProfileLevelIndication;
177    DS_U8                 i_audioProfileLevelIndication;
178    DS_U8                 i_visualProfileLevelIndication;
179    DS_U8                 i_graphicsProfileLevelIndication;
180
181    es_mpeg4_descriptor_t   es_descr[255];
182
183} iod_descriptor_t;
184
185typedef struct
186{
187    //es_format_t  fmt;
188    //es_out_id_t *id;
189    int         i_pes_size;
190    int         i_pes_gathered;
191    block_t     *p_pes;
192    block_t     **pp_last;
193
194    block_fifo_t    *p_fifo;
195
196    es_mpeg4_descriptor_t *p_mpeg4desc;
197    int         b_gather;
198
199} ts_es_t;
200
201typedef struct
202{
203    int         i_pid;
204
205    DS_BOOL        b_seen;
206    DS_BOOL        b_valid;
207    int         i_cc;   /* countinuity counter */
208
209    /* PSI owner (ie PMT -> PAT, ES -> PMT */
210//    ts_psi_t   *p_owner;
211    dvbpsi_handle   h_dvbpsi;
212    int         i_owner_number;
213
214    /* */
215//    ts_psi_t    *psi;
216    int         p_psi;
217    ts_es_t     *es;
218
219    /* Some private streams encapsulate several ES (eg. DVB subtitles)*/
220    ts_es_t     **extra_es;
221    int         i_extra_es;
222
223    DS_BOOL     bOneShot;
224   
225    /* Stream Type */
226    DS_U8       b_stream_type;
227   
228    /* Section Filter Lists */
229    PD_SECFILTER    *p_sec;
230   
231} ts_pid_t;
232
233typedef struct tag_demux_sys_t
234{
235    //vlc_mutex_t     csa_lock;
236    int         b_force;
237   
238    /* TS packet size (188, 192, 204) */
239    int         i_packet_size;
240
241    /* how many TS packet we read at once */
242    int         i_ts_read;
243
244    /* how many bytes we read */
245    DS_U32      i_firstread;
246    DS_S64      i_nread;
247    DS_U32      i_packet_rate;
248    DS_U32      i_packet_rate_short;
249   
250    /* All pid */
251    ts_pid_t    pid[8192];
252
253    /* All PMT */
254    DS_BOOL        b_user_pmt;
255    int         i_pmt;
256    ts_pid_t    **pmt;
257
258    /* */
259    DS_BOOL        b_es_id_pid;
260    //csa_t       *csa;
261    int         i_csa_pkt_size;
262    DS_BOOL        b_silent;
263
264    DS_BOOL        b_udp_out;
265    int         fd; /* udp socket */
266    DS_U8     *buffer;
267
268    DS_BOOL        b_dvb_control;
269    int         i_dvb_program;
270    DS_S64     i_dvb_start;
271    DS_S64     i_dvb_length;
272//    vlc_list_t  *p_programs_list;
273
274    DS_S64      i_cur_pcr;
275    DS_U64      i_cur_pcr_offset;
276    DS_S64      i_prev_pcr;
277    DS_U64      i_prev_pcr_offset;
278    DS_S64      i_first_pcr;
279    DS_U64      i_first_pcr_offset;
280
281    /* Input TS File */
282    char        psz_infile[256];
283    FILE        *p_infile;
284    DS_U64   i_read;
285    DS_U64      i_filesize;
286   
287    /* TS dump */
288    char        *psz_file;  /* file to dump data in */
289    FILE        *p_file;    /* filehandle */
290    DS_U64    i_write;    /* bytes written */
291    DS_BOOL        b_file_out; /* dump mode enabled */
292
293    /* */
294    DS_BOOL        b_meta;
295    DS_BOOL         bContPlay;
296} demux_sys_t;
297void change_file(int num, int bReadList, int bForce, int bCont);
298
299/******************************************************************************
300 * Local variables declaration
301 ******************************************************************************/
302static int s_PD_DMX_DelayEn = 1;
303static PD_DMX_PID_CALLBACK  s_PidCbFunc = (PD_DMX_PID_CALLBACK)NULL;
304static PD_DMX_SEC_CALLBACK  s_SecCbFunc = (PD_DMX_SEC_CALLBACK)NULL;
305static DS_U32            s_SecCbArg = (DS_U32)NULL;
306
307static demux_sys_t      s_DemuxSys;
308static demux_sys_t      *p_DmxSys = &s_DemuxSys;
309static OS_MUTEX_ID      s_DrvDmxMutex = (OS_MUTEX_ID)NULL;
310static OS_TASK_ID       s_dmxThreadId = (OS_TASK_ID)NULL;
311static DS_BOOL          s_bDrvDmxThreadRun = DS_FALSE;
312static DS_BOOL          s_bDrvDmxThreadIdle = DS_FALSE;
313static DS_BOOL          s_SetFile = DS_FALSE;
314static char            *s_VideoOutputFile = (char *)NULL;
315static char            *s_AudioOutputFile = (char *)NULL;
316static FILE            *s_VideoOut = (FILE *)NULL;
317static FILE            *s_AudioOut = (FILE *)NULL;
318FILE *s_StreamVidOut, *s_StreamAudOut;
319static DS_BOOL          b_pdemux_start = DS_FALSE;
320int pd_dmx_dbg = 1;
321
322/******************************************************************************
323 * Local function prototypes
324 ******************************************************************************/
325static int Init( demux_sys_t *p_sys );
326static int Open( demux_sys_t *p_sys );
327static int Close( demux_sys_t *p_sys );
328static int Control( demux_sys_t *p_sys, int i_query, va_list args );
329static int Demux( demux_sys_t *p_sys );
330
331static int PD_DMX_InitDemuxTask(void);
332static int PD_DMX_StartDemuxTask(void);
333static int PD_DMX_StopDemuxTask(void);
334int PD_DMX_SetOutputFile(const char *video_output, const char *audio_output);
335
336
337static inline int stream_Seek( demux_sys_t *p_sys, DS_S64 i_pos );
338
339#if 0
340___COMMON_APIs___()
341#endif
342int PD_DMX_OpenDemux(void)
343{
344    int retVal = PD_DMX_SUCCESS;
345
346    //if ( retVal )
347      //  goto done;
348    //SysASSERT( PD_DMX_OK(retVal) );
349    retVal = Init(&s_DemuxSys);
350    SysASSERT( PD_DMX_OK(retVal) );
351
352    retVal = PD_DMX_InitDemuxTask();
353    SysASSERT( PD_DMX_OK(retVal) );
354
355        s_DrvDmxMutex = OS_CreateMutex( "DrvDmxMutex" );
356        if ( s_DrvDmxMutex == (OS_MUTEX_ID)NULL ) 
357        {
358            printf("|%s:%d| ERROR\n", __FUNCTION__, __LINE__);
359            retVal = PD_DMX_EOUTOFMEMORY;
360            goto done;
361        }
362
363    b_pdemux_start = DS_FALSE;
364   
365    change_file(0, 0, 0, 1);
366    //PD_DMX_SetOutputFile("./video.vid", "./audio.ac3");
367   
368done:   
369    return retVal;
370}
371
372int PD_DMX_SetDemuxFile(const char *Pathname, DS_BOOL bContiPlay)
373{
374    int retVal = PD_DMX_SUCCESS;
375    FILE *p_fp;
376   
377    if (Pathname)
378        memcpy( p_DmxSys->psz_infile, Pathname, 256 );
379    else
380    {
381        retVal = PD_DMX_EGENERIC;
382        goto notValidFile;
383    }
384
385    if ( s_DrvDmxMutex )
386    {
387        LOCK_PD_DMX_MUTEX();
388    }
389   
390    p_fp = fopen( p_DmxSys->psz_infile, "rb" );
391    if ( p_fp == (FILE *)NULL )
392    {
393        printf("|%s:%d| ERROR: Cannot open file, %s.\n", __FUNCTION__, __LINE__, p_DmxSys->psz_infile );
394        retVal = PD_DMX_EGENERIC;
395        if ( s_DrvDmxMutex )
396        {
397            UNLOCK_PD_DMX_MUTEX();
398        }   
399        goto notValidFile;
400    }
401
402    if ( p_DmxSys->p_infile != (FILE *)NULL )
403    {
404        fclose( p_DmxSys->p_infile );
405    }
406    p_DmxSys->p_infile = p_fp;
407   
408    p_DmxSys->bContPlay = bContiPlay;
409   
410    s_SetFile = DS_TRUE;
411   
412    if ( s_DrvDmxMutex )
413    {
414        UNLOCK_PD_DMX_MUTEX();
415    }
416
417done:   
418    return retVal;
419
420notValidFile:
421    p_DmxSys->p_infile = NULL;
422    s_SetFile = DS_FALSE;
423    return retVal;
424}
425
426int PD_DMX_StartDemux(void)
427{
428    int retVal = PD_DMX_SUCCESS;
429
430    if ( s_SetFile == DS_FALSE )
431    {
432        printf("!!! No file is selected yet, just skip this.\n");
433        return retVal;
434    }
435   
436    if (b_pdemux_start == DS_TRUE )
437        return retVal;
438
439    retVal = Open( &s_DemuxSys );
440    SysASSERT( PD_DMX_OK(retVal) );
441
442    retVal = PD_DMX_StartDemuxTask();
443    SysASSERT( PD_DMX_OK(retVal) );
444   
445    b_pdemux_start = DS_TRUE;
446   
447    return retVal;
448}
449
450int PD_DMX_StopDemux(void)
451{
452    int retVal = PD_DMX_SUCCESS;
453
454    if (b_pdemux_start == DS_FALSE )
455        return retVal;
456
457    retVal = PD_DMX_StopDemuxTask();
458    SysASSERT( PD_DMX_OK(retVal) );
459   
460    b_pdemux_start = DS_FALSE;
461   
462    return retVal;
463}
464
465int PD_DMX_CloseDemux(void)
466{
467    int retVal = PD_DMX_SUCCESS;
468
469    retVal = Close( &s_DemuxSys );
470
471    if ( s_VideoOut )
472    {
473        fclose(s_VideoOut);
474        s_AudioOut = (FILE *)NULL;
475    }
476   
477    if ( s_AudioOut )
478    {
479        fclose(s_AudioOut);
480        s_AudioOut = (FILE *)NULL;
481    }
482   
483    return retVal;
484}
485
486DS_BOOL PD_DMX_IsDemuxStarted(void)
487{
488    return b_pdemux_start;
489}
490
491int PD_DMX_SetOutputFile(const char *video_output, const char *audio_output)
492{
493    int retVal = PD_DMX_SUCCESS;
494    int n;
495    DS_BOOL b_mutex_lock = DS_FALSE;
496
497    if ( !video_output || !audio_output )
498        return PD_DMX_EGENERIC;
499
500    LOCK_PD_DMX_MUTEX();
501    b_mutex_lock = DS_TRUE;
502   
503    if ( s_VideoOutputFile == (char *)NULL )
504        s_VideoOutputFile = malloc(256);
505       
506    if ( s_AudioOutputFile == (char *)NULL )
507        s_AudioOutputFile = malloc(256);
508   
509    SysASSERT( s_VideoOutputFile && s_AudioOutputFile );
510   
511#if SAVE_ON_FILE   
512    if ( s_VideoOutputFile == (char *)NULL )
513    {
514        retVal = PD_DMX_EGENERIC;
515        goto done;
516    }
517   
518    if ( s_AudioOutputFile == (char *)NULL )
519    {
520        retVal = PD_DMX_EGENERIC;
521        goto done;
522    }
523#endif
524           
525    n = strlen(video_output);
526    memcpy( s_VideoOutputFile, video_output, n >= 256 ? 256 : n );   
527
528    n = strlen(audio_output);
529    memcpy( s_AudioOutputFile, audio_output, n >= 256 ? 256 : n );   
530
531    if ( s_VideoOut )
532    {
533        fclose(s_VideoOut);
534        s_VideoOut = (FILE *)NULL;
535    }
536   
537    if ( s_AudioOut )
538    {
539        fclose(s_AudioOut);
540        s_AudioOut = (FILE *)NULL;
541    }
542
543#if SAVE_ON_FILE   
544    s_VideoOut = fopen( s_VideoOutputFile, "wb" );
545    //s_VideoOut = popen( "./mpeg2dec -o sdl", "w" );
546    if ( s_VideoOut == (FILE *)NULL )
547    {
548        perror("Cannot open/create the file.");
549        printf("Cannot open/create the file %s\n", s_VideoOutputFile);
550        retVal = PD_DMX_EGENERIC;
551        goto done;
552    }
553   
554    s_AudioOut = fopen( s_AudioOutputFile, "wb" );
555    if ( s_AudioOut == (FILE *)NULL )
556    {
557        printf("Cannot open/create the file %s\n", s_AudioOutputFile);
558        retVal = PD_DMX_EGENERIC;
559        goto done;
560    }
561#else
562    if ( s_StreamVidOut )
563    {
564        fclose(s_StreamVidOut);
565        s_StreamVidOut = (FILE *)NULL;
566    }
567   
568    if ( s_StreamAudOut )
569    {
570        fclose(s_StreamAudOut);
571        s_StreamAudOut = (FILE *)NULL;
572    }
573
574    //
575    // Open video pipe.
576    //
577    if ( pipe(vidFd) )
578    {
579        printf("!!! cannot open video pipe.\n");
580        retVal = PD_DMX_EGENERIC;
581        goto done;
582    }
583    s_VideoOut = fdopen( vidFd[1], "w" );
584    s_StreamVidOut = fdopen( vidFd[0], "r" );
585    //s_StreamVidOut = fopen( "./video.vid", "rb" );
586    if ( !s_VideoOut || !s_StreamVidOut )
587    {
588        fprintf(stderr, "!!! cannot open video pipe, 0x%lx, 0x%lx\n", (DS_U32)s_VideoOut, (DS_U32)s_StreamVidOut);
589        retVal = PD_DMX_EGENERIC;
590        goto done;
591    }
592   
593    //
594    // Open audio pipe.
595    //
596    if ( pipe(audFd) )
597    {
598        printf("!!! cannot open audio pipe.\n");
599        retVal = PD_DMX_EGENERIC;
600        goto done;
601    }
602    s_AudioOut = fdopen( audFd[1], "wb" );
603    s_StreamAudOut = fdopen( audFd[0], "rb" );
604    if ( !s_AudioOut || !s_StreamAudOut )
605    {
606        fprintf(stderr, "!!! cannot open audio pipe, 0x%lx, 0x%lx\n", (DS_U32)s_AudioOut, (DS_U32)s_StreamAudOut);
607        retVal = PD_DMX_EGENERIC;
608        goto done;
609    }
610
611#endif
612
613done:
614    if ( b_mutex_lock )
615        UNLOCK_PD_DMX_MUTEX();
616       
617    return retVal;
618}
619
620int PD_DMX_EnableDelay(int En)
621{
622    s_PD_DMX_DelayEn = En;
623   
624    return 0;
625}
626
627#if 0
628___PID_Section_Filter_APIs__()
629#endif
630int PD_DMX_SetPidFilterCallback(PD_DMX_PID_CALLBACK CbFunc)
631{
632    int retVal = PD_DMX_SUCCESS;
633   
634    s_PidCbFunc = CbFunc;
635   
636    return retVal;
637}
638
639int PD_DMX_SetSectionFilterCallback(PD_DMX_SEC_CALLBACK CbFunc, DS_U32 Argument)
640{
641    int retVal = PD_DMX_SUCCESS;
642   
643    s_SecCbFunc = CbFunc;
644    s_SecCbArg = Argument;
645   
646    return retVal;
647}
648
649int PD_DMX_CreatePIDFilter(int Pid, DS_U8 streamType, DS_BOOL bOneShot)
650{
651    int retVal = PD_DMX_SUCCESS;
652    ts_pid_t* pPid = (ts_pid_t *)NULL;
653   
654    SysREQUIRE( (Pid < 8192) && (Pid >= 0) );
655   
656    LOCK_PD_DMX_MUTEX();
657   
658    pPid = &p_DmxSys->pid[Pid];
659    pPid->b_valid = DS_TRUE;
660    pPid->bOneShot = bOneShot;
661    pPid->i_owner_number++;
662    pPid->b_stream_type = streamType;
663    pPid->es = (ts_es_t *)malloc(sizeof(ts_es_t));
664    memset( pPid->es, 0, sizeof(ts_es_t));
665
666    pPid->es->p_pes = NULL;
667    pPid->es->pp_last = &pPid->es->p_pes;
668
669    pPid->es->p_fifo = block_FifoNew();
670    if (pPid->es->p_fifo == (block_fifo_t *)NULL )
671    {
672        printf("!!! cannot allocate block_fifo.\n");
673        retVal = PD_DMX_EGENERIC;
674    }
675
676#if USE_MPEG2DEC   
677    if ( streamType == MPEG2_VIDEO_STREAM )
678        mpeg_set_fifo( pPid->es->p_fifo );
679   
680    mpeg_trigger_delete_fifo(0);
681#endif
682
683    UNLOCK_PD_DMX_MUTEX();
684
685done:   
686    return retVal;
687}
688
689int PD_DMX_DeletePIDFilter(int Pid)
690{
691    int retVal = PD_DMX_SUCCESS;
692    ts_pid_t* pPid = (ts_pid_t *)NULL;
693
694    fprintf(stderr, "Pid: %d\n", Pid);
695    SysREQUIRE( (Pid < 8192) && (Pid >= 0) );
696   
697    LOCK_PD_DMX_MUTEX();
698
699    pPid = &p_DmxSys->pid[Pid];
700    pPid->b_valid = DS_FALSE;
701    pPid->i_owner_number = 0;
702
703    if (pPid->es)
704    {
705        if (pPid->es->p_fifo)
706        {
707
708            block_FifoEmpty(pPid->es->p_fifo);
709            block_FifoWake(pPid->es->p_fifo);
710            if ( pPid->b_stream_type == MPEG2_VIDEO_STREAM )
711            {
712#if USE_MPEG2DEC
713                mpeg_trigger_delete_fifo(1);
714#endif
715            }
716            else
717            {
718                block_FifoRelease(pPid->es->p_fifo);
719            }
720   
721            pPid->es->p_fifo = (block_fifo_t *)NULL;
722        }
723
724        free(pPid->es);
725    }
726    pPid->b_stream_type = 0;
727   
728    UNLOCK_PD_DMX_MUTEX();
729
730done:   
731    return retVal;
732}
733
734PD_SECFILTER *PD_DMX_CreateSectionFilter(int Pid, DS_U8* FilterBytes, DS_U8* FilterMasks, 
735                               int FilterSiz, int SectionSize, int bOneShot)
736{
737    PD_SECFILTER* p_newsec = (PD_SECFILTER *)NULL;
738    ts_pid_t* pPid;
739
740    SysREQUIRE( (Pid < 8192) && (Pid >= 0) );
741    SysREQUIRE( FilterSiz <= MAX_FILTER_SIZE );
742   
743    LOCK_PD_DMX_MUTEX();
744
745    pPid = &p_DmxSys->pid[Pid];
746    pPid->b_valid = DS_TRUE;
747    pPid->i_owner_number++;
748   
749    p_newsec = (PD_SECFILTER *)malloc( sizeof(PD_SECFILTER) );
750    SysASSERT( p_newsec );
751   
752    p_newsec->i_pid = Pid;
753    p_newsec->i_section_size = SectionSize;
754    p_newsec->pNext = (PD_SECFILTER *)NULL;
755    memcpy( p_newsec->FilterBytes, FilterBytes, FilterSiz );
756    memcpy( p_newsec->FilterMask, FilterMasks, FilterSiz );
757    p_newsec->i_filter_size = FilterSiz;
758    p_newsec->bEnable = DS_TRUE;
759#if 0   
760    if ( pPid->p_sec == (PD_SECFILTER *)NULL )
761    {
762        /* This is first time to add section filter to specified PID filter. */
763
764    }
765    else
766    {
767        /* Section filter exists already. Have to add end of section filter. */
768       
769    }
770#else
771    DMX_LIST_ADD( pPid->p_sec, p_newsec );
772#endif
773   
774    UNLOCK_PD_DMX_MUTEX();
775
776done:   
777    return p_newsec;
778}
779
780int PD_DMX_EnableSectionFilter( PD_SECFILTER* p_sec, DS_BOOL bEnable)
781{
782    int retVal = PD_DMX_SUCCESS;
783   
784    SysASSERT( p_sec );
785
786    LOCK_PD_DMX_MUTEX();
787    p_sec->bEnable = bEnable;
788    UNLOCK_PD_DMX_MUTEX();
789
790done:
791    return retVal;
792}
793
794int PD_DMX_DeleteSectionFilter( PD_SECFILTER* p_sec )
795{
796    int retVal = PD_DMX_SUCCESS;
797    int Pid;
798    ts_pid_t* pPid;
799    PD_SECFILTER* p_firstsec = (PD_SECFILTER *)NULL;
800    PD_SECFILTER* p_cursec = (PD_SECFILTER *)NULL;
801   
802    SysASSERT( p_sec );
803
804    LOCK_PD_DMX_MUTEX();
805
806    Pid = p_sec->i_pid;
807    pPid = &p_DmxSys->pid[Pid];
808    p_firstsec = pPid->p_sec;
809    pPid->i_owner_number--;
810   
811    DMX_LIST_DEL( p_firstsec, p_cursec, p_sec );
812    if ( pPid->i_owner_number == 0 )
813    {
814        pPid->b_valid = DS_FALSE;
815        pPid->p_sec = NULL;
816    }
817       
818   
819    UNLOCK_PD_DMX_MUTEX();
820
821done:   
822    return retVal;
823}
824
825#if 0
826___MonitorThread___()
827#endif
828static void PD_DMX_MonitorDemuxThread(DS_U32 Arg)
829{
830#define TICKABS(x)  ((x)>=0 ? (x) : (-(x)))
831    demux_sys_t *p_sys = (demux_sys_t *)Arg;
832    volatile DS_U32 curtick, stick;
833    DS_U32 expectedTime, elapsedTime;
834   
835    while(1)
836    {
837        if (s_bDrvDmxThreadRun == DS_FALSE || p_sys->p_infile == NULL )
838        {
839            s_bDrvDmxThreadIdle = DS_TRUE;
840            OS_mDelay(100);
841            continue;
842        }
843       
844        s_bDrvDmxThreadIdle = DS_FALSE;
845       
846        stick = OS_GetTickCount();
847        if ( Demux(p_sys) == -1 /*EOF*/ && p_sys->bContPlay )
848            stream_Seek( p_sys, 0 );
849        curtick = OS_GetTickCount();
850
851        //if ( TICKABS(curtick-stick) && (TICKABS(curtick-stick) < 4) )
852          //  OS_Delay(TICKABS(curtick-stick));
853       
854        if ( p_sys->i_packet_rate && s_PD_DMX_DelayEn )
855        {
856            expectedTime = TICKABS(p_sys->i_firstread + (p_sys->i_nread *100) / p_sys->i_packet_rate);
857            elapsedTime = OS_GetTickCount();
858            if ( elapsedTime < expectedTime )
859            {
860                if ( pd_dmx_dbg >= 2 )
861                {
862                    printf("i_firstread: %ld, nread: %lld, rate: %ld\n", p_sys->i_firstread, p_sys->i_nread, p_sys->i_packet_rate);
863                    printf("Delay %ld more. (Elapsed: %ld, Expected: %ld)\n", ( expectedTime-elapsedTime ), elapsedTime, expectedTime);
864                }
865               
866                if ( ( expectedTime-elapsedTime ) > 100 )
867                    OS_Delay( 100 );
868                else
869                    OS_Delay( expectedTime-elapsedTime );
870            }
871            else
872            {
873            //    printf("i_firstread: %ld, nread: %lld, rate: %ld\n", p_sys->i_firstread, p_sys->i_nread, p_sys->i_packet_rate);
874            //    printf("expectedTime: %ld, Elapsed: %ld\n", expectedTime, elapsedTime);
875            }
876        }
877    }
878#undef TICKABS
879}
880
881static int PD_DMX_InitDemuxTask(void)
882{
883    int retVal = 0;
884
885        s_dmxThreadId = OS_SpawnTask( PD_DMX_MonitorDemuxThread, "tDrvDemuxThread", 0, 4096, (DS_U32)p_DmxSys);
886        if ( s_dmxThreadId == (OS_TASK_ID)NULL ) 
887        {
888                printf("ERROR: Cannot create function tDrvDemuxThread.\n");
889                retVal = PD_DMX_EOUTOFMEMORY;
890        }
891   
892    return retVal;
893}
894
895static int PD_DMX_StartDemuxTask(void)
896{
897    int retVal = 0;
898    int n_retry = 0;
899   
900    s_bDrvDmxThreadRun = DS_TRUE;
901    do {
902        OS_mDelay(10);
903        if ( s_bDrvDmxThreadIdle == DS_FALSE )
904            break;
905    } while ( n_retry++ < 10 );
906   
907    if ( n_retry >= 10 )
908        retVal = PD_DMX_ETIMEOUT;
909   
910    return retVal;
911}
912
913static int PD_DMX_StopDemuxTask(void)
914{
915    int retVal = 0;
916    int n_retry = 0;
917
918    s_bDrvDmxThreadRun = DS_FALSE;
919    do {
920        OS_mDelay(10);
921        if ( s_bDrvDmxThreadIdle == DS_TRUE )
922            break;
923    } while ( n_retry++ < 10 );
924       
925    return retVal;
926}
927
928#if 0
929___stream_Control_APIs___()
930#endif
931/******************************************************************************
932 * stream_Peek
933 *  @param p_sys is global demux system structure.
934 *  @param p_peek is next iSizRead bytes.
935 *  @param iSizRead to read
936 *  @return N total remain bytes on success, otherwise 0.
937 ******************************************************************************/
938static int stream_Peek( demux_sys_t *p_sys, const DS_U8 **p_peek, int iSizRead )
939{
940    static DS_U8 *pBuf = (DS_U8 *)NULL;
941    long cur_pos = 0;
942    int nRead = 0;
943
944    if ( p_sys->p_infile == (FILE *)NULL )
945    {
946        p_sys->p_infile = fopen( p_sys->psz_infile, "r" );
947        if ( p_sys->p_infile == (FILE *)NULL )
948        {
949            printf("|%s:%d| ERROR: Cannot open file, %s\n", __FUNCTION__, __LINE__, p_sys->psz_infile );
950            goto done;
951        }
952    }
953   
954    if ( pBuf )
955        free( pBuf );
956   
957    pBuf = (DS_U8 *)malloc( iSizRead );
958    SysASSERT( pBuf != (DS_U8 *)NULL );
959   
960    cur_pos = ftell( p_sys->p_infile );
961    nRead = fread( pBuf, 1, iSizRead, p_sys->p_infile );
962    if ( nRead > 0 )
963        *p_peek = pBuf;
964    else
965        *p_peek = (DS_U8 *)NULL;
966   
967    SysCHECK( fseek( p_sys->p_infile, cur_pos, SEEK_SET ) == 0 );
968
969done:
970    return nRead;
971}
972
973/******************************************************************************
974 * stream_Control
975 *  @param p_sys is global demux system structure.
976 *  @param i_query to control the stream
977 *  @return 0 on success, otherwise non-zero value.
978 ******************************************************************************/
979static int stream_Control( demux_sys_t *p_sys, int i_query, ... )
980{
981    va_list args;
982    int retVal = 0;
983    DS_S64 *pi_pos;
984    long cur_pos, end_pos;
985
986    if ( p_sys == NULL )
987        return retVal;
988
989    va_start( args, i_query );
990   
991    /*
992     * Do stream Control here.
993     */
994    switch( i_query )
995    {
996        case STREAM_GET_SIZE:
997            pi_pos = (DS_S64 *)va_arg( args, DS_S64 * );
998            cur_pos = ftell( p_sys->p_infile );
999           
1000            SysCHECK( fseek( p_sys->p_infile, 0, SEEK_END ) == 0 );
1001            end_pos = ftell( p_sys->p_infile );
1002           
1003            *pi_pos = (DS_S64)end_pos;
1004           
1005            SysCHECK( fseek( p_sys->p_infile, cur_pos, SEEK_SET ) == 0 );
1006            break;
1007       
1008        case STREAM_SET_POSITION:
1009            cur_pos = (DS_S64)va_arg( args, DS_S64 );
1010            SysCHECK( fseek( p_sys->p_infile, cur_pos, SEEK_SET ) == 0 );
1011            break;
1012           
1013        default:
1014            break;
1015    }
1016   
1017    va_end( args );
1018   
1019    return retVal;
1020}
1021
1022static inline DS_S64 stream_Size( demux_sys_t *p_sys )
1023{
1024    DS_S64 i_pos;
1025    stream_Control( p_sys, STREAM_GET_SIZE, &i_pos );
1026    return i_pos;
1027}
1028
1029static inline int stream_Seek( demux_sys_t *p_sys, DS_S64 i_pos )
1030{
1031//    printf("|%s:%d| Offset to 0, current time: %ld.\n", __FUNCTION__, __LINE__, OS_GetTickCount());   
1032
1033    p_sys->i_nread = 0;
1034    return stream_Control( p_sys, STREAM_SET_POSITION, i_pos );
1035}
1036
1037static block_t *stream_Block( demux_sys_t *p_sys, int i_siz )
1038{
1039    block_t *p_bk = (block_t *)NULL;
1040    DS_U8 *pBuffRead = (DS_U8 *)0;
1041    int nRead = 0;
1042    long curpos;
1043    static long lastpos = 0;
1044   
1045    SysASSERT( p_sys->p_infile );
1046
1047    p_bk = block_Alloc( i_siz );
1048    SysASSERT(p_bk);
1049    //printf("p_bk: 0x%08lX\n", p_bk);
1050   
1051    if ( p_bk == (block_t *)NULL )
1052    {
1053        return p_bk;
1054    }
1055
1056    LOCK_PD_DMX_MUTEX();
1057   
1058    nRead = fread( p_bk->p_buffer, 1, i_siz, p_sys->p_infile );
1059    if ( nRead > 0 )
1060    {
1061        pBuffRead = &p_bk->p_buffer[0];
1062
1063        curpos = ftell( p_sys->p_infile );
1064        if ( (curpos-lastpos) != p_sys->i_packet_size )
1065            printf("!!! Number of last read is %d\n", (int)(curpos-lastpos));
1066        lastpos = curpos;
1067
1068        if ( p_sys->i_nread == 0 )
1069            p_sys->i_firstread = OS_GetTickCount();
1070
1071        p_sys->i_nread += i_siz;
1072       
1073        if ( nRead != i_siz )
1074            printf("nRead: %d, expected: %d\n", nRead, i_siz );
1075    }
1076    else if ( nRead == 0 )
1077    {
1078        lastpos = 0;
1079        block_Release( p_bk );
1080        p_bk = (block_t *)NULL;
1081    }
1082    else
1083    {
1084    }
1085   
1086    UNLOCK_PD_DMX_MUTEX();
1087
1088done:
1089    return p_bk;
1090}
1091
1092/**
1093 * Try to read "i_read" bytes into a buffer pointed by "p_read".  If
1094 * "p_read" is NULL then data are skipped instead of read.  The return
1095 * value is the real numbers of bytes read/skip. If this value is less
1096 * than i_read that means that it's the end of the stream.
1097 */
1098static int stream_Read( demux_sys_t *p_sys, void *p_read, int i_read )
1099{
1100    int nRead = 0;
1101    long curpos;
1102   
1103    if ( p_read )
1104    {
1105        nRead = fread( p_sys->buffer, 1, i_read, p_sys->p_infile );
1106        if ( nRead > 0 )
1107        {
1108            memcpy( p_read, p_sys->buffer, nRead < i_read ? nRead : i_read );
1109            if ( p_sys->i_nread == 0 )
1110                p_sys->i_firstread = OS_GetTickCount();
1111            p_sys->i_nread += i_read;
1112        }
1113    }
1114    else
1115    {
1116        curpos = ftell( p_sys->p_infile );
1117        fseek( p_sys->p_infile, curpos + i_read, SEEK_SET );
1118    }
1119   
1120    return nRead;
1121}
1122
1123static DS_S64 stream_Tell( demux_sys_t *p_sys )
1124{
1125    DS_S64 nPos = 0;
1126   
1127    nPos = (DS_S64)ftell( p_sys->p_infile );
1128   
1129    return nPos;
1130}
1131
1132#if 0
1133___ES_Output___()
1134#endif
1135void _cbPESFilterCallback( ts_pid_t *p_pid, DS_U8 b_stream_type )
1136{
1137    block_t * p_bk, *p_cur_bk;
1138    PESInfo_t pesInfo;
1139   
1140    if ( b_stream_type != SUBTITLE_STREAM )
1141    {
1142            //block_ChainRelease( p_block );
1143        return;
1144    }
1145       
1146    p_bk = block_FifoGet( p_pid->es->p_fifo );
1147    if ( p_bk == (block_t *)NULL )
1148        return;
1149           
1150    if ( !p_bk->i_buffer )
1151    {
1152        /* no data available */
1153       
1154        block_ChainRelease( p_bk );
1155        return;
1156    }
1157   
1158    p_cur_bk = p_bk;
1159    while ( p_cur_bk )
1160    {
1161        if ( !p_cur_bk->i_buffer )
1162            break;
1163           
1164        if ( p_cur_bk->i_buffer > 32*1024 )
1165            fprintf(stderr, "!!! too big buffer is needed! %d\n", (int)p_cur_bk->i_buffer);
1166         
1167        if (s_PidCbFunc)
1168        {
1169            pesInfo.i_flags = p_cur_bk->i_flags;
1170            pesInfo.i_pts = p_cur_bk->i_pts;
1171            pesInfo.i_dts = p_cur_bk->i_dts;
1172           
1173            s_PidCbFunc( p_pid->i_pid, p_cur_bk->p_buffer, p_cur_bk->i_buffer, &pesInfo );
1174        }
1175       
1176        p_cur_bk = p_cur_bk->p_next;
1177    }
1178   
1179    block_ChainRelease( p_bk );
1180}
1181
1182static void es_out_Send( ts_pid_t *p_pid, DS_U8 b_stream_type, block_t *p_block )
1183{
1184    block_t *p_cur_block = p_block;
1185    int nWrite;
1186   
1187    //fprintf(stderr, "p_block: 0x%08lX\n", p_block );
1188    if ( b_stream_type == SUBTITLE_STREAM )
1189    {
1190        block_FifoPut( p_pid->es->p_fifo, p_block );
1191        _cbPESFilterCallback( p_pid, b_stream_type );
1192        return;
1193    }
1194   
1195    /*
1196     * ÇöÀç´Â File Ãâ·Â¸¸ À¯Áö.
1197     */
1198    if ( s_VideoOut && b_stream_type == MPEG2_VIDEO_STREAM )
1199    {
1200        while ( p_cur_block )
1201        {
1202            if ( p_cur_block->i_flags && BLOCK_FLAG_CORRUPTED )
1203            {
1204                fprintf(stderr, "Corrupted packet.\n");
1205            }
1206            else
1207            {
1208                nWrite = fwrite( p_cur_block->p_buffer, p_block->i_buffer, 1, s_VideoOut );
1209                if ( nWrite != 1 )
1210                {
1211                    printf("ERROR: cannot write data into %s.\n", s_VideoOutputFile);
1212                    return;
1213                }
1214            }
1215            p_cur_block = p_block->p_next;
1216        }
1217    }
1218    else if ( s_AudioOut && b_stream_type == AC3_AUDIO_STREAM )
1219    {
1220        while ( p_cur_block )
1221        {
1222            if ( p_cur_block->i_flags && BLOCK_FLAG_CORRUPTED )
1223            {
1224                fprintf(stderr, "Corrupted packet.\n");
1225            }
1226            else
1227            { 
1228                nWrite = fwrite( p_cur_block->p_buffer, p_block->i_buffer, 1, s_AudioOut );
1229                if ( nWrite != 1 )
1230                {
1231                    printf("ERROR: cannot write data into %s\n", s_AudioOutputFile);
1232                    return;
1233                }
1234            }
1235            p_cur_block = p_block->p_next;
1236        }
1237    }
1238
1239#if USE_MPEG2DEC
1240    if ( p_pid->es->p_fifo )
1241#else
1242    if (0)
1243#endif
1244    {
1245        block_FifoPut( p_pid->es->p_fifo, p_block );
1246    }
1247    else
1248    {
1249        //printf( "!!! no fifo is available.\n");
1250        block_ChainRelease( p_block );
1251    }
1252}
1253
1254#if 0
1255___PID_Section_Filter___()
1256#endif
1257static inline int PIDGet( DS_U8 *p )
1258{
1259    return ( (p[1]&0x1f)<<8 )|p[2];
1260}
1261
1262static void PCRHandle( demux_sys_t *p_sys, ts_pid_t *pid, DS_U8 *p )
1263{
1264    DS_U32 rate_in_bits;
1265    DS_U64 bytes;
1266    DS_U32 elapsedTime;
1267   
1268    if( ( p[3]&0x20 ) && /* adaptation */
1269        ( p[5]&0x10 ) &&
1270        ( p[4] >= 7 ) )
1271    {
1272        //int i;
1273        DS_S64 i_pcr;  /* 33 bits (90 kHz based) */
1274
1275        // p[6]     ->program_clock_reference_base[32:25]
1276        // p[7]     ->program_clock_reference_base[24:17]
1277        // p[8]     ->program_clock_reference_base[16:9]
1278        // p[9]     ->program_clock_reference_base[8:1]
1279        // p[10]        ->program_clock_reference_base[0] + reserved[5:0] + program_clock_reference_extension[8]
1280        // p[11]        ->program_clock_reference_extension[7:0]
1281
1282        i_pcr = ( (DS_S64)p[6] << 25 ) |
1283                ( (DS_S64)p[7] << 17 ) |
1284                ( (DS_S64)p[8] << 9 ) |
1285                ( (DS_S64)p[9] << 1 ) |
1286                ( (DS_S64)p[10] >> 7 );
1287
1288//        printf("i_pcr: %lld (@ %ld)\n", i_pcr, p_sys->i_nread);
1289#if 0
1290        /* Search program and set the PCR */
1291        for( i = 0; i < p_sys->i_pmt; i++ )
1292        {
1293            int i_prg;
1294            for( i_prg = 0; i_prg < p_sys->pmt[i]->psi->i_prg; i_prg++ )
1295            {
1296                if( pid->i_pid == p_sys->pmt[i]->psi->prg[i_prg]->i_pid_pcr )
1297                {
1298                    es_out_Control( p_demux->out, ES_OUT_SET_GROUP_PCR,
1299                                    (int)p_sys->pmt[i]->psi->prg[i_prg]->i_number,
1300                                    (int64_t)(i_pcr * 100 / 9) );
1301                }
1302            }
1303        }
1304#else
1305        if ( p_sys->i_first_pcr_offset == 0 )
1306        {
1307            p_sys->i_first_pcr_offset = p_sys->i_nread;
1308            p_sys->i_first_pcr = i_pcr;
1309        }
1310        p_sys->i_prev_pcr_offset = p_sys->i_cur_pcr_offset;
1311        p_sys->i_prev_pcr = p_sys->i_cur_pcr;
1312
1313        p_sys->i_cur_pcr = i_pcr;
1314        p_sys->i_cur_pcr_offset = p_sys->i_nread;
1315       
1316        if ( p_sys->i_first_pcr_offset && p_sys->i_cur_pcr != p_sys->i_first_pcr )
1317        {
1318            bytes = p_sys->i_cur_pcr_offset - p_sys->i_first_pcr_offset;
1319            elapsedTime = (p_sys->i_cur_pcr - p_sys->i_first_pcr);
1320            if ( elapsedTime )
1321                rate_in_bits = ((bytes * 90000) / elapsedTime)*8;
1322           
1323            if ( rate_in_bits >= STREAM_BITRATE_MIN && rate_in_bits <= STREAM_BITRATE_MAX )
1324                p_sys->i_packet_rate = rate_in_bits / 8;
1325
1326            bytes = p_sys->i_cur_pcr_offset - p_sys->i_prev_pcr_offset;
1327            elapsedTime = (p_sys->i_cur_pcr - p_sys->i_prev_pcr);
1328            if ( elapsedTime )
1329                rate_in_bits = ((bytes * 90000) / elapsedTime)*8;
1330
1331            if ( rate_in_bits >= STREAM_BITRATE_MIN && rate_in_bits <= STREAM_BITRATE_MAX )
1332                p_sys->i_packet_rate_short = rate_in_bits / 8;
1333           
1334            if ( pd_dmx_dbg > 3 )
1335                printf("Stream bitrate: %ld\n", rate_in_bits );
1336        }
1337
1338        if ( pd_dmx_dbg > 4 )
1339            printf("PCR: %lld\n", i_pcr * 100 / 9 );
1340#endif
1341    }
1342}
1343
1344void dump(DS_U8 *pBuf)
1345{
1346    int i, j;
1347   
1348    for (i=0; i<16; i++)
1349    {
1350        for (j=0; j<16; j++)
1351            printf("%02X ", pBuf[i*16+j]);
1352        printf("\n");
1353    }
1354}
1355
1356/****************************************************************************
1357 * gathering stuff
1358 ****************************************************************************/
1359static void ParsePES( demux_sys_t *p_demux, ts_pid_t *pid )
1360{
1361    block_t *p_pes = pid->es->p_pes;
1362    uint8_t header[34];
1363    int     i_pes_size = 0;
1364    int     i_skip = 0;
1365    DS_S64 i_dts = -1;
1366    DS_S64 i_pts = -1;
1367    DS_S64 i_length = 0;
1368    int i_max;
1369//    int i;
1370   
1371    /* remove the pes from pid */
1372    pid->es->p_pes = NULL;
1373    pid->es->i_pes_size= 0;
1374    pid->es->i_pes_gathered= 0;
1375    pid->es->pp_last = &pid->es->p_pes;
1376
1377    /* FIXME find real max size */
1378    memset( header, 0, sizeof(uint8_t)*34 );
1379    i_max = block_ChainExtract( p_pes, header, 34 );
1380
1381
1382    if( header[0] != 0 || header[1] != 0 || header[2] != 1 )
1383    {
1384        //if (pd_dmx_dbg)
1385            printf("invalid header [0x%x:%x:%x:%x] (pid: %d)",
1386                                  header[0], header[1],header[2],header[3], pid->i_pid );
1387        //
1388        // TBD: 000001xx¸¦ ãÀ»¶§±îÁö ã¾Æ¾ß ÇÑ´Ù.
1389        //
1390        block_ChainRelease( p_pes );
1391        return;
1392    }
1393
1394    /* TODO check size */
1395    switch( header[3] )
1396    {
1397        case 0xBC/* Program stream map */
1398        case 0xBE/* Padding */
1399        case 0xBF/* Private stream 2 */
1400        case 0xF0/* ECM */
1401        case 0xF1/* EMM */
1402        case 0xFF/* Program stream directory */
1403        case 0xF2/* DSMCC stream */
1404        case 0xF8/* ITU-T H.222.1 type E stream */
1405            i_skip = 6;
1406            break;
1407        default:
1408            if( ( header[6]&0xC0 ) == 0x80 )
1409            {
1410                /* mpeg2 PES */
1411                i_skip = header[8] + 9;
1412
1413                if( header[7]&0x80 )    /* has pts */
1414                {
1415                    i_pts = ((DS_S64)(header[ 9]&0x0e ) << 29)|
1416                             (DS_S64)(header[10] << 22)|
1417                            ((DS_S64)(header[11]&0xfe) << 14)|
1418                             (DS_S64)(header[12] << 7)|
1419                             (DS_S64)(header[13] >> 1);
1420                   
1421                    if( header[7]&0x40 )    /* has dts */
1422                    {
1423                         i_dts = ((DS_S64)(header[14]&0x0e ) << 29)|
1424                                  (DS_S64)(header[15] << 22)|
1425                                 ((DS_S64)(header[16]&0xfe) << 14)|
1426                                  (DS_S64)(header[17] << 7)|
1427                                  (DS_S64)(header[18] >> 1);
1428                    }
1429                }
1430            }
1431            else
1432            {
1433                i_skip = 6;
1434                while( i_skip < 23 && header[i_skip] == 0xff )
1435                {
1436                    i_skip++;
1437                }
1438                if( i_skip == 23 )
1439                {
1440                    printf( "!!! too much MPEG-1 stuffing" );
1441                    block_ChainRelease( p_pes );
1442                    return;
1443                }
1444                if( ( header[i_skip] & 0xC0 ) == 0x40 )
1445                {
1446                    i_skip += 2;
1447                }
1448
1449                if(  header[i_skip]&0x20 )
1450                {
1451                     i_pts = ((DS_S64)(header[i_skip]&0x0e ) << 29)|
1452                              (DS_S64)(header[i_skip+1] << 22)|
1453                             ((DS_S64)(header[i_skip+2]&0xfe) << 14)|
1454                              (DS_S64)(header[i_skip+3] << 7)|
1455                              (DS_S64)(header[i_skip+4] >> 1);
1456
1457                    if( header[i_skip]&0x10 )    /* has dts */
1458                    {
1459                         i_dts = ((DS_S64)(header[i_skip+5]&0x0e ) << 29)|
1460                                  (DS_S64)(header[i_skip+6] << 22)|
1461                                 ((DS_S64)(header[i_skip+7]&0xfe) << 14)|
1462                                  (DS_S64)(header[i_skip+8] << 7)|
1463                                  (DS_S64)(header[i_skip+9] >> 1);
1464                         i_skip += 10;
1465                    }
1466                    else
1467                    {
1468                        i_skip += 5;
1469                    }
1470                }
1471                else
1472                {
1473                    i_skip += 1;
1474                }
1475            }
1476            break;
1477    }
1478
1479    if ( pid->b_stream_type == AC3_AUDIO_STREAM  ||
1480         pid->b_stream_type == MPEG2_AUDIO_STREAM )
1481    {
1482        i_skip += 0;
1483    }
1484#if 0
1485    else if( pid->es->fmt.i_codec == VLC_FOURCC( 'l', 'p', 'c', 'b' ) ||
1486             pid->es->fmt.i_codec == VLC_FOURCC( 's', 'p', 'u', 'b' ) ||
1487             pid->es->fmt.i_codec == VLC_FOURCC( 's', 'd', 'd', 'b' ) )
1488    {
1489        i_skip += 1;
1490    }
1491#endif
1492    else if( pid->b_stream_type == SUBTITLE_STREAM &&
1493             pid->es->p_mpeg4desc )
1494    {
1495        decoder_config_descriptor_t *dcd = &pid->es->p_mpeg4desc->dec_descr;
1496
1497        if( dcd->i_decoder_specific_info_len > 2 &&
1498            dcd->p_decoder_specific_info[0] == 0x10 &&
1499            ( dcd->p_decoder_specific_info[1]&0x10 ) )
1500        {
1501            /* display length */
1502            if( p_pes->i_buffer + 2 <= i_skip )
1503            {
1504                i_length = GetWBE( &p_pes->p_buffer[i_skip] );
1505            }
1506
1507            i_skip += 2;
1508        }
1509        if( p_pes->i_buffer + 2 <= i_skip )
1510        {
1511            i_pes_size = GetWBE( &p_pes->p_buffer[i_skip] );
1512        }
1513        /* */
1514        i_skip += 2;
1515    }
1516   
1517    //if ( pid->b_stream_type == MPEG2_VIDEO_STREAM)
1518    //if (i_skip)
1519      //  printf("i_skip: %d\n", i_skip);
1520
1521    /* skip header */
1522    while( p_pes && i_skip > 0 )
1523    {
1524        if( p_pes->i_buffer <= i_skip )
1525        {
1526            block_t *p_next = p_pes->p_next;
1527
1528            i_skip -= p_pes->i_buffer;
1529            block_Release( p_pes );
1530            p_pes = p_next;
1531        }
1532        else
1533        {
1534            p_pes->i_buffer -= i_skip;
1535            p_pes->p_buffer += i_skip;
1536            break;
1537        }
1538    }
1539
1540    /* ISO/IEC 13818-1 2.7.5: if no pts and no dts, then dts == pts */
1541    if( i_pts >= 0 && i_dts < 0 )
1542        i_dts = i_pts;
1543
1544    if( p_pes )
1545    {
1546        block_t *p_block;
1547//        int i;
1548
1549        //printf("%lx, %lx\n", i_dts, i_pts);
1550
1551        if( i_dts >= 0 )
1552        {
1553            p_pes->i_dts = i_dts * 100 / 9;
1554        }
1555        if( i_pts >= 0 )
1556        {
1557            p_pes->i_pts = i_pts * 100 / 9;
1558        }
1559        p_pes->i_length = i_length * 100 / 9;
1560
1561        p_block = block_ChainGather( p_pes );
1562#if 0
1563        if( pid->es->fmt.i_codec == VLC_FOURCC( 's', 'u', 'b', 't' ) )
1564        {
1565            if( i_pes_size > 0 && p_block->i_buffer > i_pes_size )
1566            {
1567                p_block->i_buffer = i_pes_size;
1568            }
1569            /* Append a \0 */
1570            p_block = block_Realloc( p_block, 0, p_block->i_buffer + 1 );
1571            p_block->p_buffer[p_block->i_buffer -1] = '\0';
1572        }
1573
1574        //
1575        // TBD: PES¸¦ ±×³É ³»º¸³»¾ß ÇÒ °æ¿ì...
1576        //
1577        for( i = 0; i < pid->i_extra_es; i++ )
1578        {
1579            es_out_Send( pid->b_stream_type, block_Duplicate( p_block ) );
1580        }
1581#endif
1582
1583        es_out_Send( pid, pid->b_stream_type, p_block );
1584    }
1585    else
1586    {
1587        if (pd_dmx_dbg) printf("empty pes" );
1588    }
1589}
1590
1591static DS_BOOL GatherPES( demux_sys_t *p_demux, ts_pid_t *pid, block_t *p_bk )
1592{
1593    const DS_U8 *p = p_bk->p_buffer;
1594    int i_buffer = 0;
1595    const DS_U8 b_unit_start = p[1]&0x40;
1596    const DS_U8 b_adaptation = p[3]&0x20;
1597    const DS_U8 b_payload    = p[3]&0x10;
1598    const int  i_cc         = p[3]&0x0f;        /* continuity counter */
1599    DS_BOOL     b_discontinuity = DS_FALSE;     /* discontinuity */
1600    DS_BOOL     b_have_to_drop = DS_FALSE;
1601   
1602    /* transport_scrambling_control is ignored */
1603    int         i_skip = 0;
1604    DS_BOOL     i_ret  = DS_FALSE;
1605    int         i_diff;
1606
1607    /* For now, ignore additional error correction
1608     * TODO: handle Reed-Solomon 204,188 error correction */
1609    //p_bk->i_buffer = TS_PACKET_SIZE_188;
1610    i_buffer = TS_PACKET_SIZE_188;
1611
1612    if( p[1]&0x80 )
1613    {
1614        printf( "transport_error_indicator set (pid=%d)", pid->i_pid );
1615        if( pid->es->p_pes ) //&& pid->es->fmt.i_cat == VIDEO_ES )
1616            pid->es->p_pes->i_flags |= BLOCK_FLAG_CORRUPTED;
1617        //b_have_to_drop = DS_TRUE;
1618    }
1619
1620    if( !b_adaptation )
1621    {
1622        /* We don't have any adaptation_field, so payload starts
1623         * immediately after the 4 byte TS header */
1624        i_skip = 4;
1625    }
1626    else
1627    {
1628        /* p[4] is adaptation_field_length minus one */
1629        i_skip = 5 + p[4];
1630        if( p[4] > 0 )
1631        {
1632            /* discontinuity indicator found in stream */
1633            b_discontinuity = (p[5]&0x80) ? DS_TRUE : DS_FALSE;
1634            if( b_discontinuity && pid->es->p_pes )
1635            {
1636                if ( pd_dmx_dbg )
1637                    printf( "discontinuity indicator (pid=%d) ", pid->i_pid );
1638                /* pid->es->p_pes->i_flags |= BLOCK_FLAG_DISCONTINUITY; */
1639            }
1640        }
1641    }
1642
1643    /* Test continuity counter */
1644    /* continuous when (one of this):
1645        * diff == 1
1646        * diff == 0 and payload == 0
1647        * diff == 0 and duplicate packet (playload != 0) <- should we
1648        *   test the content ?
1649     */
1650    i_diff = ( i_cc - pid->i_cc )&0x0f;
1651    if( b_payload && i_diff == 1 )
1652    {
1653        pid->i_cc = ( pid->i_cc + 1 ) & 0xf;
1654    }
1655    else
1656    {
1657        if( pid->i_cc == 0xff )
1658        {
1659            if ( pd_dmx_dbg )
1660                printf( "first packet for pid=%d cc=0x%x", pid->i_pid, i_cc );
1661            pid->i_cc = i_cc;
1662        }
1663        else if( i_diff != 0 && !b_discontinuity )
1664        {
1665            if ( pd_dmx_dbg )
1666                printf( "discontinuity received 0x%x instead of 0x%x (pid=%d)", 
1667                            i_cc, ( pid->i_cc + 1 )&0x0f, pid->i_pid );
1668
1669            pid->i_cc = i_cc;
1670            if( pid->es->p_pes && pid->b_stream_type != MPEG2_VIDEO_STREAM )
1671            {
1672                /* Small video artifacts are usually better then
1673                 * dropping full frames */
1674                pid->es->p_pes->i_flags |= BLOCK_FLAG_CORRUPTED;
1675            }
1676        }
1677    }
1678
1679    PCRHandle( p_demux, pid, p_bk->p_buffer );
1680
1681    if( i_skip >= 188 || b_have_to_drop )
1682    {
1683        block_Release( p_bk );
1684        return i_ret;
1685    }
1686
1687    /* We have to gather it */
1688    p_bk->p_buffer += i_skip;
1689    p_bk->i_buffer -= i_skip;
1690
1691    if( b_unit_start )
1692    {
1693        //
1694        // ÀÌÀü¿¡ PES¸¦ ¹Þ´ø °ÍÀÌ ÀÖÀ¸¸é, ParsePES·Î º¸³½´Ù.
1695        //
1696        if( pid->es->p_pes )
1697        {
1698            ParsePES( p_demux, pid );
1699            i_ret = DS_TRUE;
1700        }
1701
1702        block_ChainLastAppend( &pid->es->pp_last, p_bk );
1703        if( p_bk->i_buffer > 6 )
1704        {
1705            pid->es->i_pes_size = GetWBE( &p_bk->p_buffer[4] );
1706            if( pid->es->i_pes_size > 0 )
1707            {
1708                pid->es->i_pes_size += 6;
1709            }
1710        }
1711        pid->es->i_pes_gathered += p_bk->i_buffer;
1712        if( pid->es->i_pes_size > 0 &&
1713            pid->es->i_pes_gathered >= pid->es->i_pes_size )
1714        {
1715            ParsePES( p_demux, pid );
1716            i_ret = DS_TRUE;
1717        }
1718    }
1719    else
1720    {
1721        if( pid->es->p_pes == NULL )
1722        {
1723            if (pd_dmx_dbg>2)
1724                printf("broken packet\n");
1725            block_Release( p_bk );
1726        }
1727        else
1728        {
1729            block_ChainLastAppend( &pid->es->pp_last, p_bk );
1730            pid->es->i_pes_gathered += p_bk->i_buffer;
1731            if( pid->es->i_pes_size > 0 &&
1732                pid->es->i_pes_gathered >= pid->es->i_pes_size )
1733            {
1734                ParsePES( p_demux, pid );
1735                i_ret = DS_TRUE;
1736            }
1737        }
1738    }
1739
1740    return i_ret;
1741}
1742
1743static void GatherSections(dvbpsi_decoder_t* p_decoder, dvbpsi_psi_section_t* p_section)
1744{
1745    PD_SECFILTER *p_cursec = (PD_SECFILTER *)NULL;
1746    ts_pid_t *pid;
1747    uint16_t i_pid;
1748    int i;
1749    DS_BOOL bFound = DS_FALSE;
1750    register DS_U8 b1, b2;
1751   
1752    i_pid = p_decoder->i_pid;
1753    SysASSERT( (i_pid<=8192) );
1754   
1755    pid = &p_DmxSys->pid[i_pid];
1756   
1757    /*
1758     * Find the appropriate filter.
1759     */
1760    for (p_cursec = pid->p_sec; p_cursec; p_cursec = p_cursec->pNext)
1761    {
1762        if (p_cursec->bEnable == DS_FALSE)
1763            continue;
1764           
1765        for (i=0; i<p_cursec->i_filter_size; i++)
1766        {
1767            b1 = (p_cursec->FilterBytes[i] & p_cursec->FilterMask[i]);
1768            b2 = (p_section->p_data[i] & p_cursec->FilterMask[i]);
1769            if ( b1 != b2 )
1770                break;
1771        }
1772       
1773        if (i == p_cursec->i_filter_size)
1774        {
1775            bFound = DS_TRUE;
1776            break;
1777        }
1778    }
1779
1780    if ( bFound == DS_TRUE )
1781    {
1782        if ( s_SecCbFunc )
1783            s_SecCbFunc( p_cursec, p_section->p_data, p_section->i_length + 4);
1784    }
1785    else
1786    {
1787        /* do nothing. */
1788    }
1789}
1790
1791#if 0
1792___Demux_Main___()
1793#endif
1794/*****************************************************************************
1795 * Init
1796 *****************************************************************************/
1797static int Init( demux_sys_t *p_sys )
1798{
1799    int          i;
1800
1801//    ts_pid_t    *pat;
1802//    const char  *psz_mode;
1803//    DS_BOOL         b_append;
1804
1805//    vlc_value_t  val;
1806
1807    //p_sys = &s_DemuxSys;
1808    //memset( p_sys, 0, sizeof( demux_sys_t ) );
1809
1810    p_sys->i_firstread = 0;
1811    p_sys->i_nread = 0;
1812    p_sys->b_force = DS_FALSE;
1813   
1814    p_sys->i_filesize = 0;
1815   
1816    p_sys->i_cur_pcr = 0;
1817    p_sys->i_cur_pcr_offset = 0;
1818    p_sys->i_prev_pcr = 0;
1819    p_sys->i_prev_pcr_offset = 0;
1820    p_sys->i_first_pcr = 0;
1821    p_sys->i_first_pcr_offset = 0;
1822
1823    //vlc_mutex_init( &p_sys->csa_lock );
1824
1825    /* Fill dump mode fields */
1826    p_sys->i_write = 0;
1827    p_sys->p_file = NULL;
1828    p_sys->b_file_out = DS_FALSE;
1829
1830    /* Init p_sys field */
1831    p_sys->b_meta = DS_TRUE;
1832    p_sys->b_dvb_control = DS_TRUE;
1833    p_sys->i_dvb_program = 0;
1834    p_sys->i_dvb_start = 0;
1835    p_sys->i_dvb_length = 0;
1836
1837    for( i = 0; i < 8192; i++ )
1838    {
1839        ts_pid_t *pid = &p_sys->pid[i];
1840
1841        pid->i_pid      = i;
1842        pid->b_seen     = DS_FALSE;
1843        pid->b_valid    = DS_FALSE;
1844        pid->i_owner_number = 0;
1845       
1846        DMX_LIST_INIT( pid->p_sec );
1847        pid->h_dvbpsi = dvbpsi_AttachSection( (dvbpsi_callback)GatherSections, NULL, i );
1848        //pid->p_sec      = (PD_SECFILTER *)NULL;
1849    }
1850
1851    /* PID 8191 is padding */
1852    p_sys->pid[8191].b_seen = DS_TRUE;
1853    p_sys->b_udp_out = DS_FALSE;
1854    p_sys->i_ts_read = 50;
1855
1856    /* Init PMT array */
1857    p_sys->i_pmt = 0;
1858    p_sys->pmt   = NULL;
1859    p_sys->b_silent = DS_TRUE;
1860   
1861    return PD_DMX_SUCCESS;
1862}
1863
1864static int Open( demux_sys_t *p_sys )
1865{
1866    const DS_U8 *p_peek;
1867    int          i_peek = 0, i_sync = 0;
1868    int          i_packet_size;
1869    DS_BOOL         b_topfield = DS_FALSE;
1870    int         retry_cnt=0;
1871   
1872    //
1873    // TBD: Packet rate shall be calculated on the incoming file.
1874    //
1875    p_sys->i_packet_rate = STREAM_BITRATE_DEF/8;
1876   
1877    if( stream_Peek( p_sys, &p_peek, TS_PACKET_SIZE_MAX*8 ) < TS_PACKET_SIZE_MAX*8 ) 
1878        return PD_DMX_EGENERIC;
1879
1880    if( memcmp( p_peek, "TFrc", 4 ) == 0 )
1881    {
1882        b_topfield = DS_TRUE;
1883        if ( pd_dmx_dbg ) printf( "this is a topfield file\n" );
1884    }
1885    i_sync = 0;
1886retry_label:
1887    if (i_sync >= (TS_PACKET_SIZE_MAX*8))
1888    {
1889        printf( "TS module discarded (lost sync)\n" );
1890        return PD_DMX_EGENERIC;
1891    }
1892   
1893    /* Search first sync byte */
1894    for( ; i_sync < (TS_PACKET_SIZE_MAX*8); i_sync++ )
1895    {
1896        if( p_peek[i_sync] == 0x47 ) break;
1897    }
1898   
1899    if( i_sync >= (TS_PACKET_SIZE_MAX*8) && !b_topfield )
1900    {
1901        if( !p_sys->b_force )
1902        {
1903            if ( pd_dmx_dbg ) printf( "this does not look like a TS stream\n" );
1904            return PD_DMX_EGENERIC;
1905        }
1906
1907        if ( pd_dmx_dbg ) printf( "this does not look like a TS stream, continuing\n" );
1908    }
1909
1910    if( b_topfield )
1911    {
1912        /* Read the entire Topfield header */
1913        i_peek = TS_TOPFIELD_HEADER;
1914    }
1915    else
1916    {
1917        /* Check next 3 sync bytes */
1918        i_peek = TS_PACKET_SIZE_MAX * (8+3) + i_sync + 1;
1919    }
1920
1921    if( ( stream_Peek( p_sys, &p_peek, i_peek ) ) < i_peek )
1922    {
1923        if ( pd_dmx_dbg ) printf( "cannot peek\n" );
1924        return PD_DMX_EGENERIC;
1925    }
1926   
1927    //dump(p_peek);
1928   
1929    if( p_peek[i_sync + TS_PACKET_SIZE_188] == 0x47 &&
1930        p_peek[i_sync + 2 * TS_PACKET_SIZE_188] == 0x47 &&
1931        p_peek[i_sync + 3 * TS_PACKET_SIZE_188] == 0x47 )
1932    {
1933        i_packet_size = TS_PACKET_SIZE_188;
1934    }
1935    else if( p_peek[i_sync + TS_PACKET_SIZE_192] == 0x47 &&
1936             p_peek[i_sync + 2 * TS_PACKET_SIZE_192] == 0x47 &&
1937             p_peek[i_sync + 3 * TS_PACKET_SIZE_192] == 0x47 )
1938    {
1939        i_packet_size = TS_PACKET_SIZE_192;
1940    }
1941    else if( p_peek[i_sync + TS_PACKET_SIZE_196] == 0x47 &&
1942             p_peek[i_sync + 2 * TS_PACKET_SIZE_196] == 0x47 &&
1943             p_peek[i_sync + 3 * TS_PACKET_SIZE_196] == 0x47 )
1944    {
1945        i_packet_size = TS_PACKET_SIZE_196;
1946    }
1947    else if( p_peek[i_sync + TS_PACKET_SIZE_204] == 0x47 &&
1948             p_peek[i_sync + 2 * TS_PACKET_SIZE_204] == 0x47 &&
1949             p_peek[i_sync + 3 * TS_PACKET_SIZE_204] == 0x47 )
1950    {
1951        i_packet_size = TS_PACKET_SIZE_204;
1952    }
1953    else if( p_sys->b_force )
1954    {
1955        i_packet_size = TS_PACKET_SIZE_188;
1956    }
1957    else if( b_topfield )
1958    {
1959        i_packet_size = TS_PACKET_SIZE_188;
1960    }
1961    else
1962    {
1963        if (retry_cnt++<8)
1964        {
1965            printf("retry! %d\n", retry_cnt);
1966            i_sync++;
1967            goto retry_label;
1968        }
1969        if ( pd_dmx_dbg ) printf( "TS module discarded (lost sync)\n" );
1970        return PD_DMX_EGENERIC;
1971    }
1972    p_sys->i_packet_size = i_packet_size;
1973    if ( p_sys->buffer == (DS_U8 *)NULL )
1974        p_sys->buffer = (DS_U8 *)malloc(TS_PACKET_SIZE_204);
1975    SysASSERT( p_sys->buffer );
1976
1977    p_sys->i_nread = 0;
1978    p_sys->i_first_pcr_offset = p_sys->i_cur_pcr_offset = p_sys->i_prev_pcr_offset = 0;
1979    p_sys->i_first_pcr = p_sys->i_cur_pcr = p_sys->i_prev_pcr = 0;
1980    p_sys->i_filesize = stream_Size(p_sys);
1981   
1982    if ( pd_dmx_dbg )
1983        printf("[PD-INFO] TS packet size: %d\n", i_packet_size );
1984
1985    return PD_DMX_SUCCESS;
1986}
1987
1988/*****************************************************************************
1989 * Close
1990 *****************************************************************************/
1991static int Close( demux_sys_t *p_sys )
1992{
1993    int retVal = PD_DMX_SUCCESS;
1994   
1995    int          i;
1996
1997    if ( pd_dmx_dbg ) printf( "pid list:" );
1998    for( i = 0; i < 8192; i++ )
1999    {
2000        ts_pid_t *pid = &p_sys->pid[i];
2001#if 0
2002        if( pid->b_valid && pid->psi )
2003        {
2004            switch( pid->i_pid )
2005            {
2006                case 0: /* PAT */
2007                    dvbpsi_DetachPAT( pid->psi->handle );
2008                    free( pid->psi );
2009                    break;
2010                case 1: /* CAT */
2011                    free( pid->psi );
2012                    break;
2013                case 0x11: /* SDT */
2014                case 0x12: /* EIT */
2015                    dvbpsi_DetachDemux( pid->psi->handle );
2016                    free( pid->psi );
2017                    break;
2018                default:
2019                    PIDClean( p_demux->out, pid );
2020                    break;
2021            }
2022        }
2023        else if( pid->b_valid && pid->es )
2024        {
2025            PIDClean( p_demux->out, pid );
2026        }
2027#endif
2028        if( pid->b_seen )
2029        {
2030            if ( pd_dmx_dbg ) printf( "  - pid[%d] seen\n", pid->i_pid );
2031        }
2032    }
2033
2034#if 0
2035    if( p_sys->b_udp_out )
2036    {
2037        net_Close( p_sys->fd );
2038    }
2039    if( p_sys->csa )
2040    {
2041        var_DelCallback( p_demux, "ts-csa-ck", ChangeKeyCallback, NULL );
2042        var_DelCallback( p_demux, "ts-csa2-ck", ChangeKeyCallback, NULL );
2043        csa_Delete( p_sys->csa );
2044        p_sys->csa = NULL;
2045    }
2046
2047    if( p_sys->i_pmt ) free( p_sys->pmt );
2048
2049    if ( p_sys->p_programs_list )
2050    {
2051        vlc_value_t val;
2052        val.p_list = p_sys->p_programs_list;
2053        var_Change( p_demux, "programs", VLC_VAR_FREELIST, &val, NULL );
2054    }
2055
2056    /* If in dump mode, then close the file */
2057    if( p_sys->b_file_out )
2058    {
2059        if ( pd_dmx_dbg ) printf( "closing %s (%"PRId64" Kbytes dumped)\n",
2060                  p_sys->psz_file, p_sys->i_write / 1024 );
2061
2062        if( p_sys->p_file != stdout )
2063        {
2064            fclose( p_sys->p_file );
2065            p_sys->p_file = NULL;
2066        }
2067    }
2068
2069    if ( p_sys->buffer )
2070        free( p_sys->buffer );
2071    free( p_sys->psz_file );
2072    p_sys->psz_file = NULL;
2073
2074    //vlc_mutex_destroy( &p_sys->csa_lock );
2075    free( p_sys );
2076#endif
2077    if ( p_sys->p_infile )
2078        fclose( p_sys->p_infile );
2079   
2080    p_sys->p_infile = (FILE *)NULL;
2081   
2082    return retVal;
2083}
2084
2085static int Control( demux_sys_t *p_sys, int i_query, va_list args )
2086{
2087    double f, *pf;
2088    DS_S64 i64;
2089    //DS_S64 *pi64;
2090    //int i_int;
2091
2092    switch( i_query )
2093    {
2094        case DEMUX_GET_POSITION:
2095            pf = (double*) va_arg( args, double* );
2096            i64 = stream_Size( p_sys );
2097            if( i64 > 0 )
2098            {
2099                *pf = (double)stream_Tell( p_sys ) / (double)i64;
2100            }
2101            return PD_DMX_SUCCESS;
2102
2103        case DEMUX_SET_POSITION:
2104            f = (double) va_arg( args, double );
2105            i64 = stream_Size( p_sys );
2106
2107            //es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
2108            if( stream_Seek( p_sys, (DS_S64)(i64 * f) ) )
2109            {
2110                return PD_DMX_EGENERIC;
2111            }
2112            return PD_DMX_SUCCESS;
2113
2114        case DEMUX_GET_FPS:
2115        case DEMUX_SET_TIME:
2116        default:
2117            return PD_DMX_EGENERIC;
2118    }
2119}
2120
2121/*****************************************************************************
2122 * Demux:
2123 *****************************************************************************/
2124static int Demux( demux_sys_t *p_sys )
2125{
2126    int          i_pkt;
2127//    PD_SECFILTER    *p_cursec = (PD_SECFILTER *)NULL;
2128   
2129    /* We read at most 100 TS packet or until a frame is completed */
2130    for( i_pkt = 0; i_pkt < p_sys->i_ts_read; i_pkt++ )
2131    {
2132        DS_BOOL         b_frame = DS_FALSE;
2133        block_t     *p_pkt;
2134        ts_pid_t    *p_pid;
2135
2136        /* Get a new TS packet */
2137        if( !( p_pkt = stream_Block( p_sys, p_sys->i_packet_size ) ) )
2138        {
2139            //if ( pd_dmx_dbg ) printf( "eof ?\n" );
2140            return -1;
2141        }
2142
2143        /* Check sync byte and re-sync if needed */
2144        if( p_pkt->p_buffer[0] != 0x47 )
2145        {
2146            if ( pd_dmx_dbg ) printf( "lost synchro\n" );
2147            block_Release( p_pkt );
2148
2149            while( 1 )
2150            {
2151                const DS_U8 *p_peek;
2152                int i_peek, i_skip = 0;
2153
2154                i_peek = stream_Peek( p_sys, &p_peek,
2155                                      p_sys->i_packet_size * 10 );
2156                if( i_peek < p_sys->i_packet_size + 1 )
2157                {
2158                    //if ( pd_dmx_dbg ) printf( "eof ?\n" );
2159                    return -1;
2160                }
2161
2162                while( i_skip < i_peek - p_sys->i_packet_size )
2163                {
2164                    if( p_peek[i_skip] == 0x47 &&
2165                        p_peek[i_skip + p_sys->i_packet_size] == 0x47 )
2166                    {
2167                        break;
2168                    }
2169                    i_skip++;
2170                }
2171
2172                if ( pd_dmx_dbg ) printf( "skipping %d bytes of garbage\n", i_skip );
2173                stream_Read( p_sys, NULL, i_skip );
2174
2175                if( i_skip < i_peek - p_sys->i_packet_size )
2176                {
2177                    break;
2178                }
2179            }
2180
2181            if( !( p_pkt = stream_Block( p_sys, p_sys->i_packet_size ) ) )
2182            {
2183                //if ( pd_dmx_dbg ) printf( "eof ?\n" );
2184                return -1;
2185            }
2186        }
2187
2188        /* Parse the TS packet */
2189        p_pid = &p_sys->pid[PIDGet( &p_pkt->p_buffer[0] )];
2190
2191        LOCK_PD_DMX_MUTEX();
2192
2193        /*
2194         * If PID filter is set (p_pid->b_valid == TRUE),
2195         * then we shall push the packet to upper layer.
2196         */
2197        if( p_pid->b_valid )
2198        {
2199            if( p_pid->p_sec )
2200            {
2201#if 0
2202                if( p_pid->i_pid == 0 || p_pid->i_pid == 0x11 || p_pid->i_pid == 0x12 )
2203                {
2204                    dvbpsi_PushPacket( p_pid->psi->handle, p_pkt->p_buffer );
2205                }
2206                else
2207                {
2208                    int i_prg;
2209                    for( i_prg = 0; i_prg < p_pid->psi->i_prg; i_prg++ )
2210                    {
2211                        dvbpsi_PushPacket( p_pid->psi->prg[i_prg]->handle,
2212                                           p_pkt->p_buffer );
2213                    }
2214                }
2215//                block_Release( p_pkt );
2216#else
2217                DS_BOOL bFound;
2218               
2219                bFound = DS_FALSE;
2220               
2221#if 0
2222                if (p_pkt->p_buffer[1] & 0x40/*payload_unit_start_indicator*/)
2223                {
2224                    PD_SECFILTER    *p_cursec;
2225                    DS_U8 b1, b2;
2226                    int payload_offset;
2227                    int adaptation_field;
2228                    int i;
2229                   
2230                    adaptation_field = (p_pkt->p_buffer[3]>>4) & 0x03;
2231                    if ( adaptation_field == 1 /* payload only */ )
2232                        payload_offset = 4;
2233                    else if ( adaptation_field == 3 || adaptation_field == 2 )
2234                        payload_offset = 4+p_pkt->p_buffer[4];
2235                    else
2236                        printf("!!! adaption_field is invalid! %d\n", adaptation_field);
2237                   
2238                    printf("ad: %d\n", adaptation_field);
2239                   
2240                    for (p_cursec = p_pid->p_sec; p_cursec; p_cursec = p_cursec->pNext)
2241                    {
2242                        if (p_cursec->bEnable == DS_FALSE)
2243                            continue;
2244                       
2245                        for (i=0; i<p_cursec->i_filter_size; i++)
2246                        {
2247                            b1 = (p_cursec->FilterBytes[i] & p_cursec->FilterMask[i]);
2248                            b2 = (p_pkt->p_buffer[payload_offset+i+1] & p_cursec->FilterMask[i]);
2249                            if ( b1 != b2 )
2250                                break;
2251                        }
2252                       
2253                        if (i == p_cursec->i_filter_size)
2254                        {
2255                            bFound = DS_TRUE;
2256                            break;
2257                        }
2258                    }
2259                }
2260               
2261                if (bFound)
2262#endif
2263                {
2264                    /*
2265                     * Do section filter.
2266                     */
2267                    dvbpsi_PushPacket( p_pid->h_dvbpsi, p_pkt->p_buffer );
2268                    block_Release( p_pkt );
2269                }
2270#endif
2271            }
2272            else if( !p_sys->b_udp_out )
2273            {
2274                b_frame = GatherPES( p_sys, p_pid, p_pkt );
2275                /*
2276                 * Do PID filter for A/V.
2277                 */
2278               
2279                //
2280                // PES¿¡¼­ ÇØ´ç ÆÐŶÀ» ¾µ¾¥µµ ÀÖÀ¸´Ï ¸±¸®Áî ÇÏÁö ¸»ÀÚ.
2281                //
2282            }
2283            else
2284            {
2285                PCRHandle( p_sys, p_pid, p_pkt->p_buffer );
2286                block_Release( p_pkt );
2287            }
2288        }
2289        else
2290        {
2291            if( !p_pid->b_seen )
2292            {
2293                //if ( pd_dmx_dbg ) printf( "pid[%d] unknown\n", p_pid->i_pid );
2294            }
2295            /* We have to handle PCR if present */
2296            PCRHandle( p_sys, p_pid, p_pkt->p_buffer );
2297            block_Release( p_pkt );
2298        }
2299        p_pid->b_seen = DS_TRUE;
2300       
2301        UNLOCK_PD_DMX_MUTEX();
2302       
2303        if( b_frame )
2304        {
2305            break;
2306        }
2307    }
2308
2309done:
2310    return 1;
2311}
2312
2313#if 0
2314___DEBUG_APIs___()
2315#endif
2316void pset_dmx_dbg(int bDebug)
2317{
2318    pd_dmx_dbg = bDebug;
2319}
2320
2321void pdmx_info(void)
2322{
2323    if (p_DmxSys->p_infile)
2324        printf("Stream filename: %s\n", p_DmxSys->psz_infile );
2325    else
2326    {
2327        printf("Stream filename: not specified or cannot open.\n");
2328        return;
2329    }
2330
2331    printf("Stream bitrate: %ld.%ld (long-term)\n", (p_DmxSys->i_packet_rate*8)/1000000, (p_DmxSys->i_packet_rate*8)%1000000);
2332    printf("Stream bitrate: %ld.%ld (short-term)\n", (p_DmxSys->i_packet_rate_short*8)/1000000, (p_DmxSys->i_packet_rate_short*8)%1000000);
2333    printf("Read offset: %lld\n", p_DmxSys->i_nread);
2334    printf("TS packet size: %d\n", p_DmxSys->i_packet_size);
2335    printf("TS file size: %lld\n", p_DmxSys->i_filesize);
2336    if (p_DmxSys->i_packet_rate)
2337        printf("Playtime (current/total): %lld / %lld\n", 
2338                (p_DmxSys->i_nread / p_DmxSys->i_packet_rate), 
2339                (p_DmxSys->i_filesize / p_DmxSys->i_packet_rate));
2340    else
2341        printf("Playtime cannot be calculated since packet_rate is not calculated yet.\n");
2342}
2343
2344void change_file(int num, int bReadList, int bForce, int bCont)
2345{
2346    static int b_list_read = 0;
2347    static char filename[256][256];
2348    DS_BOOL b_demux_started;
2349    char *p;
2350    int i;
2351    FILE *fp;
2352   
2353    if ( b_list_read == 0 || bReadList )
2354    {
2355        fp = fopen("list.txt", "r");
2356        if ( !fp )
2357        {
2358            printf("Cannot find list file; list.txt\n");
2359            b_list_read = 0;
2360            return;
2361        }
2362       
2363        for (i=0; i<256; i++)
2364        {
2365            p=fgets( filename[i], 255, fp );
2366            if (p==NULL)
2367                break;
2368        }
2369       
2370        fclose(fp);
2371        b_list_read = i;
2372    }
2373   
2374    if ( num >= b_list_read )
2375    {
2376        printf("Maximum filelist count is %d.\n", num);
2377        return;
2378    }
2379   
2380    if ( num == -1 )
2381    {
2382        printf("Stop the demux.\n");
2383        PD_DMX_StopDemux();
2384    }
2385   
2386    printf("Change stream file to (%d) %s\n", num, filename[num]);
2387    if ( filename[num][strlen(filename[num])-1] == '\r' || filename[num][strlen(filename[num])-1] == '\n' )
2388        filename[num][strlen(filename[num])-1] = '\0';
2389    if ( filename[num][strlen(filename[num])-1] == '\r' || filename[num][strlen(filename[num])-1] == '\n' )
2390        filename[num][strlen(filename[num])-1] = '\0';
2391   
2392    b_demux_started = PD_DMX_IsDemuxStarted();
2393   
2394    if ( b_demux_started )
2395        PD_DMX_StopDemux();
2396   
2397    PD_DMX_SetDemuxFile(filename[num], bCont);
2398
2399    if ( b_demux_started )
2400        PD_DMX_StartDemux();
2401}
2402
2403void set_output_file(int num)
2404{
2405    PD_DMX_SetOutputFile("./video.vid", "./audio.ac3");
2406}
2407
2408void do_dmx_control(int num)
2409{
2410    Control( p_DmxSys, 0, NULL );
2411}
Note: See TracBrowser for help on using the repository browser.