source: svn/newcon3bcm2_21bu/dst/dmw/src/Channel/DMW_ChannelUtil.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 42.1 KB
Line 
1/*
2        DMW_ChannelUtil.c
3       
4       
5*/
6
7
8
9
10#include "DMW_Platform.h"
11
12#include "DHL_SYS.h"
13#include "DHL_AVCAP.h"
14#include "DHL_DBG.h"
15
16#include "DMW_Config.h"
17
18#include "DMW_Channel.h"
19#include "dmw_channel_priv.h"
20
21#include "DMW_ChannelUtil.h"
22#include "DMW_Status.h"
23#include "DMW_DebugUtil.h"
24
25//#include <string.h>
26//#include <string.h>
27
28
29DHL_MODULE("$dmc", 1);
30
31
32#define max(a,b) (((a) > (b)) ? (a) : (b))
33#define min(a,b) (((a) < (b)) ? (a) : (b))
34
35
36// cafrii 100705
37// »õ·Î¿î DHL API ÀÎÅÍÆäÀ̽º¿¡ µû¸¥ º¯°æ
38//
39#define NEW_DHL_API 1
40
41
42
43#if COMMENT
44______UserMsgQueue______(){}
45#endif
46
47
48
49
50#include "../System/DMW_MsgQue.h"
51
52DMW_MSGQUE g_DmcMsgQue = 
53{ 
54        NULL,   // msg pool buffer. should be NULL.
55        0, //sizeof(DmcMessage),  // sizeof each message
56        0, //MAX_DECODE_MESSAGES,   // que size
57        0,    // current number of messages
58        0,    // mutex
59        0,    // semaphore
60        NULL, // pfn name
61};
62
63char *dmc_cmd_name(DmcMessage *pmsg)
64{
65        return Dmc_MsgString(pmsg->type);
66}
67
68STATUS doDmc_InitUserMsgQue(int nSizeOfMsg, int nMaxNumMsgInQue)
69{
70        if (nSizeOfMsg == 0 ||
71                nMaxNumMsgInQue == 0) {
72                return statusInvalidArgument;
73        }
74               
75        return DMW_SYS_InitMsgQue(&g_DmcMsgQue, nSizeOfMsg, nMaxNumMsgInQue, 
76                                                (DMW_FN_MSG_NAME) dmc_cmd_name);
77}
78
79void doDmc_DeleteUserMsgQue(void)
80{
81        // todo..
82        // ¸®¼Ò½º¸¦ »èÁ¦ÇÒ ¼ö ÀÖ´Â API?
83}
84
85STATUS doDmc_AddUserMsg(DmcMessage *pmsg)
86{
87        return DMW_SYS_AddUserMsg(&g_DmcMsgQue, pmsg);
88}
89
90STATUS doDmc_GetUserMsg(DmcMessage *pmsg, UINT32 timeout)
91{
92        return DMW_SYS_GetUserMsg(&g_DmcMsgQue, pmsg, timeout);
93}
94
95BOOL doDmc_UserMsgExist()
96{
97        return DMW_SYS_UserMsgExist(&g_DmcMsgQue);
98}
99
100BOOL dmc_cmd_is_event(DmcMessage *pmsg, UINT32 param)
101{
102        if (pmsg && !Dmc_IsCommand(pmsg->type))
103                return TRUE;  // this is event..
104        return FALSE;
105}
106
107// cafrii 060831 add
108void dmc_cmd_delete_event(DmcMessage *pmsg)
109{
110        // ¾îÂ¥ÇÇ event¶ó¸é status report¸¦ ÇÏÁö ¾ÊÀ» °ÍÀ̹ǷΠ¾î¶² °ªÀ» ÁöÁ¤Çصµ ¹«°ü.
111        //
112        Dmc_DeleteDmcMessage(pmsg, statusCancelled);   
113}
114
115void doDmc_DeleteAllEventMsg()
116{
117        DMW_SYS_DeleteMsgConditionally(&g_DmcMsgQue,
118                                (DMW_FN_MSG_CHECK) dmc_cmd_is_event, 0,
119                                (DMW_FN_MSG_DELETE) dmc_cmd_delete_event);
120}
121
122
123BOOL dmc_cmd_is_matched(DmcMessage *pmsg, UINT32 param)
124{
125        if (pmsg && pmsg->type == (DmcMsgType) param)
126                return TRUE;
127        return FALSE;
128
129}
130
131void doDmc_DeleteMsg(DmcMsgType msgtype)
132{
133        DMW_SYS_DeleteMsgConditionally(&g_DmcMsgQue,
134                                (DMW_FN_MSG_CHECK) dmc_cmd_is_matched, msgtype,
135                                (DMW_FN_MSG_DELETE) dmc_cmd_delete_event);
136}
137
138BOOL doDmc_CheckMsgExist(DmcMsgType msgtype)
139{
140        return DMW_SYS_CheckSpecificMsgExist(&g_DmcMsgQue, 
141                                (DMW_FN_MSG_CHECK) dmc_cmd_is_matched, msgtype);
142}
143
144char *dmc_cmd_cid_name(DmcMessage *pmsg)
145{
146        static char buf[10];
147        sprintf(buf, "%d", pmsg->cancelId);
148        return buf;
149}
150
151void doDmc_PrintUserMsgs()
152{
153        DMW_SYS_PrintUserMsgs(&g_DmcMsgQue, (DMW_FN_MSG_NAME) dmc_cmd_cid_name);
154}
155
156
157
158
159#if COMMENT
160_____CancelQue______(){}
161#endif
162
163//---------------------------------------------------------------
164// Command cancel °ü·Ã..
165//
166#define NUM_CANCEL_ID 10000000  // cancel ID ¹øÈ£ ¸Å±èÀ» ÇÒ¶§ »ç¿ëµÇ´Â ¹üÀ§. 0 ~ NUM_CANCEL_ID-1
167        // cafrii 030701
168        // I increase this value upto 1000 times larger.
169        // There was bugs about event cancel.  this number is not the reason of error,
170        // but this fix will minimize occurence of overwrap.
171        // If events occurs at every seconds, this number correspond to 115 days.
172
173int dmc_lastCancelId = -1;
174int dmc_currentCancelId = -1; 
175        // -1 means not-initialized.
176        // normal range is 0 ~ MAX_CANCEL_ID-1
177
178#define NEXT_CANCEL_ID(c, step) (((c) + (step)) % NUM_CANCEL_ID)
179        //
180        // »ç¿ë °¡´ÉÇÑ cancel ID range ³»¿¡¼­ step °¹¼ö¸¸Å­À» skipÇÑ ÈÄÀÇ ´ÙÀ½ cancel ID¸¦
181        // °è»êÇÏ´Â ¸ÅÅ©·Î.
182
183
184DHL_OS_MSGQ_ID   dmc_cancelQ;
185
186
187int doDmc_GetLastCancelId()
188{
189        return dmc_lastCancelId;
190}
191
192void doDmc_SetLastCancelId(int id)
193{
194        dmc_lastCancelId = id;
195}
196
197int doDmc_GetNextCancelId(int c, int step)
198{
199        return NEXT_CANCEL_ID(c, step);
200}
201
202int doDmc_GetNewCancelId()
203{
204        // Cancel ID¸¦ Çϳª »õ·Ó°Ô ºÎ¿©ÇÏ´Â ÇÔ¼ö.
205        //
206        // Dmc Task·Î message¸¦ º¸³¾¶§¿¡´Â Ç×»ó cancel ID¸¦ Çϳª ºÎ¿© ¹Þ¾Æ °°ÀÌ ÇÔ²² º¸³½´Ù.
207        // Dmc Task¿¡¼­´Â ÀÌ cancel ID¸¦ ÀÌ¿ëÇÏ¿© ¼ö½ÅµÈ message°¡ ÀÌ¹Ì cancel µÈ °ÍÀÎÁö ¾Ë¼ö ÀÖ´Ù.
208        //
209        // ÀÌ ÇÔ¼ö´Â DMC task¿¡¼­ callµÉ¼öµµ ÀÖ°í ÀÓÀÇÀÇ Å½ºÅ©¿¡¼­ call µÉ¼öµµ ÀÖ´Ù.
210       
211        int cancelId;
212
213        if (1)
214        {       
215                UINT32 mask = DHL_OS_DisableInterrupts();
216                dmc_currentCancelId = NEXT_CANCEL_ID (dmc_currentCancelId, 1);
217                cancelId = dmc_currentCancelId;
218                DHL_OS_RestoreInterrupts(mask);
219        }
220       
221        return cancelId;
222}
223
224int doDmc_GetNewMultipleCancelIds(UINT32 count)
225{
226        // Cancel ID¸¦ 'count' °¹¼ö¸¸Å­ ºÎ¿©ÇÏ´Â ÇÔ¼ö.
227        // ÁغñÇÑ cancel ID´Â ÀϷùøÈ£À̸ç, ¸Ç óÀ½ cancel ID°ªÀ» ¸®ÅÏÇÑ´Ù.
228        // caller´Â ¸®ÅϵǴ cancel IDÀÇ ½ÃÀÛºÎÅÍ ÃÑ 'count' °¹¼ö¸¸Å­ÀÇ ID¸¦ »ç¿ëÇÒ ¼ö ÀÖ´Ù.
229        //
230        // caller´Â DMC¿¡ º¸³¾ message¿¡ ±â·ÏÇÏ´Â cancel ID¿Í, cancel command¿¡ º¸³»´Â cancel ID¸¦
231        // ¿¬¼ÓµÈ °ªÀ¸·Î ¾ò±â¸¦ ¿øÇÑ´Ù. À̶§ ÀÌ ÇÔ¼ö¸¦ »ç¿ëÇÑ´Ù.
232        //
233        // ÀÌ ÇÔ¼ö´Â DMC task¿¡¼­ callµÉ¼öµµ ÀÖ°í ÀÓÀÇÀÇ Å½ºÅ©¿¡¼­ call µÉ¼öµµ ÀÖ´Ù.
234       
235        // count 0 is ignored. (set to 1 forcefully)
236        //
237       
238        int cancelIdStart;
239       
240        if (count <= 1)
241                return doDmc_GetNewCancelId();
242       
243        if (1)
244        {
245                UINT32 mask = DHL_OS_DisableInterrupts();
246                cancelIdStart = NEXT_CANCEL_ID (dmc_currentCancelId, 1);
247                dmc_currentCancelId = NEXT_CANCEL_ID (cancelIdStart, count-1);
248                DHL_OS_RestoreInterrupts(mask);
249        }
250
251        return cancelIdStart;
252                // cancelIdStart ºÎÅÍ ½ÃÀÛÇØ¼­ count °¹¼ö¸¸Å­ »ç¿ëÀÌ °¡´ÉÇÏ´Ù.
253}
254
255BOOL doDmc_IsCancelledMsg(int msgId)
256{
257        int lastCancelId = dmc_lastCancelId;
258       
259        // µÎ ID°ªÀ» ºñ±³ÇÑ´Ù.
260        //
261        //  lastCancelId: °¡Àå ¸¶Áö¸·À¸·Î ÀÔ·ÂµÈ cancel ID.
262        //
263        //  msgId: ÇöÀç ¼ö½ÅµÈ ¸Þ½ÃÁöÀÇ ID
264       
265        if (abs(msgId - lastCancelId) > NUM_CANCEL_ID/2) { // ! it is wrapped state.
266                // Á¤´çÇÑ ºñ±³¸¦ À§Çؼ­ ÀÛÀº °ª¿¡ NUM_CANCEL_ID¸¦ ´õÇÑ´Ù.
267                //
268                if (msgId < lastCancelId)
269                        msgId += NUM_CANCEL_ID;
270                else
271                        lastCancelId += NUM_CANCEL_ID;
272        }
273
274        if (msgId <= lastCancelId)
275                return TRUE;  // cancelled!!
276        else return FALSE;
277}
278
279/*
280        return true if new cancel id is updated.
281*/
282BOOL doDmc_RefreshCancelQue()
283{
284        // clear cancel queue.
285        // °¡Àå ¸¶Áö¸· cancel_number¸¦ ¸®ÅÏÇÑ´Ù.
286        // ¸¸¾à cancel queue°¡ ºñ¾îÀÖÀ¸¸é cancel_numÀº ¼Õ´ëÁö ¾Ê´Â´Ù.
287
288        int rc;
289        int msg, msgLen;
290        BOOL bNewCancelRefreshed = FALSE;
291
292        rc = DHL_OS_ReceiveMessage(dmc_cancelQ, (char *)&msg, 0);
293
294        while (rc == DHL_OK) {
295                doDmc_SetLastCancelId(msg);
296                bNewCancelRefreshed = TRUE;
297               
298                //OS_Delay(1);
299                rc = DHL_OS_ReceiveMessage(dmc_cancelQ, (char *)&msg, 0);
300        }
301
302        return bNewCancelRefreshed;
303}
304
305BOOL doDmc_CheckCancel()
306{
307        int rc;
308        int msg, msgLen;
309       
310
311        // <Question> 030613
312        //
313        //  cancel Q¿¡ ¸Þ½ÃÁö°¡ ÀÖ´Ù°í ÇØ¼­ ÇöÀç ¸Þ½ÃÁö°¡ cancelµÇ¾ú´Ù°í º¼¼ö´Â ¾ø´Ù.
314        //  ÀÌ cancel msgÀÇ cid°¡ ÇöÀç ¸Þ½ÃÁöÀÇ cidº¸´Ù ³ªÁßÀÇ °ªÀÎÁö ºñ±³ÇØ ºÁ¾ß ÇÏÁö ¾ÊÀ»±î?
315        //
316        // --> message¸¦ ¹ÞÀº Á÷ÈÄ¿¡ cancel üũ¸¦ Çѹø ÇÏ°Ô µÇ¾î Àִµ¥,
317        //   À̶§ OK¶ó¸é ±× ÀÌÈÄ¿¡´Â cancel QÀÇ emptyness ¸¸ üũÇÏ´Â °ÍÀ¸·Îµµ ÃæºÐÇÏ´Ù.
318        //
319        //   ±×¸®°í cancel Q¸¦ ¿©±â¼­ empty·Î ¸¸µé ÇÊ¿ä´Â ¾ø´Ù.
320        //   ´ÙÀ½ message¸¦ ¹Þ±â Àü¿¡ ClearCancelQ¸¦ ºÒ·¯ û¼Ò¸¦ Çϱ⠶§¹®.
321        //
322        //   Áï, ¾Æ·¡ ÄÚµå´Â ÀüÇô ¹®Á¦ ¾ø´Â ÄÚµåÀÓ.
323        //
324        // cafrii 041110 add comment
325        //   ´Ü¼øÈ÷ message queue¿¡¼­ msg°¡ ÀÖ´ÂÁöÀÇ ¿©ºÎ¸¸À¸·Î cancel üũ¸¦ ¼öÇàÇϱ⠶§¹®¿¡
326        //   ÀÏ´Ü cancel msg¸¦ ¹Þ¾ÒÀ¸¸é ±× Á¤º¸¸¦ ¹«½ÃÇÏ¸é ¾ÈµÈ´Ù.
327        //   ´Ù½Ã ÀÌ ÇÔ¼ö¸¦ ¶Ç ºÎ¸£¸é ±×¶§´Â not_cancel À̶ó°í ¸®ÅÏÇÒ °ÍÀÌ´Ù. (msg que °¡ ºñ¾úÀ¸¹Ç·Î)
328        //
329
330        rc = DHL_OS_ReceiveMessage(dmc_cancelQ, (char *)&msg, 0);
331        if (rc == 0) {
332                dprint(1, "!! cancel requested. cid %d\n", msg);
333                doDmc_SetLastCancelId(msg);
334               
335                return TRUE;  // cancel message received.
336        }
337        else
338                return FALSE;  // something err or not canceled.
339               
340}
341
342
343//-----------------------------------------------------------
344//
345STATUS Dmc_SendCancelCommand(int cancelId)
346{
347        UINT32 msg;
348       
349        //msg = doDmc_GetNewCancelId();
350        msg = cancelId;
351       
352        dprint(3, "Send cancel command, cid %d\n", msg);
353       
354        if (dmc_cancelQ) {
355                return (STATUS)DHL_OS_SendMessage(dmc_cancelQ, &msg, sizeof(msg));
356        }
357       
358        return statusOutOfResource; // no cancel Q??
359}
360
361
362STATUS Dmc_InitCancelQue(int nSizeQue)
363{
364        if (dmc_cancelQ)
365                return statusOK;
366       
367        dmc_cancelQ = DHL_OS_CreateMessageQueue("DmcCancelQ", 0, 
368                                                                nSizeQue, sizeof(UINT32));
369                                                               
370        return dmc_cancelQ ? statusOK : statusOutOfResource;
371}
372
373void Dmc_DeleteCancelQue(void)
374{
375        DHL_OS_DeleteMessageQueue(dmc_cancelQ);
376        dmc_cancelQ = 0;
377}
378
379
380
381
382
383
384#if COMMENT
385_______PSI_Util________(){}
386#endif
387
388
389BOOL Dmc_CheckIfSamePat(MPEG_PAT *pat1, MPEG_PAT *pat2)
390{
391#if 0 // for reference
392        typedef struct MPEG_PAT_program {
393                UINT16          program_number;
394                UINT16          program_map_PID;
395        } MPEG_PAT_program;
396       
397        typedef struct MPEG_PAT {
398                UINT16                          transport_stream_id;
399                UINT8                           version_number;
400                BOOLEAN                         current_next_indicator;
401                UINT8                           section_number;
402                UINT8                           last_section_number;
403                BOOLEAN                         isWholePAT;                             /* FALSE if only a singe section of a PAT */
404                UINT16                          numPrograms;
405                BOOLEAN                         networkPIDPresent;              /* TRUE if network_pid is valid */
406                UINT16                          network_PID;
407                MPEG_PAT_program        *programs;
408        } MPEG_PAT;
409#endif
410        int i;
411        if (!pat1 || !pat2 ||
412                pat1->transport_stream_id != pat2->transport_stream_id ||
413                pat1->numPrograms != pat2->numPrograms)
414                return FALSE;
415       
416        // todo..
417        // ¼ø¼­¸¸ ´Þ¶óÁø °æ¿ì´Â equivalent pat·Î º¼ ¼ö Àִµ¥
418        // ±×°Í¿¡ ´ëÇÑ Ã¼Å© ÇÊ¿ä.
419       
420        for (i=0; i<pat1->numPrograms; i++)
421                if (pat1->programs[i].program_number != pat2->programs[i].program_number ||
422                        pat1->programs[i].program_map_PID != pat2->programs[i].program_map_PID)
423                        return FALSE;
424
425        return TRUE;
426}
427
428BOOL Dmc_CheckIfSamePmt(MPEG_PMT *pmt1, MPEG_PMT *pmt2)
429{
430        // µÎ PMT¸¦ ºñ±³Çؼ­ °°Àº °ÍÀÎÁö ¾Æ´ÑÁö ºñ±³ÇÑ´Ù.
431
432        // todo..
433        // ÁÖ·Î PsiEventProc¿¡¼­ ºÒ¸± °ÍÀε¥, tDHL_PSI_DataArray¸¦ Á÷Á¢ ºñ±³ÇÏ´Â °ÍÀº ¾î¶³±î?
434        //
435        // °°À¸¸é TRUE¸¦ ¸®ÅÏÇÑ´Ù.
436        // ¹öÀü ¹øÈ£ (CRCµµ?) ´Â ºñ±³ÇÏÁö ¾Ê´Â´Ù.
437
438
439        int i;
440        if (!pmt1 || !pmt2 ||
441                pmt1->PID != pmt2->PID ||
442                pmt1->program_number != pmt2->program_number ||
443                pmt1->PCR_PID != pmt2->PCR_PID ||
444                pmt1->descriptor_length != pmt2->descriptor_length ||
445                pmt1->numStreams != pmt2->numStreams)
446                return FALSE;
447       
448        if (pmt1->descriptors && pmt2->descriptors && pmt1->descriptor_length > 0) {
449                if (memcmp(pmt1->descriptors, pmt2->descriptors, pmt1->descriptor_length))
450                        return FALSE;
451        }
452       
453        for (i=0; i<pmt1->numStreams; i++) {
454                MPEG_PMT_stream *st1 = &pmt1->streams[i], *st2 = &pmt2->streams[i];
455               
456                if (st1->stream_type != st2->stream_type ||
457                        st1->elementary_PID != st2->elementary_PID ||
458                        st1->descriptor_length != st2->descriptor_length)
459                        return FALSE;
460                if (st1->descriptors && st2->descriptors && 
461                        st1->descriptor_length > 0 &&
462                        memcmp(st1->descriptors, st2->descriptors, st1->descriptor_length))
463                        return FALSE;
464        }
465        return TRUE;
466}
467
468
469
470
471// Dmc_CheckPmtDifference
472//    µÎ°³ÀÇ PMT¸¦ ºñ±³ÇÑ´Ù.
473//    µÎ PMT¸¦ ºñ±³ÇÑ °á°ú, ¼­·Î µ¿ÀÏÇÏÁö ¾ÊÀ¸¸é non-Zero¸¦ ¸®ÅÏ.
474//
475int Dmc_CheckPmtDifference(MPEG_PMT *pmt1, MPEG_PMT *pmt2)
476{
477        MPEG_PMT_stream *str1, *str2;
478        int i, errbase;
479       
480        // if invalid PMTs are passed to this function, return valus is meaningless.
481        if (pmt1 == NULL || pmt2 == NULL) return 1;
482       
483        if (pmt1->PID != pmt2->PID) return 2;
484        if (pmt1->program_number != pmt2->program_number) return 3;
485        if (pmt1->PCR_PID != pmt2->PCR_PID) return 4;
486       
487        if (pmt1->descriptor_length != pmt2->descriptor_length) return 5;
488        if (pmt1->descriptor_length &&
489                memcmp(pmt1->descriptors, pmt2->descriptors, pmt1->descriptor_length))
490                return 6;
491       
492        if (pmt1->numStreams != pmt2->numStreams) return 7;
493
494        for (i=0; i<pmt1->numStreams; i++) 
495        {
496                str1 = &(pmt1->streams[i]);
497                str2 = &(pmt2->streams[i]);
498                errbase = (i+1)*10;
499               
500                if (str1->stream_type != str2->stream_type) return errbase+1;
501                if (str1->elementary_PID != str2->elementary_PID) return errbase+2;
502                if (str1->descriptor_length != str2->descriptor_length) return errbase+3;
503                if (str1->descriptor_length &&
504                        memcmp(str1->descriptors, str2->descriptors, str1->descriptor_length))
505                        return errbase+4;
506                       
507                // videoStreamDescriptor is NULL if not present
508                if ((str1->videoStreamDescriptor && !str2->videoStreamDescriptor) ||
509                        (!str1->videoStreamDescriptor && str2->videoStreamDescriptor))  // if only one of the two is NULL
510                        return errbase+5;
511                if (str1->videoStreamDescriptor &&  // if both are non-NULL and,
512                        memcmp(str1->videoStreamDescriptor, str2->videoStreamDescriptor, 
513                        sizeof(VideoStreamDescriptor))) // if contents are different
514                        return errbase+6;
515               
516                // VideoDecodeControlDescriptor has valid flag..
517                // compare whole contents including valid flag
518                if (memcmp(&str1->videoDecodeControlDescriptor, &str2->videoDecodeControlDescriptor,
519                        sizeof(VideoDecodeControlDescriptor)))
520                        return errbase+7;
521        }
522       
523        return FALSE; // meaning that two PMTs are same..
524}
525
526
527
528
529#if COMMENT
530_______PSI_Util2_________(){}
531#endif
532
533//
534// VCT channel pointer·ÎºÎÅÍ major/minor °ªÀ» ÃßÃâÇÏ´Â ÇÔ¼ö
535//
536// major °ªÀÇ ¹üÀ§¸¦ Ã¼Å©ÇØ¼­ One Part Çü½ÄÀÏ °æ¿ì ÇØ´ç Çü½Ä¿¡ ¸Â°Ô º¯È¯ÇÑ´Ù.
537//
538UINT16 Dmc_GetMajorNumber(BOOL is_cvct, xvctChannelPtr_t ch)
539{
540        if (is_cvct && IsOnePartChannelNumber(ch->major_channel_number)) {
541                return ConvertToOnePartChannelNumber(
542                                (ch)->major_channel_number, 
543                                (ch)->minor_channel_number);
544        }       
545        return (ch)->major_channel_number;
546}
547
548UINT16 Dmc_GetMinorNumber(BOOL is_cvct, xvctChannelPtr_t ch)
549{
550        if (is_cvct && IsOnePartChannelNumber(ch->major_channel_number)) {
551                return ONE_PART_CHANNEL_INDICATOR;
552        }
553        return (ch)->minor_channel_number;
554}
555
556
557
558
559
560//===========================================================================
561//
562//    Debug
563//
564
565
566
567
568// from $6.7, Table 6.16 from ATSC A-65.A document
569//
570const char *Dmc_PsipDescriptorString(UINT8 d)
571{
572        if (d == 0x80) return "Stuffing descriptor";
573        if (d == 0x81) return "AC-3 audio descriptor";
574        if (d == 0x86) return "Caption service descriptor";
575        if (d == 0x87) return "Content advisory descriptor";
576        if (d == 0xA0) return "Extended channel name descriptor";
577        if (d == 0xA1) return "Service location descriptor";
578        if (d == 0xA2) return "Time-shifted service descriptor";
579        if (d == 0xA3) return "Component name descriptor";
580       
581        if (d >= 0xC0 && d <= 0xFE) return "User private";
582       
583        return "Unknown";
584}
585
586
587
588
589
590#if COMMENT
591____PSILoad____(){}
592#endif
593
594
595
596
597// 
598//  ÇØ´ç program number¿¡ ÇØ´çÇÏ´Â PAT/PMT¸¦ ¼ö½ÅÇÑ´Ù.
599//
600//  [IN] program_number, fnCheck
601//  [INOUT] ppat, ppmt
602//
603//  return value:
604//    statusOK
605//    statusInvalidPSI
606//    statusNoPSI
607//    statusCancelled
608//
609STATUS Dmc_GetPmtByProgramNumber(MPEG_PAT **ppat, MPEG_PMT **ppmt, 
610                        UINT16 program_number, BOOL (*fnCheck)(void))
611{
612        // TVCT, CVCT ó¸® Áß¿¡ ºÒ¸°´Ù.
613        // VCT¸¦ ¼ö½ÅÇϸ鼭 µ¿½Ã¿¡ PAT´Â ¹Þ¾ÆÁ® ÀÖ´Â °æ¿ì°¡ ´ëºÎºÐÀÌÁö¸¸,
614        // ¸ø¹ÞÀº °æ¿ì¿¡´Â ´Ù½Ã ¹Þ´Â´Ù.
615        // PMT´Â ¾È¹Þ¾ÆÁ® ÀÖ´Â°Ô º¸ÅëÀÌ´Ù. ÁöÁ¤µÈ program_number¿¡ ÇØ´çÇÏ´Â °ÍÀ» ¹Þ´Â´Ù.
616        // ¹ÞÀº tableÀº ctx ÀúÀåµÇ¾î ¸®ÅϵȴÙ.
617        //
618        STATUS status, returnStatus = statusOK;
619        int i;
620        int _second = 1000;
621
622        MPEG_PAT *pat;
623        MPEG_PMT *pmt;
624
625        if (ppat == NULL || ppmt == NULL) 
626                return statusInvalidArgument;
627
628        pat = *ppat;
629        pmt = *ppmt;
630       
631        dprint(2, "Dmc_GetPmtByProgramNumber(#%d):\n", program_number);
632       
633        if (pat && pmt) {
634                if (pmt->program_number == program_number) {
635                        dprint(2, "\talready program number %d PMT received\n");
636                        return statusOK;
637                }
638                else {
639                        dprint(2, "\tfree previous PMT.. program num %d\n", pmt->program_number);
640                        FreePMT(pmt);
641                        pmt = NULL;
642                }
643        }
644       
645        // PAT¸¦ ¼ö½ÅÇÑ´Ù.
646        //
647        if (pat == NULL) 
648        {
649                dprint(2, "\tget new pat..\n");
650                status = Dmc_GetPAT(Dmc_GetCurrentTsd(), &pat, 
651                                                g_Timeout_PatLoading*_second/1000, fnCheck);
652
653                if (status == statusCancelled) goto label_cancelled;
654       
655                else if (status) {
656                        dprint(1, "!! PAT load failed, %d\n", status);
657                        returnStatus = statusNoPSI;
658                        goto label_end_function;
659                }
660                if (fnCheck && fnCheck()) goto label_cancelled;
661
662                dprint(2, "\tpat found. TSID %d, total %d programs\n",
663                                pat->transport_stream_id,  pat->numPrograms); // MPEG_PAT
664        }
665        else {
666                dprint(2, "\tpat %x already exist. TSID %d, %d programs\n", 
667                                pat, pat->transport_stream_id,  pat->numPrograms);
668        }
669
670        if (pat->numPrograms == 0 || pat->programs == NULL) {
671                dprint(1, "!! invalid PSI.. no program in pat?\n");
672                returnStatus = statusInvalidPSI;
673                goto label_end_function;
674        }
675
676        // ¿øÇÏ´Â ÇÁ·Î±×·¥À» ã´Â´Ù.
677       
678        // find 'the program' whose program number is 'progNumber'.
679        // if not found, we report error directly.
680        //
681        for (i=0; i<pat->numPrograms; ++i) {
682                if (pat->programs[i].program_number == program_number)
683                        break;
684        }
685        if (i >= pat->numPrograms) {
686                dprint(1, "!! program number %d not found!\n", program_number);
687                returnStatus = statusChannelNotFound;
688                goto label_end_function;
689        }
690       
691        dprint(2, "\tget pmt of program number #%d\n", pat->programs[i].program_number);
692
693        status = Dmc_GetPMT(Dmc_GetCurrentTsd(), pat->programs[i].program_map_PID,
694                                        pat->programs[i].program_number, &pmt, 
695                                        g_Timeout_PmtLoading*_second/1000, fnCheck);
696
697        if (status == statusCancelled) goto label_cancelled;
698
699        else if (status) {
700                dprint(1, "!! PMT (#%d, pid %x) load failed, err %d\n", 
701                                        pat->programs[i].program_number, 
702                                        pat->programs[i].program_map_PID, status);
703                returnStatus = statusNoPSI;
704                goto label_end_function;
705        }
706        returnStatus = statusOK;
707        goto label_end_function;
708
709label_cancelled:
710        returnStatus = statusCancelled;
711       
712label_end_function:
713        *ppat = pat;
714        *ppmt = pmt;
715
716        return returnStatus;
717}
718
719
720
721
722
723
724// cafrii 060710 add
725//
726//  vctÀÇ program number¿¡ ÇØ´çÇÏ´Â ÇÁ·Î±×·¥ÀÌ PAT¿¡ ¾ø´Â °æ¿ì,
727//  vctÀÇ program numberÀÇ PMT°¡ ¼ö½ÅÀÌ ¾ÈµÇ´Â °æ¿ì,
728//  vctÀÇ program number Á¤º¸°¡ À߸øµÈ °ÍÀ¸·Î °¡Á¤ÇÏ°í º¹±¸¸¦ ¼öÇàÇÑ´Ù.
729//  µî·ÏµÈ ¸ðµç PMT¸¦ ¼ö½ÅÇØ¼­ °¡Àå ºñ½ÁÇÑ PMTÀÇ program number·Î ±³Ã¼ÇÑ´Ù.
730//
731//  [IN] xvctChannelPtr_t channel : º¹±¸ÇÒ vct channel.
732//       pat : ¹Ýµå½Ã ÀÖ¾î¾ß Çϸç, Á¦´ë·Î µÈ °ÍÀ̾î¾ß ÇÔ.
733//       cancel check fn
734//
735//  [INOUT] pmt list
736//
737STATUS Dmc_RecoverVctProgramNumber(xvctChannelPtr_t channel,
738                                        MPEG_PAT *pat,        // IN
739                                        MPEG_PMT **pmtList,  // INOUT
740                                        int *pIndex,         // OUT
741                                        BOOL (*fnCheck)(void))
742{
743        STATUS status = statusError;
744        int k;
745        int _second = 1000;
746        PidInfo pid1, pid2;
747
748        if (channel == NULL)
749                return statusInvalidArgument;
750
751        dprint(2, "Dmc_RecoverVctProgramNumber(vct #%d):\n", channel->program_number);
752
753        if (pat == NULL)
754                return statusInvalidPSI;
755       
756        // PAT ¼ö½ÅÀ» ´õÀÌ»ó ½ÃµµÇÏÁö ¾Ê´Â´Ù.
757        // ÀÌ ÇÔ¼ö°¡ ºÒ¸®´Â ´Ü°è¶ó¸é ÀÌ¹Ì ¸î ¹ø PAT ¼ö½Å¿¡ ½ÇÆÐÇÑ °æ¿ìÀÏ °ÍÀÓ.
758        //
759
760        if (pat->numPrograms == 0 || pat->programs == NULL) {
761                dprint(1, "!! invalid PSI.. no program in pat?\n");
762                status = statusInvalidPSI;
763                goto label_end_function;
764        }
765               
766        memset(&pid1, 0, sizeof(pid1));
767
768        status = Dmc_GetInfoFromVctDesc(channel->descriptors, 
769                                channel->descriptor_length, &pid1, NULL);
770
771        if (status) {
772                dprint(2, "!! vct pid info invalid. cannot recover\n");
773                return statusInvalidVCT;
774        }
775       
776        for (k=0; k<pat->numPrograms; k++)
777        {
778                if (pmtList[k] && 
779                        pat->programs[k].program_number == pmtList[k]->program_number)
780                {
781                        // already downloaded.
782                }
783                else
784                {
785                        dprint(2, "\t[%d] load pmt #%d..\n", k, pat->programs[k].program_number);
786
787                        if (pmtList[k])
788                                FreePMT(pmtList[k]);  // pnÀÌ pat°Í°ú ´Ù¸¥ °ÍÀ̹ǷΠ»èÁ¦ÈÄ ´Ù½Ã ¹ÞÀ½.
789                       
790                        status = Dmc_GetPMT(Dmc_GetCurrentTsd(), pat->programs[k].program_map_PID,
791                                                        pat->programs[k].program_number, &pmtList[k], 
792                                                        g_Timeout_PmtLoading*_second/1000, fnCheck);
793
794                        if (status == statusCancelled) goto label_cancelled;
795
796                        else if (status) {
797                                dprint(2, "\t PMT[%d] load failed, %d\n", k, status);
798                                continue;
799                        }
800                }
801               
802                // pmtÀÇ pid Á¤º¸¿Í, vctÀÇ pid Á¤º¸°¡ ÀÏÄ¡ÇÏ¸é ¼­·Î °°Àº programÀ¸·Î º¸°í
803                // vctÀÇ program number¸¦ ¼öÁ¤ÇÏÀÚ!
804
805                status = Dmc_GetPidInfoFromPMT(pmtList[k], &pid2);
806
807                if (status) {
808                        dprint(2, "\t PMT[%d] pid info err %d\n", k, status);
809                        continue;
810                }
811
812                if (pid1.pcr == pid2.pcr &&
813                        pid1.video == pid2.video &&
814                        pid1.audio == pid2.audio)
815                {
816                        dprint(2, "\tcorrect pmt found. recover vct #%d -> #%d\n", 
817                                        channel->program_number, pmtList[k]->program_number);
818                        channel->program_number = pmtList[k]->program_number;
819
820                        if (pIndex)
821                                *pIndex = k;
822                       
823                        status = statusOK;
824                        goto label_end_function;
825                }
826        }
827
828        dprint(2, "\tproper pmt not found.\n");
829       
830        status = statusNotFound;
831        goto label_end_function;
832       
833label_cancelled:
834        status = statusCancelled;
835       
836label_end_function:
837
838        return status;
839
840}
841
842
843
844
845
846
847#if COMMENT
848____PID____(){}
849#endif
850
851
852
853
854#define IS_VALID_PES_PID(p) ((p)>=0x10 && (p)<=0x1ffe)
855
856#define IS_VALID_PCR_PID(p) ((p)>=0x10 && (p)<=0x1ffe)
857
858
859
860
861STATUS Dmc_GetPidInfoFromSLD(serviceLocationDescriptorPtr_t sld, PidInfo *pPidInfo)
862{
863        int i;
864        BOOL bAudioPidFound = FALSE;  // audio pid´Â óÀ½ ¹ß°ßµÇ´Â °Í Çϳª¸¸ »ç¿ë.
865       
866        if (pPidInfo == NULL) return statusInvalidArgument;
867       
868        pPidInfo->pcr = sld->PCR_PID;
869       
870        for(i=0; i<sld->number_elements; i++)
871        {
872                if(sld->element[i].stream_type == StreamType_MPEG2Video) // MPEG-2 video
873                {
874                        // ITU-T Rec.H.262 | ISO/IEC 13818-2 Video or
875                        // ISO/IEC 11172-2 constrained parameter video stream
876                       
877                        pPidInfo->video = sld->element[i].elementary_PID;
878                       
879                        dprint(3, "    [%d] sld video pid %d (0x%x)\n", i, pPidInfo->video, pPidInfo->video);
880                }
881                else if (sld->element[i].stream_type == StreamType_AC3Audio) // ATSC A/53 audio
882                {
883                        // ATSC A/53 Audio
884                       
885                        UINT32 lanCode;
886
887                        if (bAudioPidFound == FALSE)   // ¸Ç óÀ½ ¹ß°ßµÇ´Â audio¸¸ ó¸®Çϵµ·Ï ÇÑ´Ù.
888                                pPidInfo->audio = sld->element[i].elementary_PID;
889
890                        lanCode = sld->element[i].ISO639_language_code;
891                       
892                        dprint(3, "    [%d] sld audio pid %d (0x%x), Lang code (%c%c%c) %s\n",
893                                i, sld->element[i].elementary_PID, sld->element[i].elementary_PID,
894                                (lanCode>>16) & 0xff, (lanCode>>8) & 0xff, lanCode & 0xff,
895                                bAudioPidFound ? "ignored" : "");
896
897                        bAudioPidFound = TRUE;
898                }
899                // cafrii 041203 add.. °­µ¿ ÄÉÀ̺í ä³Î¿¡¼­ MPEG-2 Audio ½ºÆ®¸²ÀÌ ³ª¿À°í ÀÖÀ½.
900                else if (sld->element[i].stream_type == StreamType_MPEG1Audio ||
901                         sld->element[i].stream_type == StreamType_MPEG2Audio)  // MPEG audio
902                {
903                        // MPEG 1 Audio, MPEG 2 Audio
904                       
905                        UINT32 lanCode;
906
907                        if (bAudioPidFound == FALSE)   // ¸Ç óÀ½ ¹ß°ßµÇ´Â audio¸¸ ó¸®Çϵµ·Ï ÇÑ´Ù.
908                                pPidInfo->audio = sld->element[i].elementary_PID;
909
910                        lanCode = sld->element[i].ISO639_language_code;
911                       
912                        dprint(3, "    [%d] sld audio pid %d (0x%x), MPEG%d audio, Lang code (%c%c%c) %s\n",
913                                i, sld->element[i].elementary_PID, sld->element[i].elementary_PID,
914                                sld->element[i].stream_type == StreamType_MPEG1Audio ? 1 : 2,
915                                (lanCode>>16) & 0xff, (lanCode>>8) & 0xff, lanCode & 0xff,
916                                bAudioPidFound ? "ignored" : "");
917
918                        bAudioPidFound = TRUE;
919                }
920                else {
921                        dprint(3, "    [%d] !! unknown stream type: 0x%x\n", i, sld->element[i].stream_type);
922                }
923        }
924       
925        return statusOK;
926}
927                       
928
929// PidInfo ´Â caller¿¡¼­ ÇÒ´çµÈ ¸Þ¸ð¸® ¿µ¿ªÀÇ Æ÷ÀÎÅÍÀ̰í,
930// pXcnd ´Â ÀÌ ÇÔ¼ö ³»ºÎ¿¡¼­ »õ·Î µ¿ÀûÀ¸·Î ÇÒ´çµÈ descriptor structure pointer ÀÌ´Ù.
931//
932// ÁÖÀÇ:
933//   ¹ß°ßµÇÁö ¾Ê´Â stream type¿¡ ´ëÇØ¼­´Â pid update¸¦ ÇÏÁö ¾Ê°í ÀÖ´Ù.
934//   µû¶ó¼­ caller¿¡¼­ ÃʱⰪÀ» ¸ÕÀú ÇÒ´çÇÑ »óÅ¿¡¼­ ºÒ·¯¾ß ÇÑ´Ù. (ex: 0)
935//
936STATUS Dmc_GetInfoFromVctDesc(UINT8 *desc, int desc_len, PidInfo *pPidInfo, 
937                                                                extendedChannelNameDescriptorPtr_t *pXcnd)
938{
939        UINT8* ptr;
940        serviceLocationDescriptorPtr_t sld = NULL;
941        //extendedChannelNameDescriptorPtr_t xcnd; // cafrii 050315 delete unused var.
942
943        STATUS rval;
944        int this_descriptor_len;
945        int offset;
946
947        dprint(2, "Dmc_GetInfoFromVctDesc:\n");
948       
949        if (desc == NULL || desc_len == 0) {
950                dprint(0, "!! GetInfoFromVctDesc: invalid desc\n");
951                return statusPSIPError;
952        }
953       
954        if (pPidInfo) pPidInfo->bValid = FALSE;
955        if (pXcnd) *pXcnd = NULL;
956
957        ptr = desc;
958        offset = 0;          // Áö±Ý±îÁö parsingµÈ µ¥ÀÌÅÍ ±æÀÌ.
959
960        while (TRUE)
961        {
962                // ptr[0] : descriptor tag.
963                // ptr[1] : descriptor length.
964
965                if (offset + 2 >= desc_len)
966                        // we need at least two bytes more to parse descriptor.
967                        break;
968
969                this_descriptor_len = ptr[1] + 2;  // include 'tag' and 'length'
970
971                // cafrii 060707, remove unproper 'unsupported desc..' message
972
973               
974                if (ptr[0] == 0xA0)  // extended channel name descriptor tag.
975                {
976                        if (pXcnd) 
977                        {
978                                rval = (STATUS)ParseExtendedChannelNameDescriptor (ptr, pXcnd);
979                               
980                                //if (rval != noError)
981                                if (IsError(rval)) // cafrii 050315 change
982                                {
983                                        dprint(0, "!! parse ExtChNameDesc error %d\n", rval);
984                                        *pXcnd = NULL;  // cafrii 050315 add
985                                }
986                                else {
987                                        dprint(2, "  found ext.ch.name desc\n");
988                               
989                                        // descriptor´Â ¿©±â¼­ free ½ÃŰÁö ¾Ê°í, caller °¡ free ½Ã۵µ·Ï ÇÑ´Ù.
990                                }
991                        }
992                }
993                else if (ptr[0] == 0xA1) // SLD descriptor tag.
994                {
995                        if (pPidInfo)
996                        {
997                                rval = (STATUS)ParseServiceLocationDescriptor(ptr, &sld);
998               
999                                //if (rval != noError)
1000                                if (IsError(rval)) // cafrii 050315 change
1001                                {
1002                                        dprint(0, "!! parse sld error %d\n", rval);
1003                                        sld = NULL; // cafrii 050315 add
1004                                }
1005                                else {
1006                                        dprint(2, "  found sld, pcr pid %d, %d streams\n", sld->PCR_PID, sld->number_elements);
1007                                       
1008                                        Dmc_GetPidInfoFromSLD(sld, pPidInfo);
1009                       
1010                                        if (sld)
1011                                                FreeMpegDescriptor(sld); // cafrii 030716
1012                                        sld = NULL;
1013                                       
1014                                        pPidInfo->bValid = TRUE;
1015                                }
1016                        }
1017                }
1018                else 
1019                {
1020                        // cafrii 030716, print more detail information..
1021                        //
1022                        dprint(3, "  unsupported descriptor, '%s' 0x%02x, len %d, skip!\n", 
1023                                        Dmc_PsipDescriptorString(ptr[0]), ptr[0], this_descriptor_len);
1024
1025                        if (dprintable(3))
1026                                memdump(ptr, min(this_descriptor_len, desc_len - offset), 0); 
1027                }
1028
1029                // goto next descriptor.
1030                ptr += this_descriptor_len;
1031                offset += this_descriptor_len;
1032
1033        } // while
1034
1035        return statusOK;
1036}
1037
1038
1039
1040// cafrii 060710 add
1041// driverÀÇ ÇÔ¼ö¿¡ ÀÇÁ¸ÇÏÁö ¾Ê°í MW¿¡¼­ º°µµ·Î Á¦°øÇÑ´Ù.
1042// GetElementaryPIDs ´ë½Å »ç¿ë.
1043//
1044STATUS Dmc_GetPidInfoFromPMT(MPEG_PMT *pmt, PidInfo *pPidInfo)
1045{
1046        int i;
1047       
1048        if (pmt == NULL || pPidInfo == NULL)
1049                return statusInvalidArgument;
1050
1051        memset(pPidInfo, 0, sizeof(PidInfo));
1052
1053        pPidInfo->pcr = IS_VALID_PCR_PID(pmt->PCR_PID) ? pmt->PCR_PID : 0;
1054       
1055        for (i=0; i<pmt->numStreams; i++) 
1056        {
1057                if (pmt->streams[i].stream_type == StreamType_MPEG2Video &&
1058                        pPidInfo->video == 0) 
1059                {
1060                        if (!IS_VALID_PES_PID(pmt->streams[i].elementary_PID)) {
1061                                dprint(0, "!! pmt video pes pid %x invalid\n", pmt->streams[i].elementary_PID);
1062                                continue;
1063                        }
1064                       
1065                        pPidInfo->video = pmt->streams[i].elementary_PID;
1066                }
1067                // todo
1068                // StreamType_MPEG1Video Áö¿øÀº flag¿¡ µû¶ó¼­..
1069
1070                if (pmt->streams[i].stream_type == StreamType_AC3Audio &&
1071                        pPidInfo->audio == 0) 
1072                {
1073                        if (!IS_VALID_PES_PID(pmt->streams[i].elementary_PID)) {
1074                                dprint(0, "!! pmt audio pes pid %x invalid\n", pmt->streams[i].elementary_PID);
1075                                continue;
1076                        }
1077
1078                        pPidInfo->audio = pmt->streams[i].elementary_PID;
1079                }
1080                // todo
1081                // StreamType_MPEG1Audio, StreamType_MPEG2Audio,
1082                // StreamType_AACAudio Áö¿øÀº flag¿¡ µû¶ó¼­..
1083
1084        }
1085
1086        pPidInfo->bValid = TRUE;
1087
1088        return statusOK;
1089       
1090}
1091
1092
1093
1094
1095STATUS Dmc_DecidePidInfo3(MPEG_PMT *pmt, xvctChannelPtr_t channel,
1096                                                PidInfo *pPidInfo, UINT32 flag)
1097{
1098        if (channel == NULL)
1099                return Dmc_DecidePidInfo(pmt, NULL, pPidInfo, flag);
1100
1101        else
1102                return Dmc_DecidePidInfo2(pmt, channel->descriptors,
1103                                channel->descriptor_length, pPidInfo, flag);
1104}
1105
1106STATUS Dmc_DecidePidInfo2(MPEG_PMT *pmt, UINT8 *descs, int descs_len,
1107                                                PidInfo *pPidInfo, UINT32 flag)
1108{
1109        DHL_RESULT err = DHL_OK;
1110        STATUS status; 
1111        serviceLocationDescriptorPtr_t sld = NULL;
1112
1113        if (descs && descs_len > 0)
1114        {
1115                UINT8 *sld_desc;
1116               
1117                err = GetMpegDescriptor(descs, descs_len, service_location_tag, 0, &sld_desc);
1118                        // 0xA1, SLD descriptor tag.
1119               
1120                if (!err)
1121                        err = ParseServiceLocationDescriptor(sld_desc, &sld);
1122        }
1123       
1124        status = Dmc_DecidePidInfo(pmt, err ? NULL : sld, pPidInfo, flag);
1125
1126        if (sld)
1127                FreeMpegDescriptor(sld);
1128
1129        return status;
1130
1131}
1132
1133
1134
1135
1136// cafrii 061114 add support multiple audio format
1137//
1138#define StreamTypeToAudioType(t) ( \
1139        (t) == StreamType_AC3Audio   ? eDHL_AUDIO_TYPE_AC3 : \
1140        (t) == StreamType_MPEG2Audio ? eDHL_AUDIO_TYPE_MPEG_2 : \
1141        (t) == StreamType_AACAudioADTS ? eDHL_AUDIO_TYPE_AAC_ADTS : \
1142        (t) == StreamType_AACAudioLATM ? eDHL_AUDIO_TYPE_AAC_LATM : \
1143                eDHL_AUDIO_TYPE_UNKNOWN )
1144
1145#define StreamTypeToVideoType(t) ( \
1146        (t) == StreamType_MPEG2Video ? eDHL_VIDEO_TYPE_MPEG2 : \
1147        (t) == StreamType_DC2Video   ? eDHL_VIDEO_TYPE_MPEG2 : \
1148        (t) == StreamType_MPEG1Video ? eDHL_VIDEO_TYPE_MPEG1 : \
1149        (t) == StreamType_H264       ? eDHL_VIDEO_TYPE_H264 : \
1150                eDHL_VIDEO_TYPE_UNKNOWN )
1151               
1152//
1153//  PSIP (VCT SLD)¿Í PMT Á¤º¸¸¦ ÀÌ¿ëÇÏ¿© PID¸¦ °áÁ¤ÇÑ´Ù.
1154//
1155//  [IN] pmt, sld, flag
1156//  [OUT] pPidInfo
1157//
1158//  °æ¿ì¿¡ µû¶ó¼­ vctChannelPtr_t, ¶Ç´Â sld ÇüÅ·Π¹Þ´Â°Ô ³ªÀ» ¼öµµ ÀÖÀ½.
1159//
1160STATUS Dmc_DecidePidInfo(MPEG_PMT *pmt, serviceLocationDescriptorPtr_t sld, 
1161                                                PidInfo *pPidInfo, UINT32 flag)
1162{
1163        #define MAX_PID_LIST 20
1164
1165        char buf[100];
1166       
1167        UINT16 list_p[MAX_PID_LIST]; // candidate pid list from PMT
1168        UINT16 list_v[MAX_PID_LIST]; // candidate pid list from VCT
1169
1170        int n_list_p, n_list_v;  // number of candidate for each list
1171       
1172        int i, ip, iv;
1173
1174        PidInfo pi;
1175
1176        BOOL bVerbose = (flag & DMC_DPIF_SILENT) ? 0 : 1;
1177
1178        tDHL_VideoCodingType vidType;
1179        tDHL_AudioCodingType audType;
1180       
1181        UINT32 vidCap, audCap;
1182
1183        DHL_AV_Query(eDHL_AV_QUERY_VIDEO_CAP, &vidCap);
1184        DHL_AV_Query(eDHL_AV_QUERY_AUDIO_CAP, &audCap);
1185
1186        if (bVerbose)
1187        //dprint(1, "%s: \n", __FUNCTION__);
1188
1189        memset(&pi, 0, sizeof(pi)); // cafrii 060728 add
1190
1191        // -------- VIDEO ------------
1192       
1193        // Video pid from PMT
1194
1195        memset(list_p, 0, sizeof(list_p));
1196        n_list_p = 0;
1197       
1198        for (i=0; pmt && i<pmt->numStreams; i++) 
1199        {
1200                vidType = StreamTypeToVideoType(pmt->streams[i].stream_type);
1201                if (vidType == eDHL_VIDEO_TYPE_UNKNOWN) continue;
1202
1203                if ((vidCap & (1<<vidType)) == 0) {
1204                        //dprint(0, "!! not supported video stream type %d in pmt\n", vidType);
1205                        continue;
1206                }
1207                if (!IS_VALID_PES_PID(pmt->streams[i].elementary_PID)) {
1208                        //dprint(0, "!! pmt video pes pid %x invalid\n", pmt->streams[i].elementary_PID);
1209                        continue;
1210                }
1211                if (n_list_p >= MAX_PID_LIST) {
1212                        //dprint(0, "!! pmt video pid too many\n");
1213                        break;
1214                }
1215                list_p[n_list_p++] = pmt->streams[i].elementary_PID;
1216        }
1217
1218        // Video pid from VCT
1219
1220        memset(list_v, 0, sizeof(list_v));
1221        n_list_v = 0;
1222       
1223        for (i=0; sld && i<sld->number_elements; i++)
1224        {
1225                vidType = StreamTypeToVideoType(sld->element[i].stream_type);
1226                if (vidType == eDHL_VIDEO_TYPE_UNKNOWN) continue;
1227
1228                if ((vidCap & (1<<vidType)) == 0) {
1229                        //dprint(0, "!! not supported video stream type %d in vct\n", vidType);
1230                        continue;
1231                }
1232                if (!IS_VALID_PES_PID(sld->element[i].elementary_PID)) {
1233                        //dprint(0, "!! vct video pes pid %x invalid\n", sld->element[i].elementary_PID);
1234                        continue;
1235                }
1236                if (n_list_v >= MAX_PID_LIST) {
1237                        //dprint(0, "!! vct video pid too many\n");
1238                        break;
1239                }
1240                list_v[n_list_v++] = sld->element[i].elementary_PID;
1241        }
1242
1243        // decide video pid using list of pmt and vct
1244       
1245        if ((list_v[0] != list_p[0] || dprintable(3)) && bVerbose)
1246        {
1247                if (list_v[0] != list_p[0] && n_list_p*n_list_v)
1248                        // ÀÏÄ¡ÇÏÁö ¾Ê´Â °æ¿ì.
1249                        // ¸¸¾à pmt³ª vct Áß Çϳª¸¸ ÁöÁ¤ÇÑ °æ¿ì¿£ °æ°í ¸Þ½ÃÁö Ãâ·ÂÇÏÁö ¸»ÀÚ.
1250                        dprint(0, "!! Warning: pmt/vct video pid mismatch\n");
1251
1252                buf[0] = 0;
1253                //sprintf(buf, "vpid pmt(%d):", n_list_p);
1254                //for (i=0; i<min(n_list_p, 5); i++)
1255                //      sprintf(buf + strlen(buf), " %x", list_p[i]);
1256                //sprintf(buf + strlen(buf), ", vct(%d):", n_list_v);
1257                //for (i=0; i<min(n_list_v, 5); i++)
1258                //      sprintf(buf + strlen(buf), " %x", list_v[i]);
1259
1260                //dprint(0, "  %s\n", buf);
1261        }
1262
1263        pi.video = 0;
1264        for (ip=0; ip<n_list_p; ip++)
1265        {
1266                // vct list¿¡¼­ ÀÏÄ¡ÇÏ´Â °Í °Ë»ö
1267                for (iv=0; iv<n_list_v; iv++) {
1268                        if (list_p[ip] == list_v[iv]) {
1269                                pi.video = list_p[ip];
1270                                break;
1271                        }
1272                }
1273                if (pi.video) break;
1274        }
1275
1276        if (pi.video == 0) {  // if not yet decided, choose any valid one
1277                if (n_list_p > 0)
1278                        // choose from list_pmt
1279                        pi.video = list_p[0];  // it also may be zero
1280                else if (n_list_v > 0)
1281                        // choose from list_vct
1282                        pi.video = list_v[0];  // it also may be zero
1283        }
1284
1285        // video pid·ÎºÎÅÍ video type ÃßÃâ.
1286        if (pi.video) {
1287                pi.videoType = eDHL_VIDEO_TYPE_UNKNOWN;
1288                for (i=0; pmt && i<pmt->numStreams && pi.videoType==eDHL_VIDEO_TYPE_UNKNOWN; i++) {
1289                        if (pmt->streams[i].elementary_PID == pi.video)
1290                                pi.videoType = StreamTypeToVideoType(pmt->streams[i].stream_type);
1291                }
1292                for (i=0; sld && i<sld->number_elements && pi.videoType==eDHL_VIDEO_TYPE_UNKNOWN; i++) {
1293                        if (sld->element[i].elementary_PID == pi.video)
1294                                pi.videoType = StreamTypeToVideoType(sld->element[i].stream_type);
1295                }
1296                DHL_ASSERT(pi.videoType != eDHL_VIDEO_TYPE_UNKNOWN, "");
1297        }
1298        // -------- AUDIO ------------
1299
1300        // Audio pid from PMT
1301
1302        memset(list_p, 0, sizeof(list_p));
1303        n_list_p = 0;
1304       
1305        for (i=0; pmt && i<pmt->numStreams; i++) 
1306        {
1307                audType = StreamTypeToAudioType(pmt->streams[i].stream_type);
1308                if (audType == eDHL_AUDIO_TYPE_UNKNOWN) continue;
1309
1310                if ((audCap & (1<<audType)) == 0) {
1311                        dprint(0, "!! not supported audio stream type %d in pmt\n", audType);
1312                        continue;
1313                }
1314                if (!IS_VALID_PES_PID(pmt->streams[i].elementary_PID)) {
1315                        dprint(0, "!! pmt audio pes pid %x invalid\n", pmt->streams[i].elementary_PID);
1316                        continue;
1317                }
1318                if (n_list_p >= MAX_PID_LIST) {
1319                        dprint(0, "!! pmt audio pid too many\n");
1320                        break;
1321                }
1322                list_p[n_list_p++] = pmt->streams[i].elementary_PID;
1323        }
1324
1325        // Audio pid from VCT
1326
1327        memset(list_v, 0, sizeof(list_v));
1328        n_list_v = 0;
1329       
1330        for (i=0; sld && i<sld->number_elements; i++)
1331        {
1332                audType = StreamTypeToAudioType(sld->element[i].stream_type);
1333                if (audType == eDHL_AUDIO_TYPE_UNKNOWN) continue;
1334
1335                if ((audCap & (1<<audType)) == 0) {
1336                        dprint(0, "!! not supported audio stream type %d in vct\n", audType);
1337                        continue;
1338                }
1339                if (!IS_VALID_PES_PID(sld->element[i].elementary_PID)) {
1340                        dprint(0, "!! vct video pes pid %x invalid\n", sld->element[i].elementary_PID);
1341                        continue;
1342                }
1343                if (n_list_v >= MAX_PID_LIST) {
1344                        dprint(0, "!! vct video pid too many\n");
1345                        break;
1346                }
1347                list_v[n_list_v++] = sld->element[i].elementary_PID;
1348        }
1349
1350        // decide Audio pid
1351
1352        if ((list_v[0] != list_p[0] || dprintable(3)) && bVerbose)
1353        {
1354                if (list_v[0] != list_p[0] && pmt && sld)
1355                        // ÀÏÄ¡ÇÏÁö ¾Ê´Â °æ¿ì.
1356                        // ¸¸¾à pmt³ª vct Áß Çϳª¸¸ ÁöÁ¤ÇÑ °æ¿ì¿£ °æ°í ¸Þ½ÃÁö Ãâ·ÂÇÏÁö ¸»ÀÚ.
1357                        dprint(0, "!! Warning: pmt/vct audio pid mismatch\n");
1358                       
1359                buf[0] = 0;
1360                //sprintf(buf, "apid pmt(%d):", n_list_p);
1361                //for (i=0; i<min(n_list_p, 5); i++)
1362                //      sprintf(buf + strlen(buf), " %x", list_p[i]);
1363                //sprintf(buf + strlen(buf), ", vct(%d):", n_list_v);
1364                //for (i=0; i<min(n_list_v, 5); i++)
1365                //      sprintf(buf + strlen(buf), " %x", list_v[i]);
1366
1367                //dprint(0, "  %s\n", buf);
1368        }
1369
1370        pi.audio = 0;
1371        for (ip=0; ip<n_list_p; ip++)
1372        {
1373                // vct list¿¡¼­ ÀÏÄ¡ÇÏ´Â °Í °Ë»ö
1374                for (iv=0; iv<n_list_v; iv++) {
1375                        if (list_p[ip] == list_v[iv]) {
1376                                pi.audio = list_p[ip];
1377                                break;
1378                        }
1379                }
1380                if (pi.audio) break;
1381        }
1382
1383        if (pi.audio == 0) {
1384                if (n_list_p > 0)
1385                        // choose from list_pmt
1386                        pi.audio = list_p[0];  // it also may be zero
1387                if (n_list_v > 0)
1388                        // choose from list_vct
1389                        pi.audio = list_v[0];  // it also may be zero
1390        }
1391
1392        // audio pid·ÎºÎÅÍ audio type ÃßÃâ.
1393        if (pi.audio) {
1394                pi.audioType = eDHL_AUDIO_TYPE_UNKNOWN;
1395                for (i=0; pmt && i<pmt->numStreams && pi.audioType==eDHL_AUDIO_TYPE_UNKNOWN; i++) {
1396                        if (pmt->streams[i].elementary_PID == pi.audio)
1397                                pi.audioType = StreamTypeToAudioType(pmt->streams[i].stream_type);
1398                }
1399                for (i=0; sld && i<sld->number_elements && pi.audioType==eDHL_AUDIO_TYPE_UNKNOWN; i++) {
1400                        if (sld->element[i].elementary_PID == pi.audio)
1401                                pi.audioType = StreamTypeToAudioType(sld->element[i].stream_type);
1402                }
1403                DHL_ASSERT(pi.audioType != eDHL_AUDIO_TYPE_UNKNOWN, "");
1404        }
1405
1406        // -------- check ------------
1407       
1408        if (pi.video == 0 && pi.audio == 0){
1409                dprint(0, "!! Warning: no valid pid\n");
1410                return statusNotFound;
1411        }
1412
1413        // -------- PCR ------------
1414
1415        pi.pcr = 0;
1416
1417        if (1)
1418        {
1419                int pmt_pcr, sld_pcr;
1420
1421                pmt_pcr = pmt ? pmt->PCR_PID : 0;
1422                sld_pcr = sld ? sld->PCR_PID : 0;
1423               
1424                if (pmt_pcr == sld_pcr && 
1425                        IS_VALID_PCR_PID(pmt_pcr))
1426                        pi.pcr = pmt_pcr;
1427
1428                else
1429                {
1430                        if (bVerbose && pmt && sld)
1431                                // ¸¸¾à pmt³ª vct Áß Çϳª¸¸ ÁöÁ¤ÇÑ °æ¿ì¿£ °æ°í ¸Þ½ÃÁö Ãâ·ÂÇÏÁö ¸»ÀÚ.
1432                                dprint(0, "!! Warning: pcr invalid, pmt %x, vct %x\n", 
1433                                        pmt_pcr, sld_pcr);
1434
1435                        if (IS_VALID_PCR_PID(pmt_pcr))
1436                                pi.pcr = pmt_pcr;
1437
1438                        else if (IS_VALID_PCR_PID(sld_pcr))
1439                                pi.pcr = sld_pcr;
1440
1441                        else 
1442                        {
1443                                if (IS_VALID_PCR_PID(pi.video))
1444                                        pi.pcr = pi.video;
1445                                else if (IS_VALID_PCR_PID(pi.audio))
1446                                        pi.pcr = pi.audio;
1447                        }       
1448                }
1449        }
1450       
1451        pi.bValid = TRUE;
1452       
1453        if (pPidInfo)
1454                *pPidInfo = pi;
1455
1456        return statusOK;
1457       
1458}
1459
1460
1461
1462
1463
1464#if COMMENT
1465_______Timing_Util________(){}
1466#endif
1467
1468// Dmc_CheckIfFormatChanged
1469//    µÎ sequence header¸¦ ºñ±³ ºÐ¼®ÇÏ¿© »õ·Î¿î seq header¿¡¼­ display timingÀÌ
1470//    ¹Ù²î¾ú´ÂÁö üũÇÑ´Ù.
1471//
1472//    º¯°æµÇ¾úÀ¸¸é TRUE¸¦ ¸®ÅÏÇÑ´Ù.
1473//
1474//    ºÒ¸®´Â °÷: StartDigital (°¡Àå ¸¶Áö¸·ÀÇ seqHdr¿Í ºñ±³)
1475//              HandleImportantChange (video source°¡ Running changeµÈ °æ¿ìÀÓ)
1476//
1477BOOL Dmc_CheckIfFormatChanged(tDHL_VideoSeqHdr *newsh, tDHL_VideoSeqHdr *oldsh)
1478{
1479       
1480#if 0 // reference only. member of tDHL_VideoSeqHdr
1481        UINT32  generationNumber;                                       /* Increments each time it changes */
1482        UINT16  horizontal_size;                                    /* incorporates horizontal_size_value and extension */
1483        UINT16  vertical_size;                                  /* incorporates vettical_size_value and extension */
1484        MPEG_ASPECT_RATIO aspect_ratio_information;
1485        MPEG_FRAME_RATE frame_rate_code;
1486        FLOAT  frame_rate;                          /* incorporates frame_rate_code, extension_n,_d */
1487        UINT32  bit_rate;                                                   /* bit_rate_extension is added */
1488        UINT32  vbv_buffer_size;                                    /* Specified in bytes. (vbv_buffer_size_extension,value * 16/8 * 1024 */
1489        BOOLEAN         constrained_parameter_flag;
1490        BOOLEAN    MPEG2;                              /* True if sequece_extension is present */
1491        UINT8   profile_and_level_indication;
1492        BOOLEAN         progressive_sequence;
1493        MPEG_CHROMA_FORMAT chroma_format;
1494        BOOLEAN         low_delay;
1495#endif
1496
1497        if (newsh == NULL)
1498                return FALSE;  // do not change. current seq hdr is invalid.
1499               
1500        if (oldsh == NULL)
1501                return TRUE;   // newly generated. so changed!!
1502
1503        // cafrii
1504        // ¼öÁ÷ ÇØ»óµµ 1080°ú 1088Àº °°Àº ÇØ»óµµ·Î °£ÁÖÇϵµ·Ï º¯°æ.
1505        //
1506        if (newsh->horizontal_size != oldsh->horizontal_size)
1507                return TRUE;
1508               
1509        // now we treat vertical line 1080 and 1088 as same format.
1510        if (newsh->vertical_size == 1080 || newsh->vertical_size == 1088) {
1511                if (oldsh->vertical_size != 1080 && oldsh->vertical_size != 1088)
1512                        return TRUE;
1513        }
1514        else if (newsh->vertical_size != oldsh->vertical_size)
1515                return TRUE;
1516
1517        if (newsh->aspect_ratio_information != oldsh->aspect_ratio_information ||
1518                newsh->frame_rate_code != oldsh->frame_rate_code ||
1519                newsh->progressive_sequence != oldsh->progressive_sequence)
1520                return TRUE;
1521       
1522        return FALSE; // no change in resolution/timing.
1523}
1524
1525
1526
1527// Dmc_WhichATSCFormat
1528//    Sarnoff Stream ATSC_01 ~ ATSC_36 Áß¿¡¼­ ¾î¶² °Í¿¡ ÇØ´çµÇ´ÂÁö ¸®ÅÏ.
1529//    Á¤È®È÷ °°Àº°Ô ¾øÀ¸¸é 0À» ¸®ÅÏÇÑ´Ù.
1530//   
1531int Dmc_WhichATSCFormat(tDHL_VideoSeqHdr *seq)
1532{
1533        if (seq->horizontal_size == 1920 && (seq->vertical_size == 1080 || seq->vertical_size == 1088)) {
1534                if (seq->progressive_sequence) {
1535                                return 
1536                                        seq->frame_rate_code == FRAMERATE_23_976 ?  1 :
1537                                        seq->frame_rate_code == FRAMERATE_24     ?  2 :
1538                                        seq->frame_rate_code == FRAMERATE_29_97  ?  3 :
1539                                        seq->frame_rate_code == FRAMERATE_30     ?  4 : 0;
1540                }
1541                else {
1542                                return
1543                                        seq->frame_rate_code == FRAMERATE_29_97  ?  5 :
1544                                        seq->frame_rate_code == FRAMERATE_30     ?  6 : 0;
1545                }
1546        }
1547        else if (seq->horizontal_size == 1280 && seq->vertical_size == 720) {
1548                                return
1549                                        seq->frame_rate_code == FRAMERATE_23_976 ?  7 :
1550                                        seq->frame_rate_code == FRAMERATE_24     ?  8 :
1551                                        seq->frame_rate_code == FRAMERATE_29_97  ?  9 :
1552                                        seq->frame_rate_code == FRAMERATE_30     ? 10 :
1553                                        seq->frame_rate_code == FRAMERATE_59_94  ? 11 :
1554                                        seq->frame_rate_code == FRAMERATE_60     ? 12 : 0;
1555        }
1556        else if (seq->horizontal_size == 704 && seq->vertical_size == 480) {
1557                if (DHL_AV_IsWideoFormat(seq)) { // 16:9
1558                        if (seq->progressive_sequence) {
1559                                return
1560                                        seq->frame_rate_code == FRAMERATE_23_976 ? 13 :
1561                                        seq->frame_rate_code == FRAMERATE_24     ? 14 :
1562                                        seq->frame_rate_code == FRAMERATE_29_97  ? 15 :
1563                                        seq->frame_rate_code == FRAMERATE_30     ? 16 :
1564                                        seq->frame_rate_code == FRAMERATE_59_94  ? 17 :
1565                                        seq->frame_rate_code == FRAMERATE_60     ? 18 : 0;
1566                        }
1567                        else {
1568                                return
1569                                        seq->frame_rate_code == FRAMERATE_29_97  ? 19 :
1570                                        seq->frame_rate_code == FRAMERATE_30     ? 20 : 0;
1571                        }
1572                }
1573                else { // 4:3
1574                        if (seq->progressive_sequence) {
1575                                return
1576                                        seq->frame_rate_code == FRAMERATE_23_976 ? 21 :
1577                                        seq->frame_rate_code == FRAMERATE_24     ? 22 :
1578                                        seq->frame_rate_code == FRAMERATE_29_97  ? 23 :
1579                                        seq->frame_rate_code == FRAMERATE_30     ? 24 :
1580                                        seq->frame_rate_code == FRAMERATE_59_94  ? 25 :
1581                                        seq->frame_rate_code == FRAMERATE_60     ? 26 : 0;
1582                        }
1583                        else {
1584                                return
1585                                        seq->frame_rate_code == FRAMERATE_29_97  ? 27 :
1586                                        seq->frame_rate_code == FRAMERATE_30     ? 28 : 0;
1587                        }
1588                }
1589        }
1590        else if (seq->horizontal_size == 640 && seq->vertical_size == 480) {
1591                        if (seq->progressive_sequence) {
1592                                return
1593                                        seq->frame_rate_code == FRAMERATE_23_976 ? 29 :
1594                                        seq->frame_rate_code == FRAMERATE_24     ? 30 :
1595                                        seq->frame_rate_code == FRAMERATE_29_97  ? 31 :
1596                                        seq->frame_rate_code == FRAMERATE_30     ? 32 :
1597                                        seq->frame_rate_code == FRAMERATE_59_94  ? 33 :
1598                                        seq->frame_rate_code == FRAMERATE_60     ? 34 : 0;
1599                        }
1600                        else {
1601                                return
1602                                        seq->frame_rate_code == FRAMERATE_29_97  ? 35 :
1603                                        seq->frame_rate_code == FRAMERATE_30     ? 36 : 0;
1604                        }
1605        }
1606        return 0;
1607}
1608
1609
1610
1611
1612
1613#if COMMENT
1614________(){}
1615#endif
1616
1617#if DMW_REGISTER_DEBUG_SYMBOL
1618
1619
1620static DHL_SymbolTable symbols[] =
1621{
1622};
1623
1624#endif
1625
1626void RegisterChannelUtilSymbols(void)
1627{
1628       
1629#if DMW_REGISTER_DEBUG_SYMBOL
1630        DHL_DBG_RegisterSymbols(symbols, DHL_NUMSYMBOLS(symbols));
1631#endif
1632
1633}
1634
Note: See TracBrowser for help on using the repository browser.