source: svn/trunk/zasc/app/DST_ISDBT_ChannelTask.cpp @ 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: 70.4 KB
Line 
1#include "DST_ISDBT_ChannelTask.h"
2#include "DST_CommonAPI.h"
3#include "DST_HostInterface.h"
4#include "DST_WinManagerTask.h"
5#include "sqlite3.h"
6#include "dst_eroum_interface.h"
7#include "DST_DB_Engine.h"
8#include "DST_DB.h"
9#include "DST_Parser.h"
10#include "DST_MultipleStringStructure.h"
11//#include "DST_OTC_Main.h"
12
13DS_U16 DST_GetMHzFrequencybyIndex(int index);
14int DST_GetAppShortVersionNumber();
15
16void DST_SignalInfoCallBack(int nWidth, int nHeight, int RefreshRate, bool bInterlaced, DHL_SOURCE_ASEPCT Aspect);
17void DST_VideoFreezeEndProc();
18void DST_SBTVDCC_Reset();
19DS_U8* JST_Arib2Utf8(DS_U8* strArib, int nLen);
20
21#define MAX_EIT_COUNT 4
22#define MAX_PMT_COUNT 16
23
24#define POS_TVCT 0
25#define POS_CVCT (POS_TVCT+1)
26#define POS_STT (POS_CVCT+1)
27#define POS_MGT (POS_STT+1)
28#define POS_EIT (POS_MGT+1)
29#define POS_ETT (POS_EIT+MAX_EIT_COUNT)
30#define POS_PAT (POS_ETT+MAX_EIT_COUNT)
31#define POS_PMT (POS_PAT+1)
32#define POS_RFUPDATE (POS_PMT+MAX_PMT_COUNT)
33#define POS_CVT (POS_RFUPDATE+1)
34#define POS_OTC_DII (POS_CVT+1)
35#define POS_OTC_DDB (POS_OTC_DII+1)
36
37#if 0
38____FREQUENCY___()
39#endif
40
41DS_U8* JST_Uni2Utf8(DS_U16* strUni, int nLen)
42{
43        if (nLen == 0) return 0;
44        if (strUni == 0) return 0;
45        DS_U16 strTmp16[4097];
46        memset(strTmp16, 0,  sizeof(strTmp16));
47        if (nLen > 4096) nLen = 4096;
48        memcpy(strTmp16, strUni, nLen * sizeof(DS_U16));
49        nLen = strlen16(strTmp16);
50        if (nLen == 0) return 0;
51        DS_U8* buff = (DS_U8*)DST_OS_Calloc(nLen*4+1,1);
52        int nPos = 0;
53        for (int i = 0; i < nLen; i++)
54        {
55                DS_U32 uni = strUni[i];
56                if (uni <= 0x7F)
57                { // 0xxxxxxx
58                        buff[nPos] = uni;
59                        nPos++;
60                        continue;
61                }
62                if (uni <= 0x7FF)
63                { // 110xxxxx 10xxxxxx
64                        buff[nPos] = 0xC0 | (uni >> 6);
65                        nPos++;
66                        buff[nPos] = 0x80 | (uni & 0x3F);
67                        nPos++;
68                        continue;                       
69                }
70                if (uni <= 0xFFFF)
71                { // 1110xxxxx 10xxxxxx 10xxxxxx
72                        buff[nPos] = 0xE0 | (uni >> 12);
73                        nPos++;
74                        buff[nPos] = 0x80 | ((uni >> 6) & 0x3F);
75                        nPos++;
76                        buff[nPos] = 0x80 | (uni & 0x3F);
77                        nPos++;
78                        continue;                       
79                }
80                // 11110zzz 10zzxxxx 10xxxxxx 10xxxxxx
81                uni = uni & 0x1FFFFF;
82                buff[nPos] = 0xF0 | (uni >> 18);
83                nPos++;
84                buff[nPos] = 0x80 | ((uni >> 12) & 0x3F);
85                nPos++;
86                buff[nPos] = 0x80 | ((uni >> 6) & 0x3F);
87                nPos++;
88                buff[nPos] = 0x80 | (uni & 0x3F);
89                nPos++;
90        }
91        return buff;
92}
93
94class mss2utf8
95{
96private:
97        char *strUTF8;
98public:
99        mss2utf8()
100        {
101                strUTF8 = 0;
102        }
103        mss2utf8(DS_U8 nLen, DS_U8 *text)
104        {
105                strUTF8 = 0;
106                set(nLen, text);
107        }
108        void set(DS_U8 nLen, DS_U8 *text)
109        {
110                DST_OS_Free(&strUTF8);
111                if (nLen == 0 || text == 0) return;
112                DS_U16 strUni[4096];
113                memset(strUni, 0, 4096*2);
114                DMW_Decode_MultipleStringStructure(nLen, text, (char*)"kor",4096-1, strUni);
115                strUTF8 = (char*)JST_Uni2Utf8(strUni, 4096-1);
116        }
117        char* get()
118        {
119                if (strUTF8) return strUTF8;
120                static char *strEmpty = (char*)"";
121                return strEmpty;
122        }
123        ~mss2utf8()
124        {
125                DST_OS_Free(&strUTF8);
126        }
127};
128
129#if 0
130____MUTE___()
131#endif
132
133static DS_U32 g_VideoMute = 0;
134static DS_U32 g_AudioMute = 0;
135static DS_U8  g_AudioVolume = 0;
136
137static void CT_VideoMute(DS_U8 nPos, bool bVal)
138{
139        DS_U32 nVal = bVal ? (g_VideoMute | (1 << nPos)) : (g_VideoMute & (~(1 << nPos)));
140        if (nVal == g_VideoMute) return;
141        if (g_VideoMute == 0 || nVal == 0) DHL_VID_Mute(bVal);
142        g_VideoMute = nVal;
143}
144
145static void CT_AudioMute(DS_U8 nPos, bool bVal)
146{
147        DS_U32 nVal = bVal ? (g_AudioMute | (1 << nPos)) : (g_AudioMute & (~(1 << nPos)));
148        if (nVal == g_AudioMute) return;
149        if (g_AudioMute == 0 || nVal == 0) DHL_AUD_Volume(bVal ? g_AudioVolume : 0);
150        g_AudioMute = nVal;
151}
152
153void CT_AudioVolume(DS_U8 nVal)
154{
155        g_AudioVolume = nVal;
156        CT_AudioMute(0, nVal ? true : false);
157}
158
159// mute ó¸®
160static void CT_ChannelChangeVideoMute(bool bMute)
161{
162        CT_VideoMute(1, bMute);
163}
164static void CT_ChannelChangeAudioMute(bool bMute)
165{
166        CT_AudioMute(1, bMute);
167}
168
169//static void CT_DigitalSignalMute(bool bMute)
170//{
171//      CT_VideoMute(2, bMute);
172//      CT_AudioMute(2, bMute);
173//}
174
175void CT_AutoScanMute(bool bMute)
176{
177        CT_VideoMute(3, bMute);
178        CT_AudioMute(3, bMute);
179}
180
181void CT_RatingMute(bool bMute)
182{
183        CT_VideoMute(4, bMute);
184        CT_AudioMute(4, bMute);
185}
186
187
188#if 0
189____CHANNEL_MAP___()
190#endif
191
192class CDBString
193{
194private:
195        char* strText;
196public:
197
198        CDBString(const char* strSQL)
199        {
200                strText = (char*)DST_OS_Calloc(1,1);
201                Add("%s", strSQL);
202        }
203        ~CDBString()
204        {
205                DST_OS_Free(&strText);
206        }
207        int Add(const char* strSQL, ...)
208        {
209                if (strSQL == 0) return 0;
210                va_list ap;
211          char *z;
212                va_start(ap, strSQL);
213          z = sqlite3_vmprintf(strSQL, ap);
214          va_end(ap);
215                int nLen = strlen(strText) + strlen(z) + 1;
216                char* strTmp = (char*)DST_OS_Calloc(nLen,1);
217                sprintf(strTmp, "%s%s",strText, z);
218                DST_OS_Free(&strText);
219                sqlite3_free(z);
220                strText = strTmp;       
221                return nLen;
222        }
223        void Run()
224        {
225                // insert ¹®À» ½±°Ô ó¸®Çϱâ À§Çؼ­ ¸¶Áö¸· ±ÛÀÚ°¡ ½°Ç¥¸é ½ºÆäÀ̽º·Î º¯È¯
226                int nLen = strlen(strText);
227                if (strText[nLen-1] == ',') 
228                {
229                        strText[nLen-1] = ' ';
230                        CDB db;
231                        db.Query("%s", strText);
232                }
233                strText[0] = 0; // clear
234        }
235};
236
237static DS_U8* GetMpegDescriptor (DS_U8 *descriptors, DS_U16 len, DS_U8 tag, DS_U8& tag_len)
238{
239        if (descriptors == 0 || len == 0) return 0;
240        int nPos = 0;
241        while (nPos < len)
242        {
243                DS_U8 nTag = descriptors[nPos];
244                DS_U8 nLen = descriptors[nPos+1];
245                if (nPos + nLen + 2 > len) break; // ÀԷµȵ¥ÀÌÅÍÀÇ ¹üÀ§¸¦ ¹ù¾î³ª µ¥ÀÌÅͰ¡ Àִ°æ¿ì
246                if (nTag == tag)
247                {
248                        tag_len = nLen;
249                        return &descriptors[nPos];
250                }
251                nPos += (nLen + 2);
252        }
253        return 0;
254}
255
256static int GetMpegDescriptorCount (DS_U8 *descriptors, DS_U16 len, DS_U8 tag)
257{
258        if (descriptors == 0 || len == 0) return 0;
259
260        int nCount = 0;
261        int nPos = 0;
262        while (nPos < len)
263        {
264                DS_U8 nTag = descriptors[nPos];
265               
266                DS_U8 nLen = descriptors[nPos+1];
267                if (nPos + nLen + 2 > len) break; // ÀԷµȵ¥ÀÌÅÍÀÇ ¹üÀ§¸¦ ¹ù¾î³ª µ¥ÀÌÅͰ¡ Àִ°æ¿ì
268                if (nTag == tag) nCount++;
269                nPos += (nLen + 2);
270        }
271        return nCount;
272}
273
274// ¹®ÀÚ¿­ µÚÀÇ ' ' Á¦°Å
275static void Trim(DS_U16 *strText, int nLen)
276{
277        for (int i=nLen-1; i >= 0; i--)
278        {
279                if (strText[i] == ' ')
280                {
281                        strText[i] = 0;
282                        continue;
283                }
284                break;
285        }
286}
287
288static bool CT_ChMapUpdateTVCT(DS_U8 RF, TVCT *tvct, DS_U32 CRC32)
289{
290        if (tvct == 0) return false;
291        if (tvct->numChannels == 0) return false;
292        if (tvct->channel == 0) return false;
293               
294        CDB db;
295//      db.Query("create table if not exists tvct(rf int unique, transport_stream_id int, version_number int, crc32)");
296//      db.Query("create table if not exists tvct_sub("
297//              "rf int, short_name text, long_name text, major_channel_number int, minor_channel_number int, "
298//              "modulation_mode int, carrier_frequency int, channel_TSID int, program_number int, ETM_location int, "
299//              "access_controlled int, hidden int, show_guide int,  service_type int, source_id int)");
300
301        db.GetTable("select crc32 from tvct where rf = %d and crc32 = %d", RF, CRC32);
302        if(db.GetRow() > 0) return false; // ÀÌ¹Ì µ¿ÀÏÇÑ TVCT°¡ ä³Î¸Ê¿¡ Àִ°æ¿ìÀÓ
303        db.Query("insert or replace into tvct values(%d, %d, %d, %d)", 
304                RF, tvct->transport_stream_id, tvct->version_number, (int)CRC32);
305        CDBString tvct_sub("insert into tvct_sub values");
306        tvctChannelPtr_t channel = tvct->channel;
307        for (int i = 0; i < tvct->numChannels; i++, channel++)
308        {
309                Trim(channel->short_name, 7);
310                DS_U8* strName = JST_Uni2Utf8(channel->short_name, 7);
311                mss2utf8 strExtName;
312                if (GetMpegDescriptorCount(channel->descriptors, channel->descriptor_length, extended_channel_name_tag))
313                {
314                        DS_U8 tag_len = 0;
315                        DS_U8 *p = GetMpegDescriptor(channel->descriptors, channel->descriptor_length, extended_channel_name_tag, tag_len);
316                        strExtName.set(tag_len, p+2);
317                }
318                tvct_sub.Add("(%d, %Q, %Q, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d),",
319                        RF, strName, strExtName.get(),
320                        channel->major_channel_number, channel->minor_channel_number,
321                        channel->modulation_mode, channel->carrier_frequency,
322                        channel->channel_TSID, channel->program_number,
323                        channel->ETM_location, channel->access_controlled,
324                        channel->hidden, channel->show_guide,
325                        channel->service_type, channel->source_id
326                        );
327                DST_OS_Free(&strName);
328#if 1
329                DST_Printf("tvct descriptor = %x\n",  (int)channel->descriptors);
330                DST_Printf("descriptor_length = %d\n", (int)channel->descriptor_length);
331                for (int i = 0; i < channel->descriptor_length; i++) DST_Printf("%02X ", channel->descriptors[i]);
332                DST_Printf("\n");
333#endif
334        }
335        db.Query("delete from tvct_sub where rf = %d", RF);
336        tvct_sub.Run();
337        return true;
338}
339
340static bool CT_ChMapUpdateCVCT(DS_U32 RF, CVCT *cvct, DS_U32 CRC32)
341{
342        if (cvct == 0) return false;
343        if (cvct->numChannels == 0) return false;
344        if (cvct->channel == 0) return false;
345
346        CDB db;
347//      db.Query("create table if not exists cvct(rf int unique, transport_stream_id int, version_number int, crc32)");
348//      db.Query("create table if not exists cvct_sub("
349//              "rf int, short_name text, long_name text, major_channel_number int, minor_channel_number int, "
350//              "modulation_mode int, carrier_frequency int, channel_TSID int, program_number int, ETM_location int, "
351//              "access_controlled int, hidden int, show_guide int, service_type int, source_id int)");
352
353        db.GetTable("select crc32 from cvct where rf = %d and crc32 = %d", RF, CRC32);
354        if(db.GetRow() > 0) return false; // ÀÌ¹Ì µ¿ÀÏÇÑ CVCT°¡ ä³Î¸Ê¿¡ Àִ°æ¿ìÀÓ
355        db.Query("insert or replace into cvct values(%d, %d, %d, %d)", 
356                RF, cvct->transport_stream_id, cvct->version_number, (int)CRC32);
357        CDBString cvct_sub("insert into cvct_sub values");
358        cvctChannelPtr_t channel = cvct->channel;
359        int nValidCount = 0;
360        for (int i = 0; i < cvct->numChannels; i++, channel++)
361        {
362                Trim(channel->short_name, 7);
363                DS_U8* strName = JST_Uni2Utf8(channel->short_name, 7);
364                mss2utf8 strExtName;
365                if (GetMpegDescriptorCount(channel->descriptors, channel->descriptor_length, extended_channel_name_tag))
366                {
367                        DS_U8 tag_len = 0;
368                        DS_U8 *p = GetMpegDescriptor(channel->descriptors, channel->descriptor_length, extended_channel_name_tag, tag_len);
369                        strExtName.set(tag_len, p+2);
370                }
371                // ATSC_private_information_descriptor
372                // KLabsŬ¸®¾îÄæDTV_¼Û¼ö½ÅÁ¤ÇÕÇ¥ÁØ_°³Á¤º»-1
373                bool bCrear = true;
374                if (GetMpegDescriptorCount(channel->descriptors, channel->descriptor_length, 0xAD))
375                {
376                        DS_U8 tag_len = 0;
377                        DS_U8 *p = GetMpegDescriptor(channel->descriptors, channel->descriptor_length, 0xAD, tag_len);
378                        if (p[0] == 0xAD) // descriptor_tag
379                        {
380                                if (p[1] >= 9) // descriptor_length
381                                {
382                                        if (p[2] == 0x54 && p[3] == 0x54 && p[4] == 0x41 && p[5] == 0x30) // format_identifier
383                                        {
384                                                if (p[6] >= 1) // private_info_count
385                                                {
386                                                        if (p[7] == 0x02) // private_info_type Ŭ¸®¾îÄæ DTV¿ë ¼­¼úÀÚ
387                                                        {
388                                                                if (p[8] == 0x02) // private_info_length
389                                                                {
390                                                                        DS_U8 ch_frequency_version_number = p[9];
391                                                                        DS_U8 channel_mode = (p[10] >> 4) & 0x0F;
392                                                                        DS_U8 resolution = p[10] & 0x0F;
393                                                                        DST_Printf("ch_frequency_version_number = %d channel_mode =%d resolution =%d\n", ch_frequency_version_number, channel_mode, resolution);
394                                                                        bCrear = (channel_mode == 0) ? true : false;
395                                                                }
396                                                        }
397                                                }
398                                        }
399                                }
400                        }
401                }
402               
403                bool bValidMajorMinor = true;
404                int major = channel->major_channel_number;
405                int minor = channel->minor_channel_number;
406                if (major < 1000)
407                {
408                        bValidMajorMinor = (minor > 0 && minor < 1000);
409                }       
410                else if (major >= 0x3F0)
411                {
412                        major = (major & 0x0F) * 1024 + minor;
413                        minor = 0;
414                }
415                else
416                {
417                        bValidMajorMinor = false;
418                }
419                bool bIsCurrentRF = true;
420                {
421                        if (channel->carrier_frequency)
422                        {
423                                DS_U32 freq = 1000000 * DST_GetMHzFrequencybyIndex(RF);
424                                //freq = 645000000; // TEST ÄÚµå
425                                bIsCurrentRF = (freq == channel->carrier_frequency);
426                        }
427                }
428                if (bCrear && bValidMajorMinor && channel->hidden==0 && bIsCurrentRF)
429                {
430                        nValidCount++;
431                        cvct_sub.Add("(%d, %Q, %Q, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d),",
432                                RF, strName, strExtName.get(),
433                                major, minor,
434                                channel->modulation_mode, channel->carrier_frequency,
435                                channel->channel_TSID, channel->program_number,
436                                channel->ETM_location, channel->access_controlled,
437                                channel->hidden, channel->show_guide,
438                                channel->service_type, channel->source_id
439                                );
440                }
441                DST_OS_Free(&strName);
442#if 1
443                DST_Printf("cvct descriptor = %x\n",  (int)channel->descriptors);
444                DST_Printf("descriptor_length = %d\n", (int)channel->descriptor_length);
445                for (int i = 0; i < channel->descriptor_length; i++) DST_Printf("%02X ", channel->descriptors[i]);
446                DST_Printf("\n");
447#endif
448        }
449        db.Query("delete from cvct_sub where rf = %d", RF);
450        if (nValidCount > 0) cvct_sub.Run();
451       
452#if 1
453                DST_Printf("cvct additional_descriptors = %x\n",  (int)cvct->additional_descriptors);
454                DST_Printf("cvct additional_descriptor_length = %d\n", (int)cvct->additional_descriptor_length);
455                for (int i = 0; i < cvct->additional_descriptor_length; i++) DST_Printf("%02X ", cvct->additional_descriptors[i]);
456                DST_Printf("\n");
457#endif
458
459        return true;
460}
461
462// ±âÁ¸ÀÇ PAT°¡ ¾÷µ¥ÀÌÆ® µÇ¸é VCT¸¦ Áö¿ì°í »õ·Î ¹Þ´Â´Ù
463// ¹Ýȯ°ªÀº °»½Å¿©ºÎÀÌ´Ù.
464static bool CT_ChMapUpdatePAT(DS_U8 RF, MPEG_PAT *pat, DS_U32 CRC32)
465{
466        if (pat == 0) return false;
467        CDB db;
468        db.GetTable("select crc from pat where rf =%d", RF);
469        bool bUpdate = false; // óÀ½¹Þ´Â°Å
470        if (db.GetRow() > 0) // ±âÁ¸¿¡ ÀÖ´Â CRC¿Í µ¿ÀÏÇÑÁö °Ë»ç
471        {
472                if ((int)CRC32 == atoi(db.GetResult(1))) return false; // µ¿ÀÏÇÑ°Ô ÀÖ´Ù¸é ¾÷µ¥ÀÌÆ® ¾È ÇÔ
473                bUpdate = true; // °»½ÅÇϴ°Å
474        }
475       
476        CDBString str("insert into pat values");
477        for (int i = 0; i < pat->numPrograms; i++)
478        {
479                DS_U16 program_number = pat->programs[i].program_number;
480                DS_U16 pid = pat->programs[i].program_map_PID;
481//              if (CT_IsFixedPID(pid) == true) continue;
482//              if (CT_CheckServiceID(program_number) == -1) continue;
483                str.Add("(%d, %d, %d, %d),", RF, program_number, pid, CRC32);
484        }
485        db.Query("delete from pat where rf=%d", RF);
486        str.Run();
487        // »ç¶óÁø PMT Á¤º¸ Á¦°Å
488        db.Query("delete from pmt where rf =%d and program_number not in (select program_number from pat where rf =%d)", RF, RF);
489        return bUpdate; // ¾÷µ¥ÀÌÆ®ÀÎÁö ¾Æ´ÑÁö ¹Ýȯ
490}
491
492
493static int g_ChCount = 0;
494int CT_ChMapCount()
495{
496        return g_ChCount;
497}
498
499void CT_ChMapUpdate()
500{
501        // CVCT ¿ì¼±
502        //  CVCT°¡ ÀÖÀ¸¸é TVCT´Â ¹«½ÃÇÑ´Ù.
503        // TVCT¿Í CVCT°¡ ¸ðµÎ ¾ø´Â RF´Â PMT ä³Î·Î ó¸®ÇÑ´Ù.
504        CDB db;
505        db.Query("drop table if exists channel_db;"
506        "create table channel_db as " 
507        "select tvct_sub.rf as rf, case when (length(long_name)< length(short_name)) then short_name else long_name end as name, major_channel_number as major, minor_channel_number as minor, tvct_sub.program_number, source_id, pcr_pid, video_pid, video_type "
508        "from tvct_sub "
509        "left join pmt "
510        "on tvct_sub.rf = pmt.rf and tvct_sub.program_number = pmt.program_number " 
511        "where hidden =0  and tvct_sub.rf not in (select rf from cvct) "
512        "union "
513        "select cvct_sub.rf, case when (length(long_name)< length(short_name)) then short_name else long_name end, major_channel_number, minor_channel_number, cvct_sub.program_number, source_id, pcr_pid, video_pid, video_type "
514        "from cvct_sub "
515        "left join pmt "
516        "on cvct_sub.rf = pmt.rf and cvct_sub.program_number = pmt.program_number " 
517        "where hidden =0 "
518        "union "
519        "select pmt.rf, '', case when (pmt.rf<96) then pmt.rf+2 else pmt.rf+4 end, minor, pmt.program_number, 0, pcr_pid, video_pid, video_type "
520        "from pmt where rf not in "
521        "(select rf from cvct union select rf from tvct) "
522        "order by major_channel_number, tvct_sub.rf, minor_channel_number;"
523       
524        "drop table if exists channel_updn;"
525        "create table channel_updn as "
526        "select major, channel_db.rf, minor, channel_db.program_number "
527        "FROM channel_db "
528        "LEFT JOIN skip_list "
529        "ON channel_db.rf = skip_list.rf and channel_db.program_number = skip_list.program_number "
530        "WHERE skip_list.program_number IS NULL;"
531       
532        );
533       
534        db.GetTable("select rf from channel_db");
535        g_ChCount = db.GetRow();
536       
537        DST_DB_Sync();
538}
539
540static bool g_bReceiveCCDescriptor = false;
541
542#define MAX_PMT_CC_TABLE_COUNT 500
543struct PMT_CC_TABLE
544{
545        int rf;
546        int program_number;
547        char language[4];
548        int cc_type;
549        int cc_id;
550        int easy_reader;
551        int wide_aspect_ratio;
552        int korean_code;
553};
554
555static PMT_CC_TABLE pmt_cc_table[MAX_PMT_CC_TABLE_COUNT];
556
557static void CT_ChMapUpdatePMTCCDescriptor(DS_U32 RF, DS_U16 prog_num, DS_U8 *descriptors, DS_U16 descriptor_length)
558{
559        T();
560        if(descriptors == 0 || descriptor_length == 0) return;
561        DS_U8 tag_len = 0;
562        DS_U8 *p = GetMpegDescriptor(descriptors, descriptor_length, caption_service_tag, tag_len );
563        if (tag_len == 0)       return;
564        DST_Printf("tag_len = %d\n", tag_len); for (int i=0; i < tag_len+2; i++) DST_Printf("0x%02X ", p[i]); DST_Printf("\n");
565        captionServiceDescriptorPtr_t descripPtr = 0;
566        T();
567        if (DHL_PSI_ParseCaptionServiceDescriptor(p, &descripPtr))      return;
568        T();
569        if (descripPtr == 0)    return;
570        CDB db;
571        DST_Printf("descripPtr->number_of_services = %d\n", descripPtr->number_of_services);
572        captionServicePtr_t captionService = descripPtr->service;
573        for(int idx = 0 ; idx < descripPtr->number_of_services ; idx++, captionService++)
574        {
575                if(captionService == 0) break;
576                DS_U8 ccId = (captionService->cc_type == cct_line21) ? captionService->cc_id.line21_field : captionService->cc_id.caption_service_number;
577                char strLanguage[4] = "kor";
578                strcpy(strLanguage, captionService->language);
579                DST_Printf("strLanguage = %s\n", strLanguage);
580                       
581                bool bFind = false;
582                for (int i = 0; i < MAX_PMT_CC_TABLE_COUNT; i++)
583                {
584                        if (pmt_cc_table[i].rf == 0 || (pmt_cc_table[i].rf == (int)RF && pmt_cc_table[i].program_number == prog_num))
585                        {
586                                pmt_cc_table[i].rf = RF;
587                                pmt_cc_table[i].program_number = prog_num;
588                                strcpy(pmt_cc_table[i].language,strLanguage);
589                                pmt_cc_table[i].cc_type = captionService->cc_type;
590                                pmt_cc_table[i].cc_id = ccId;
591                                pmt_cc_table[i].easy_reader = captionService->easy_reader;
592                                pmt_cc_table[i].wide_aspect_ratio = captionService->wide_aspect_ratio;
593                                pmt_cc_table[i].korean_code = captionService->korean_code;
594                                bFind = true;
595                                DST_Printf("%s|pmt_cc_table|captionService->cc_type = %d\n", __func__, captionService->cc_type);
596                                DST_Printf("%s|pmt_cc_table|ccId = %d\n", __func__, ccId);
597                                DST_Printf("%s|pmt_cc_table|captionService->easy_reader = %d\n", __func__, captionService->easy_reader);
598                                DST_Printf("%s|pmt_cc_table|captionService->wide_aspect_ratio = %d\n", __func__, captionService->wide_aspect_ratio);
599                                DST_Printf("%s|pmt_cc_table|captionService->korean_code = %d\n", __func__, captionService->korean_code);
600                                break;
601                        }
602                }
603                if (bFind == false)
604                {
605                        T();
606                        memset(pmt_cc_table, 0, sizeof(pmt_cc_table));
607                        CT_ChMapUpdatePMTCCDescriptor(RF, prog_num, descriptors, descriptor_length);
608                }                       
609                g_bReceiveCCDescriptor = true;
610        }
611        DHL_PSI_FreeMpegDescriptor(descripPtr);
612}
613
614
615#define MAX_PMT_AC3_TABLE_COUNT 500
616struct PMT_AC3_TABLE
617{
618        int rf;
619        int program_number;
620        int pid;
621        int bsmod;
622        int full_svc;
623        int langcod;
624        char language[4];
625};
626
627static PMT_AC3_TABLE pmt_ac3_table[MAX_PMT_AC3_TABLE_COUNT];
628
629static void CT_ChMapUpdatePMTAC3AudioDescriptor(DS_U32 RF, DS_U16 prog_num, DS_U16 pid, DS_U8 *descriptors, DS_U16 descriptor_length)
630{
631        T();
632        if (descriptors == 0 || descriptor_length == 0) return;
633        T();
634        DS_U8 tag_len = 0;
635        DS_U8 *p = GetMpegDescriptor(descriptors, descriptor_length, AC3_audio_stream_tag, tag_len );
636        if (tag_len == 0)       return;
637        DST_Printf("tag_len = %d\n", tag_len); for (int i=0; i < tag_len+2; i++) DST_Printf("0x%02X ", p[i]); DST_Printf("\n");
638        ac3AudioStreamDescriptorPtr_t descripPtr = 0;
639        if (DHL_PSI_ParseAc3AudioStreamDescriptor(p, &descripPtr))      return;
640        if (descripPtr == 0)    return;
641        CDB db;
642        char strLanguage[4] = {0,0,0,0};
643        strcpy(strLanguage, descripPtr->language);
644        DST_Printf("strLanguage = %s\n", strLanguage);
645       
646        bool bFind = false;
647        for (int i = 0; i < MAX_PMT_AC3_TABLE_COUNT; i++)
648        {
649                if (pmt_ac3_table[i].program_number == 0 || (pmt_ac3_table[i].rf == (int)RF && pmt_ac3_table[i].program_number == prog_num && pmt_ac3_table[i].pid == pid))
650                {
651                        pmt_ac3_table[i].rf = RF;
652                        pmt_ac3_table[i].program_number = prog_num;
653                        pmt_ac3_table[i].pid = pid;
654                        pmt_ac3_table[i].bsmod = descripPtr->bsmod;
655                        pmt_ac3_table[i].full_svc = descripPtr->full_svc;
656                        pmt_ac3_table[i].langcod = descripPtr->langcod;
657                        strcpy(pmt_ac3_table[i].language, strLanguage);
658                        bFind = true;
659                        DST_Printf("%s|pmt_ac3_table|%d\n", __func__, i);
660                        DST_Printf("%s|pmt_ac3_table|pid = %d\n", __func__, pid);
661                        DST_Printf("%s|pmt_ac3_table|descripPtr->bsmod = %d\n", __func__, descripPtr->bsmod);
662                        DST_Printf("%s|pmt_ac3_table|descripPtr->full_svc = %d\n", __func__, descripPtr->full_svc);
663                        DST_Printf("%s|pmt_ac3_table|descripPtr->langcod = %d\n", __func__, descripPtr->langcod);
664                        break;
665                }
666        }
667        if (bFind == false)
668        {
669                T();
670                memset(pmt_ac3_table, 0, sizeof(pmt_ac3_table));
671                CT_ChMapUpdatePMTAC3AudioDescriptor(RF, prog_num, pid, descriptors, descriptor_length);
672        }                       
673        DHL_PSI_FreeMpegDescriptor(descripPtr);
674}
675
676#define MAX_PMT_ISO_TABLE_COUNT 500
677struct PMT_ISO_TABLE
678{
679        int rf;
680        int program_number;
681        int pid;
682        char lang[4];
683        int type;
684};
685static PMT_ISO_TABLE pmt_iso_table[MAX_PMT_ISO_TABLE_COUNT];
686
687static void CT_ChMapUpdatePMTISO639LanguageDescriptor(DS_U32 RF, DS_U16 prog_num, DS_U16 pid, DS_U8 *descriptors, DS_U16 descriptor_length)
688{
689        T();
690        if (descriptors == 0 || descriptor_length == 0) return;
691        T();
692        DS_U8 tag_len = 0;
693        DS_U8 *p =  GetMpegDescriptor(descriptors, descriptor_length, ISO_639_language_tag, tag_len);
694        if (tag_len == 0)       return;
695        DST_Printf("tag_len = %d\n", tag_len); for (int i=0; i < tag_len+2; i++) DST_Printf("0x%02X ", p[i]); DST_Printf("\n");
696        if (p[1] < 4) return;
697        char ISO_639_Language_code[4];
698        ISO_639_Language_code[0] = (char)p[2];
699        ISO_639_Language_code[1] = (char)p[3];
700        ISO_639_Language_code[2] = (char)p[4];
701        ISO_639_Language_code[3] = 0;
702        DS_U8 audio_type = p[5];
703       
704        bool bFind = false;
705        for (int i = 0; i < MAX_PMT_AC3_TABLE_COUNT; i++)
706        {
707                if (pmt_iso_table[i].program_number == 0 || (pmt_iso_table[i].rf == (int)RF && pmt_iso_table[i].program_number == prog_num && pmt_iso_table[i].pid == pid))
708                {
709                        pmt_iso_table[i].rf = RF;
710                        pmt_iso_table[i].program_number = prog_num;
711                        pmt_iso_table[i].pid = pid;
712                        strcpy(pmt_iso_table[i].lang, ISO_639_Language_code);
713                        pmt_iso_table[i].type = audio_type;
714                        bFind = true;
715                        DST_Printf("%s|pmt_iso_table|%d\n", __func__, i);
716                        DST_Printf("%s|pmt_iso_table|pid = %d\n", __func__, pid);
717                        DST_Printf("%s|pmt_iso_table|ISO_639_Language_code = %s\n", __func__, ISO_639_Language_code);
718                        DST_Printf("%s|pmt_iso_table|audio_type = %d\n", __func__, audio_type);
719                        break;
720                }
721        }
722        if (bFind == false)
723        {
724                T();
725                memset(pmt_iso_table, 0, sizeof(pmt_iso_table));
726                CT_ChMapUpdatePMTISO639LanguageDescriptor(RF, prog_num, pid, descriptors, descriptor_length);
727        }                       
728}
729
730#define MAX_PMT_AUDIO_TABLE_COUNT 500
731struct PMT_AUDIO_TABLE
732{
733        int rf;
734        int program_number;
735        int pid;
736        int type;
737        int component_tag;
738};
739static PMT_AUDIO_TABLE pmt_audio_table[MAX_PMT_AUDIO_TABLE_COUNT];
740
741static void CT_PMT_AudioTableUpdate(int rf, int program_number, int pid, int type, int component_tag)
742{
743        // µ¿ÀÏÇÑ Á¤º¸°¡ ÀÌ¹Ì ÀÖ´Â °æ¿ì
744        for (int j = 0; j < MAX_PMT_AUDIO_TABLE_COUNT; j++)
745        {
746                if (pmt_audio_table[j].rf != rf) continue;
747                if (pmt_audio_table[j].program_number != program_number) continue;
748                if (pmt_audio_table[j].pid != pid) continue;
749                pmt_audio_table[j].rf = rf;
750                pmt_audio_table[j].program_number = program_number;
751                pmt_audio_table[j].pid = pid;
752                pmt_audio_table[j].type = type;
753                pmt_audio_table[j].component_tag = component_tag;
754                return;
755        }
756        // ºó°÷¿¡ ã¾Æ ³Ö´Â´Ù.
757        for (int j = 0; j < MAX_PMT_AUDIO_TABLE_COUNT; j++)
758        {
759                if (pmt_audio_table[j].program_number != 0) continue;
760                pmt_audio_table[j].rf = rf;
761                pmt_audio_table[j].program_number = program_number;
762                pmt_audio_table[j].pid = pid;
763                pmt_audio_table[j].type = type;
764                pmt_audio_table[j].component_tag = component_tag;
765                return;
766        }
767        // ºó°÷ÀÌ ¾ø´Â°æ¿ì ¸ðµÎ Áö¿î´Ù.
768        memset(pmt_audio_table, 0, sizeof(pmt_audio_table));
769        // Àç±ÍÈ£Ãâ
770        CT_PMT_AudioTableUpdate(rf, program_number, pid, type, component_tag);
771}
772
773static bool CT_ChMapUpdatePMT(DS_U8 RF, MPEG_PMT *pmt, int minor, DS_U32 CRC32)
774{
775        if (pmt == 0) return false;
776        CDB db;
777        db.GetTable("select crc from pmt where rf =%d and crc=%d", RF, CRC32);
778        //if (db.GetRow() > 0) return false;
779       
780        for (int i = 0 ; i < MAX_PMT_AUDIO_TABLE_COUNT; i++) if (pmt_audio_table[i].rf == (int)RF && pmt_audio_table[i].program_number == pmt->program_number) pmt_audio_table[i].rf = 0;
781        for (int i = 0 ; i < MAX_PMT_CC_TABLE_COUNT; i++) if (pmt_cc_table[i].rf == (int)RF && pmt_cc_table[i].program_number == pmt->program_number) pmt_cc_table[i].rf = 0;
782        for (int i = 0 ; i < MAX_PMT_AC3_TABLE_COUNT; i++) if (pmt_ac3_table[i].rf == (int)RF && pmt_ac3_table[i].program_number == pmt->program_number) pmt_ac3_table[i].rf = 0;       
783        for (int i = 0 ; i < MAX_PMT_ISO_TABLE_COUNT; i++) if (pmt_iso_table[i].rf == (int)RF && pmt_iso_table[i].program_number == pmt->program_number) pmt_iso_table[i].rf = 0;
784
785        DS_U16 video_pid = 0;
786        DS_U8  video_stream_type = 0;
787        for (int i = 0; i < pmt->numStreams; i++)
788        {
789                DS_U16 pid = pmt->streams[i].elementary_PID;
790                if (pid == 0 || pid >= 0x1FFF) continue;
791                DS_U8 stream_type = pmt->streams[i].stream_type;
792                DS_U8 component_tag = pmt->streams[i].component_tag;
793                switch (stream_type)
794                {
795                        case StreamType_MPEG1Video:
796                        case StreamType_MPEG2Video:
797                        case StreamType_MPEG4Video:
798                        case StreamType_DC2Video:
799                                video_pid = pid;
800                                video_stream_type = stream_type;
801                                CT_ChMapUpdatePMTCCDescriptor(RF, pmt->program_number, pmt->streams[i].descriptors, pmt->streams[i].descriptor_length);
802                                break;
803                        case StreamType_MPEG1Audio:
804                        case StreamType_MPEG2Audio:
805                        case StreamType_MPEG4Audio:
806                        case StreamType_AACAudio:
807                        case StreamType_AC3Audio:
808                                CT_PMT_AudioTableUpdate(RF, pmt->program_number, pid, stream_type, component_tag);
809                                CT_ChMapUpdatePMTAC3AudioDescriptor(RF, pmt->program_number, pid, pmt->streams[i].descriptors, pmt->streams[i].descriptor_length);
810                                CT_ChMapUpdatePMTISO639LanguageDescriptor(RF, pmt->program_number, pid, pmt->streams[i].descriptors, pmt->streams[i].descriptor_length);
811                                break;
812                }
813        }
814        db.Query(       "delete from pmt where rf=%d and program_number=%d;"
815                                                "insert into pmt values(%d, %d, %d, 0, %d, %d,%d, %d)", 
816                                                RF, pmt->program_number,
817                                                RF, pmt->program_number, pmt->PCR_PID, video_pid, video_stream_type, minor, CRC32);
818        return true;
819}
820
821static bool CT_ChMapUpdateEIT(DS_U8 rf, EIT *eit, DS_U8 id, DS_U32 CRC32)
822{
823        if (eit == 0) return false;
824        CDB db;
825        db.GetTable("select crc from eit where rf =%d and id=%d and source_id=%d", rf, id, eit->source_id);
826        if(db.GetRow() > 0)
827        {
828                if ((int)CRC32 == atoi(db.GetResult(1)))
829                {
830                        return false;
831                }
832                else
833                {
834                        db.Query("delete from eit where rf = %d and id=%d and source_id=%d", rf, id, eit->source_id);
835                        db.Query("delete from eit_sub where rf = %d and id=%d and source_id=%d", rf, id, eit->source_id);
836                }
837        }
838        db.Query("insert into eit values(%d, %d, %d, %d, %d)", rf, id, eit->source_id, eit->version_number, CRC32);
839        CDBString eit_sub("insert into eit_sub values");
840        eitEventPtr_t event = eit->event;
841        for (int i = 0; i < eit->numEvents; i++, event++)
842        {
843                mss2utf8 strTitle(event->title_length,event->title);
844                eit_sub.Add("(%d, %d, %d, %d, %d, %d, %Q),",
845                                rf, id, eit->source_id,  event->event_id, event->start_time, event->length_in_seconds, 
846                                strTitle.get());
847        }
848        if (eit->numEvents > 0) eit_sub.Run();
849        return true;
850}
851
852static bool CT_ChMapUpdateETT(DS_U8 rf, ETT *ett, DS_U32 crc)
853{
854        if (ett == 0) return false;
855        CDB db;
856        db.GetTable("select crc from ett where rf =%d and crc=%d", rf, crc);
857        if(db.GetRow() > 0) return false;
858        mss2utf8 strText(ett->extended_text_message_length,ett->extended_text_message);
859        db.Query("insert into ett values(%d, %d, %d, %Q, %d)", 
860                rf, (ett->ETM_id>>16) & 0xFFFF, (ett->ETM_id>>2) & 0x3FFF, strText.get(), crc);
861               
862        //À¯È¿ÇÑ ETT¸¦ 100°³ ¹ÞÀ»¶§¸¶´Ù EIT¿Í ¿¬°áµÇÁö ¾ÊÀº ETT¸¦ Á¤¸®ÇÑ´Ù.
863        static int nReceiveETTCount = 0;
864        nReceiveETTCount++;
865        if ((nReceiveETTCount % 100) == 0)
866        {
867                db.Query("delete from ett where crc in (select crc from ett left join eit_sub on "
868                        "eit_sub.rf = ett.rf and eit_sub.source_id = ett.source_id and  eit_sub.event_id = ett.event_id "
869                        "where id is null)");
870        }       
871        return true;
872}
873
874
875// ä³Î½ºÄµ¿¡ ½ÇÆÐÇÑ °æ¿ì ÇØ´ç RF Á¦°Å
876void JST_DB_Del(DS_U8 nRF)
877{
878        CDB db;
879        db.Query("delete from eit where rf=%d", nRF);
880        db.Query("delete from eit_sub where rf=%d", nRF);
881        db.Query("delete from ett where rf=%d", nRF);
882        db.Query("delete from pat where rf=%d", nRF);
883        db.Query("delete from pmt where rf=%d", nRF);
884//      db.Query("delete from signal where rf=%d", nRF);
885        db.Query("delete from tvct where rf=%d", nRF);
886        db.Query("delete from tvct_sub where rf=%d", nRF);
887        db.Query("delete from cvct where rf=%d", nRF);
888        db.Query("delete from cvct_sub where rf=%d", nRF);
889        db.Query("delete from channel_db where rf=%d", nRF);
890        db.Query("delete from channel_updn where rf=%d", nRF);
891}
892
893#if 0
894____CHANNEL_TASK___()
895#endif
896
897static int gMsgQ = 0;
898static int gSIMsgQ = 0;
899
900struct CT_Msg {
901        DS_U8   Cmd;
902        DHL_MODULATION_MODE demod;
903        DS_U8 RF;
904        DS_U16 program_number;
905};
906
907#define CMD_NULL               0
908#define CMD_TUNE               1
909#define CMD_SCAN                2
910#define CMD_RF_UPDATE 3
911#define CMD_CVT              4
912#define CMD_OTC             5
913#define CMD_OTC_STOP   6
914#define CMD_STOP               8
915#define CMD_CLOSE              8
916
917char* CT_GetMsgName(DS_U8 Cmd)
918{
919        static char strText[32];
920        sprintf(strText, "Unknown");
921        switch (Cmd)
922        {
923                case CT_RECEIVE_PAT:sprintf(strText, "CT_RECEIVE_PAT"); break;
924                case CT_RECEIVE_PMT:sprintf(strText, "CT_RECEIVE_PMT"); break;
925                case CT_RECEIVE_MGT:sprintf(strText, "CT_RECEIVE_MGT"); break;
926                case CT_CHMAP_UPDATE:sprintf(strText, "CT_CHMAP_UPDATE"); break;
927                case CT_SIGNAL_INFO:sprintf(strText, "CT_SIGNAL_INFO"); break;
928                case CT_AV_START:sprintf(strText, "CT_AV_START"); break;
929                case CT_SCAN_PSIP_WAIT:sprintf(strText, "CT_SCAN_PSIP_WAIT"); break;
930                case CT_SCAN_LOCK_WAIT:sprintf(strText, "CT_SCAN_LOCK_WAIT"); break;
931                case CT_TUNE_START:sprintf(strText, "CT_TUNE_START"); break;
932                case CT_SCAN_START:sprintf(strText, "CT_SCAN_START"); break;
933                case CT_STOPPED:sprintf(strText, "CT_STOPPED"); break;
934                case CT_RECEIVE_PMT_CC:sprintf(strText, "CT_RECEIVE_PMT_CC"); break;
935                case CT_RECEIVE_PMT_AUDIO:sprintf(strText, "CT_RECEIVE_PMT_AUDIO"); break;
936        }
937        return strText;
938}
939
940static jst_callback g_callback = 0;
941
942static void CT_CallBack(DS_U8 Cmd = 0, DS_U32 p1 = 0, DS_U32 p2 = 0, DS_U32 p3 = 0, DS_U32 p4 = 0, DS_U32 p5 = 0, DS_U32 p6 = 0)
943{
944        ////DST_Printf("Cmd = %s(%d) %d %d %d\n", CT_GetMsgName(Cmd), Cmd, p1, p2, p3);
945        if (g_callback) g_callback(Cmd, p1, p2, p3, p4, p5, p6);
946}
947
948static void DST_FreeAtscTable(void *tablePtrPtr)
949{
950        if (tablePtrPtr == NULL || *(void **) tablePtrPtr == NULL) return;
951        DHL_PSI_FreeMpegSection(*(void **) tablePtrPtr);
952        *(void **) tablePtrPtr = NULL;
953}
954
955struct CT_SI_Msg {
956        DS_U32 RF;
957        DHL_MODULATION_MODE demod;
958        DS_U32 nRequestID;
959        DS_U32 *SI;
960        DS_U32 CRC32;
961};
962
963struct MTS
964{
965        DS_U16 pid;
966        DS_U8  type;
967        bool bKorean;
968        bool bVI;
969};
970
971static int CT_DB_GetAudioPidSub(MTS *mts, int mts_count)
972{
973//      for (int i = 0; i < mts_count; i++)
974//      {
975//              DST_Printf("mts[%d].bVI = %d mts[%d].bKorean = %d\n", i, mts[i].bVI, i, mts[i].bKorean);
976//      }
977        // È­¸éÇØ¼³¹æ¼Û + Çѱ¹¾î
978        if (DST_EEPROM_GetVI() == 1 && DST_EEPROM_GetAudioPref() == 0) // È­¸éÇØ¼³¹æ¼Û
979        {
980                // È­¸éÇØ¼³¹æ¼ÛÀ̸鼭 Çѱ¹¾î
981                for (int i = 0; i < mts_count; i++) if (mts[i].bVI == true && mts[i].bKorean == true) return i;
982                // ù¹øÂ° Çѱ¹¾î
983                for (int i = 0; i < mts_count; i++) if (mts[i].bKorean == true) return i;
984                // ù¹øÀç Æ®·¢
985                return 0;
986        }
987        // È­¸éÇØ¼³¹æ¼Û + ¿Ü±¹¾î
988        if (DST_EEPROM_GetVI() == 1 && DST_EEPROM_GetAudioPref() == 1) // È­¸éÇØ¼³¹æ¼Û
989        {
990                // È­¸éÇØ¼³¹æ¼ÛÀ̸鼭 ¿Ü±¹¾î
991                for (int i = 0; i < mts_count; i++) if (mts[i].bVI == true && mts[i].bKorean == false) return i;
992                // ù¹øÂ° ¿Ü±¹¾î
993                for (int i = 0; i < mts_count; i++) if (mts[i].bKorean == false) return i;
994                // µÎ¹øÀç Æ®·¢
995                return 1;
996        }
997        // È­¸éÇØ¼³ ¹æ¼Û(x) + Çѱ¹¾î
998        if (DST_EEPROM_GetAudioPref() == 0) // È­¸éÇØ¼³¹æ¼Û
999        {
1000                // È­¸éÇØ¼³¹æ¼Û¾Æ´Ï¸é¼­ Çѱ¹¾î
1001                for (int i = 0; i < mts_count; i++) if (mts[i].bVI == false && mts[i].bKorean == true) return i;
1002                // ù¹øÂ° Çѱ¹¾î
1003                for (int i = 0; i < mts_count; i++) if (mts[i].bKorean == true) return i;
1004                // È­¸éÇØ¼³¹æ¼Û¾Æ´Ï¸é¼­ ¿Ü±¹¾î
1005                for (int i = 0; i < mts_count; i++) if (mts[i].bVI == false && mts[i].bKorean == false) return i;
1006                // ù¹øÀç Æ®·¢
1007                return 0;
1008        }
1009        // È­¸éÇØ¼³ ¹æ¼Û(x) + ¿Ü±¹¾î
1010        // È­¸éÇØ¼³¹æ¼Û¾Æ´Ï¸é¼­ ¿Ü±¹¾î
1011        for (int i = 0; i < mts_count; i++) if (mts[i].bVI == false && mts[i].bKorean == false) return i;
1012        // ù¹øÂ° ¿Ü±¹¾î
1013        for (int i = 0; i < mts_count; i++) if (mts[i].bKorean == false) return i;
1014        // È­¸éÇØ¼³¹æ¼Û¾Æ´Ï¸é¼­ Çѱ¹¾î
1015        for (int i = 0; i < mts_count; i++) if (mts[i].bVI == false && mts[i].bKorean == true) return i;
1016        // µÎ¹øÀç Æ®·¢
1017        return 1;
1018}
1019
1020// ÀÔ·ÂµÈ ¹®ÀÚ¿­ÀÌ "kor"ÀÎÁö °Ë»çÇÑ´Ù.
1021// -1 unknown 0: ¿Ü±¹¾î 1: Çѱ¹¾î
1022static int isKOR(char* strText)
1023{
1024        if (strText == 0) return -1;
1025        int nLen = strlen(strText);
1026        if (nLen != 3) return -1;
1027        for (int i= 0; i < nLen; i++) if (strText[i] >='A' || strText[i] <= 'Z') strText[i] -= ('A'-'a'); // tolower
1028        return (strcmp(strText, "kor") == 0) ? 1 : 0;
1029}
1030
1031
1032int CT_GetAudioCount(DS_U8 RF, DS_U16 program_number)
1033{
1034        int pmt_audio_count = 0;
1035        for (int i = 0; i < MAX_PMT_AUDIO_TABLE_COUNT; i++)
1036        {
1037                if (pmt_audio_table[i].rf == (int)RF && pmt_audio_table[i].program_number == program_number)
1038                        pmt_audio_count++;
1039        }
1040        return pmt_audio_count;
1041}
1042
1043static bool g_ReceivePMTAudio = false;
1044void CT_DB_GetAudioPid(DS_U8 RF, DS_U16 program_number, DS_U16* pid, DS_U8* type)
1045{
1046        static DS_U32 old_RF = 0;
1047        static DS_U16 old_program_number = 0;
1048        static DS_U16 old_pid = 0;
1049        static DS_U8 old_type = 0;
1050        if (g_ReceivePMTAudio == true || DST_g_AudioSettingChanged == true || old_RF != RF || old_program_number != program_number)
1051        {
1052                DST_g_AudioSettingChanged = false;
1053               
1054                int pmt_audio_count = 0;
1055                struct PMT_AUDIO
1056                {
1057                        int pid;
1058                        int type;
1059                };
1060                PMT_AUDIO pmt_audio[32];
1061                memset(pmt_audio, 0, sizeof(pmt_audio));
1062                for (int i = 0; i < MAX_PMT_AUDIO_TABLE_COUNT; i++)
1063                {
1064                        if (pmt_audio_table[i].rf == (int)RF && pmt_audio_table[i].program_number == program_number)
1065                        {
1066                                pmt_audio[pmt_audio_count].pid = pmt_audio_table[i].pid;
1067                                pmt_audio[pmt_audio_count].type = pmt_audio_table[i].type;
1068                                pmt_audio_count++;
1069                        }
1070                        if (pmt_audio_count == 32) break;
1071                }
1072                if (pmt_audio_count < 1)
1073                {
1074                        *pid = 0; *type = 0;
1075                }
1076                else
1077                {
1078                        if (pmt_audio_count == 1)
1079                        {
1080                                *pid = pmt_audio[0].pid;
1081                                *type = pmt_audio[0].type;
1082                        }
1083                        else
1084                        {
1085                                int mts_count = pmt_audio_count;
1086                                MTS *mts = (MTS*)DST_OS_Malloc(sizeof(MTS)*mts_count);
1087                                for (int i = 0; i < mts_count; i++)
1088                                {
1089                                        mts[i].pid = pmt_audio[i].pid;
1090                                        mts[i].type = pmt_audio[i].type;
1091                                        mts[i].bKorean = true;
1092                                        mts[i].bVI = false;
1093                                        int nKorean[3] = {-1, -1, -1}; // unknown
1094                                        // AC-3 Audio Descriptor °¡ ¿ì¼± ¼øÀ§°¡ ³ô´Ù
1095                                        for (int j = 0; j < MAX_PMT_ISO_TABLE_COUNT; j++)
1096                                        {
1097                                                if (pmt_iso_table[j].rf == (int)RF && pmt_iso_table[j].program_number == program_number && pmt_iso_table[j].pid == mts[i].pid)
1098                                                {
1099                                                DS_U8 audio_type = pmt_iso_table[j].type;
1100                                                mts[i].bVI = (audio_type == 0x03);
1101                                                nKorean[0] = isKOR(pmt_iso_table[j].lang);
1102                                                break;
1103                                        }
1104                                        }
1105                                        for (int j = 0; j < MAX_PMT_AC3_TABLE_COUNT; j++)
1106                                        {
1107                                                if (pmt_ac3_table[j].rf == (int)RF && pmt_ac3_table[j].program_number == program_number && pmt_ac3_table[j].pid == mts[i].pid)
1108                                                {
1109                                                        DS_U8 bsmod = pmt_ac3_table[j].bsmod;
1110                                                        DS_U8 full_svc = pmt_ac3_table[j].full_svc;
1111                                                        DS_U8 langcod = pmt_ac3_table[j].langcod;
1112                                                        mts[i].bVI = (bsmod == 0x02 && full_svc == 0x01);
1113                                                        nKorean[1] = (langcod == 0xFF) ? -1 : (langcod == 0x65) ? 1 : 0;
1114                                                        nKorean[2] = isKOR(pmt_ac3_table[j].language);
1115                                                        break;
1116                                                }
1117                                        }
1118//                                      DST_Printf("nKorean[0] = %d nKorean[1] = %d nKorean[2] = %d\n", nKorean[0], nKorean[1], nKorean[2]);
1119                                        if (nKorean[0] == 0 || nKorean[1] == 0 || nKorean[2] == 0) mts[i].bKorean = false; // µÑ ÁßÇϳª ¿Ü±¹¾îÀÎ °æ¿ì ¿Ü±¹¾î
1120                                        if (nKorean[0] == 1 || nKorean[1] == 1 || nKorean[2] == 1) mts[i].bKorean = true; // µÑ Áß Çϳª Çѱ¹¾îÀÎ °æ¿ì Çѱ¹¾î
1121                                        //isoÁ¤º¸  ac3Á¤º¸  °áÁ¤µÈ¾ð¾î
1122                                        //¾Ë¼ö¾øÀ½ ¾Ë¼ö¾øÀ½ Çѱ¹¾î
1123                                        //¾Ë¼ö¾øÀ½ ¿Ü±¹¾î   ¿Ü±¹¾î
1124                                        //¾Ë¼ö¾øÀ½ Çѱ¹¾î   Çѱ¹¾î
1125                                        //¿Ü±¹¾î   ¾Ë¼ö¾øÀ½ ¿Ü±¹¾î
1126                                        //¿Ü±¹¾î   ¿Ü±¹¾î   ¿Ü±¹¾î
1127                                        //¿Ü±¹¾î   Çѱ¹¾î   Çѱ¹¾î
1128                                        //Çѱ¹¾î   ¾Ë¼ö¾øÀ½ Çѱ¹¾î
1129                                        //Çѱ¹¾î   ¿Ü±¹¾î   Çѱ¹¾î
1130                                        //Çѱ¹¾î         Çѱ¹¾î   Çѱ¹¾î
1131                                }
1132                                int nPos = CT_DB_GetAudioPidSub(mts, mts_count);
1133                                *pid =  mts[nPos].pid;
1134                                *type = mts[nPos].type;
1135                                DST_OS_Free(&mts);                             
1136                        }
1137                }
1138                g_ReceivePMTAudio = false;
1139                old_RF = RF;
1140                old_program_number = program_number;
1141                old_pid = *pid;
1142                old_type = *type;
1143        }
1144        else
1145        {
1146                *pid = old_pid; *type = old_type;
1147        }
1148}
1149
1150//static void CT_DB_GetCCPid(DS_U8 RF, DS_U16 sID,DS_U16 pid[8])
1151//{
1152//      CDB db;
1153//      db.GetTable("select pid from pmt_cc where rf=%d and program_number=%d", RF, sID);
1154//      memset(pid, 0, sizeof(DS_U16)*8);
1155//      for (int i = 0; i < db.GetRow(); i++) pid[i] = atoi(db.GetResult(i+1));
1156//}
1157
1158void CT_DB_GetVideoPid(DS_U8 RF, DS_U16 sID,DS_U16* pcr, DS_U16* pid, DS_U8* type)
1159{
1160        CDB db;
1161        db.GetTable("select pcr_pid, video_pid, video_type from pmt where rf=%d and program_number=%d", RF, sID);
1162        if (pcr) *pcr = (db.GetRow() < 1) ? 0 : atoi(db.GetResult(3));
1163        if (pid) *pid = (db.GetRow() < 1) ? 0 : atoi(db.GetResult(4));
1164        if (type) *type = (db.GetRow() < 1) ? 0 : atoi(db.GetResult(5));
1165}
1166
1167#define MAX_CRC_COUNT 400
1168class CheckCRC32
1169{
1170private:
1171        int nPos;
1172        DS_U32 CRC32[MAX_CRC_COUNT];
1173public:
1174        CheckCRC32()
1175        {
1176                memset(CRC32, 0, sizeof(CRC32));
1177                nPos = 0;
1178        }
1179        void Add(DS_U32 crc32)
1180        {
1181                for (int i = 0; i < MAX_CRC_COUNT; i++) if (CRC32[i] == crc32) return;
1182                CRC32[nPos] =  crc32;
1183                nPos++;
1184                if (nPos >= MAX_CRC_COUNT) nPos = 0;
1185        }
1186        bool IsDuplicate(DS_U32 crc32)
1187        {
1188                for (int i = 0; i < MAX_CRC_COUNT; i++) if (CRC32[i] == crc32) return true;
1189                return false;
1190        }
1191        // CRC LIST¿¡ ¾ø´Â CRC´Â Áö¿î´Ù.
1192        void Clear(DS_U32 *crclist, int nCount)
1193        {
1194                for (int i = 0; i < MAX_CRC_COUNT; i++)
1195                {
1196                        if (CRC32[i] == 0) continue;
1197                        bool bFind = false;
1198                        for (int j=0; j <nCount;j++)
1199                        {
1200                                if (CRC32[i] != crclist[j]) continue;
1201                                bFind = true;
1202                                break;
1203                        }
1204                        if (bFind == false) CRC32[i] = 0;
1205                }
1206        }
1207};
1208
1209static CheckCRC32 check_crc;
1210
1211static DS_U32 CalcCRC(DS_U8* buff)
1212{
1213        DS_U32 len = (((DS_U32)buff[1]&0x0F) << 8) + (DS_U32)buff[2]-1;
1214        return ((DS_U32)buff[len] << 24) + ((DS_U32)buff[len+1] << 16) + ((DS_U32)buff[len+2] << 8) + (DS_U32)buff[len+3];
1215}
1216
1217static void CT_TunePSIP(DS_U8 RF = 0, DHL_MODULATION_MODE demod = DHL_MODULATION_8VSB, 
1218                        DS_U16 program_number = 0, DS_U16 source_id = 0, bool bOn = false)
1219{
1220        static bool bStart = false;
1221
1222        static DHL_HANDLE hTVCT = 0;
1223        static DHL_HANDLE hCVCT = 0;
1224        static DHL_HANDLE hSTT = 0;
1225        static DHL_HANDLE hMGT = 0;
1226        static DHL_HANDLE hEIT[MAX_EIT_COUNT];
1227        static DHL_HANDLE hETT[MAX_EIT_COUNT];
1228        static DHL_HANDLE hPAT = 0;
1229        static DHL_HANDLE hPMT[MAX_PMT_COUNT];
1230       
1231        static DS_U16 eit_pid[MAX_EIT_COUNT];
1232        static DS_U16 ett_pid[MAX_EIT_COUNT];
1233        static DS_U16 pmt_pid[MAX_PMT_COUNT];
1234        bool g_bReceiveMGT = false;
1235        if (bOn)
1236        {
1237                if (bStart)
1238                {
1239                        CT_SI_Msg msg;
1240                        DS_U32 retLen = 0;
1241                        while (DST_OS_ReceiveMessage_NoWait(gSIMsgQ, (DS_U32*)&msg, sizeof(CT_SI_Msg), &retLen) == noError)
1242                        {
1243                                if (RF == msg.RF) 
1244                                {
1245                                        if (msg.nRequestID == POS_TVCT)
1246                                        {
1247                                                if (CT_ChMapUpdateTVCT(RF, (TVCT*)msg.SI, msg.CRC32)) CT_ChMapUpdate();
1248                                                CT_CallBack(CT_RECEIVE_TVCT, RF);
1249                                        }
1250                                        if (msg.nRequestID == POS_CVCT)
1251                                        {
1252                                                if (CT_ChMapUpdateCVCT(RF, (CVCT*)msg.SI, msg.CRC32)) CT_ChMapUpdate();
1253                                                CT_CallBack(CT_RECEIVE_CVCT, RF);
1254                                        }
1255                                        if (msg.nRequestID == POS_MGT)
1256                                        {
1257                                                g_bReceiveMGT = true;
1258                                                MGT *mgt = (MGT*)msg.SI;
1259                                                DST_Printf("mgt->tables_defined = %d\n", mgt->tables_defined);
1260                                                for(int i = 0 ; i< mgt->tables_defined ; i++)
1261                                                {
1262                                                        DST_Printf("mgt->table[%d].table_type = 0x%X table_type_PID = 0x%X\n", i, mgt->table[i].table_type, mgt->table[i].table_type_PID);
1263                                                        if (mgt->table[i].table_type >= 0x100 && mgt->table[i].table_type <0x100 + MAX_EIT_COUNT)
1264                                                        {
1265                                                                T();
1266                                                                int pos = mgt->table[i].table_type - 0x100;
1267                                                                if (eit_pid[pos] == mgt->table[i].table_type_PID) continue;
1268                                                                eit_pid[pos] = mgt->table[i].table_type_PID;
1269                                                                //DHL_SI_MonitorStop(&hEIT[pos]);
1270                                                                //hEIT[pos] = DHL_SI_MonitorEIT(RF, POS_EIT+pos, eit_pid[pos]);
1271                                                        }
1272                                                        if (mgt->table[i].table_type >= 0x200 && mgt->table[i].table_type <0x200 + MAX_EIT_COUNT)
1273                                                        {
1274                                                                T();
1275                                                                int pos = mgt->table[i].table_type - 0x200;
1276                                                                if (ett_pid[pos] == mgt->table[i].table_type_PID) continue;
1277                                                                ett_pid[pos] = mgt->table[i].table_type_PID;
1278                                                                //DHL_SI_MonitorStop(&hETT[pos]);
1279                                                                //hETT[pos] = DHL_SI_MonitorETT(RF, POS_ETT+pos, ett_pid[pos]);
1280                                                        }
1281                                                }
1282                                                CT_CallBack(CT_RECEIVE_MGT, RF);
1283                                        }
1284                                        if (msg.nRequestID >= POS_EIT && msg.nRequestID < POS_EIT+MAX_EIT_COUNT)
1285                                        {
1286                                                EIT *eit = (EIT*)msg.SI;
1287                                                if (eit->source_id == source_id)
1288                                                {
1289                                                        CT_ChMapUpdateEIT(RF, eit, msg.nRequestID - POS_EIT, msg.CRC32);
1290                                                        CT_CallBack(CT_RECEIVE_EIT, RF);
1291                                                }
1292                                        }
1293                                        if (msg.nRequestID >= POS_ETT && msg.nRequestID < POS_ETT+MAX_EIT_COUNT)
1294                                        {
1295                                                ETT *ett = (ETT*)msg.SI;
1296                                                if ((ett->ETM_id >> 16) == source_id)
1297                                                {
1298                                                        CT_ChMapUpdateETT(RF, ett, msg.CRC32);
1299                                                        CT_CallBack(CT_RECEIVE_ETT, RF);
1300                                                }
1301                                        }
1302                                        if (msg.nRequestID == POS_PAT)
1303                                        {
1304                                                MPEG_PAT *pat = (MPEG_PAT*)msg.SI;
1305                                                CT_ChMapUpdatePAT(RF, pat, msg.CRC32);
1306                                                int nPos = 0;
1307                                                for (int i = 0; i < pat->numPrograms; i++)
1308                                                {
1309                                                        if (pat->programs[i].program_map_PID == 0) continue;
1310                                                        if (pat->programs[i].program_map_PID == 0x1FFF) continue;
1311                                                        if (pmt_pid[nPos] == pat->programs[i].program_map_PID) continue;
1312                                                        if (pmt_pid[nPos]) DHL_SI_MonitorStop(&hPMT[i]);
1313                                                        pmt_pid[nPos] = pat->programs[i].program_map_PID;
1314                                                        hPMT[nPos] = DHL_SI_MonitorPMT(RF, POS_PMT+nPos, pmt_pid[nPos]);
1315                                                        nPos++;
1316                                                        if (nPos >= MAX_PMT_COUNT) break;
1317                                                }
1318                                                CT_CallBack(CT_RECEIVE_PAT, RF);
1319                                        }
1320                                        if (msg.nRequestID >= POS_PMT && msg.nRequestID < POS_PMT+MAX_PMT_COUNT)
1321                                        {
1322                                                MPEG_PMT *pmt = (MPEG_PMT*)msg.SI;
1323                                                if (CT_ChMapUpdatePMT(RF, pmt, msg.nRequestID - POS_PMT+1, msg.CRC32))
1324                                                {
1325                                                        CT_ChMapUpdate();
1326                                                }
1327                                                CT_CallBack(CT_RECEIVE_PMT, RF, pmt->program_number);
1328                                                g_ReceivePMTAudio = true;
1329                                                CT_CallBack(CT_RECEIVE_PMT, RF);
1330                                        }
1331                                }
1332                                DST_FreeAtscTable(&msg.SI); // ¸Þ¸ð¸® ÇØÁ¦´Â ¿©±â¿¡¼­
1333                        } // while
1334                        { // CC µð½ºÅ©¸³ÅÍ ¸ð´ÏÅ͸µ
1335                                static DS_U32 old_RF = 0;
1336                                static DS_U16 old_program_number = 0;
1337                                if (old_RF != RF || old_program_number != program_number || g_bReceiveCCDescriptor == true)
1338                                {
1339                                        old_RF = RF;
1340                                        old_program_number = program_number;
1341                                        g_bReceiveCCDescriptor = false;
1342                                        bool bFind = false;
1343                                        for (int i=0; i < MAX_PMT_CC_TABLE_COUNT; i++)
1344                                        {
1345                                                if (pmt_cc_table[i].rf == (int)RF && pmt_cc_table[i].program_number == program_number && pmt_cc_table[i].cc_type > 0 && pmt_cc_table[i].cc_id == 1) 
1346                                                {
1347                                                        DST_g_CC_bCCKorean = (strcmp(pmt_cc_table[i].language, "kor") != 0 && strcmp(pmt_cc_table[i].language, "KOR") != 0) ? false : true;
1348                                                        DST_g_CC_bWideScreen = pmt_cc_table[i].wide_aspect_ratio ? true : false;
1349                                                        DST_g_CC_bUnicode = pmt_cc_table[i].korean_code ? true : false;
1350                                                        bFind = true;
1351                                                        break;
1352                                                }
1353                                        }
1354                                        if (bFind == false)
1355                                        {
1356                                                DST_g_CC_bCCKorean = true;
1357                                                DST_g_CC_bWideScreen = true;
1358                                                DST_g_CC_bUnicode = false;
1359                                        }
1360                                }
1361                        }
1362                        { // EIT ETT ¸ð´ÏÅ͸µ
1363                                static DS_U8 old_RF = 0;
1364                                static DS_U16 old_source_id = 0;
1365                                if (old_RF != RF || old_source_id != source_id || g_bReceiveMGT == true)
1366                                {
1367                                        old_RF = RF;
1368                                        old_source_id = source_id;
1369                                        for (int i = 0; i < MAX_EIT_COUNT; i++)
1370                                        {
1371                                                DHL_SI_MonitorStop(&hEIT[i]);
1372                                                if (eit_pid[i]) hEIT[i] = DHL_SI_MonitorEIT(RF, POS_EIT+i, eit_pid[i], source_id);
1373                                                DHL_SI_MonitorStop(&hETT[i]);
1374                                                if (ett_pid[i]) hETT[i] = DHL_SI_MonitorETT(RF, POS_ETT+i, ett_pid[i], source_id);
1375                                        }
1376                                }
1377                        }
1378                }
1379                else // bStart == false
1380                {
1381                        CT_TunePSIP();
1382                        bStart = true;
1383                        hTVCT = DHL_SI_MonitorTVCT(RF, POS_TVCT);
1384                        hCVCT = DHL_SI_MonitorCVCT(RF, POS_CVCT);
1385                        hSTT = DHL_SI_MonitorSTT(RF, POS_STT);
1386                        hMGT = DHL_SI_MonitorMGT(RF, POS_MGT);
1387                        hPAT = DHL_SI_MonitorPAT(RF, POS_PAT);
1388                }
1389        }
1390        else
1391        {
1392                if (bStart)
1393                {
1394                        DHL_SI_MonitorStop(&hTVCT);
1395                        DHL_SI_MonitorStop(&hCVCT);
1396                        DHL_SI_MonitorStop(&hSTT);
1397                        DHL_SI_MonitorStop(&hMGT);
1398                        for (int i = 0; i < MAX_EIT_COUNT; i++) 
1399                        {
1400                                DHL_SI_MonitorStop(&hEIT[i]);
1401                                eit_pid[i] = 0;
1402                                DHL_SI_MonitorStop(&hETT[i]);
1403                                ett_pid[i] = 0;
1404                        }
1405                        DHL_SI_MonitorStop(&hPAT);
1406                        for (int i = 0; i < MAX_PMT_COUNT; i++) 
1407                        {
1408                                DHL_SI_MonitorStop(&hPMT[i]);
1409                                pmt_pid[i] = 0;
1410                        }
1411                        CT_SI_Msg msg;
1412                        DS_U32 retLen = 0;
1413                        while (DST_OS_ReceiveMessage_NoWait(gSIMsgQ, (DS_U32*)&msg, sizeof(CT_SI_Msg), &retLen) == noError)
1414                        {
1415                                DST_Printf("Remove msg.nRequestID == %d\n", (int)msg.nRequestID);
1416                                DST_FreeAtscTable(&msg.SI);
1417                        }
1418                        bStart = false;
1419                }
1420        }
1421}
1422
1423static void CT_VideoAudio(DS_U16 pcr = 0, DS_U16 vpid = 0, DS_U8 vtype = 0, DS_U16 apid = 0, DS_U8 atype = 0)
1424{
1425        static DS_U16 _pcr  = 0;
1426        static DS_U16 _vpid  = 0;
1427        static DS_U8  _vtype = 0;
1428        static DS_U16 _apid = 0;
1429        static DS_U8  _atype = 0;
1430        if (pcr == _pcr && vpid == _vpid && vtype == _vtype && apid == _apid && atype == _atype) return;
1431        if (vpid != _vpid)
1432        {
1433                if (vpid)
1434                {
1435                        DHL_VIDEO_TYPE VidStreamType = DHL_VIDEO_NONE;
1436                        switch (vtype) // ABNT NBR 15602-3:2007 Table 5 ? Strem_type
1437                        {
1438                                case 0x01: VidStreamType = DHL_VIDEO_MPEG1; break;
1439                                case 0x02: VidStreamType = DHL_VIDEO_MPEG2; break;
1440                                case 0x1B: VidStreamType = DHL_VIDEO_MPEG4; break;
1441                        };
1442                        DHL_VID_Start(vpid, pcr, VidStreamType);
1443                        DST_g_LastVideoStartTime = DST_OS_GetTickCount();
1444                        _apid = 0; // ºñµð¿À º¯°æ ½Ã ¿Àµð¿Àµµ ´Ù½Ã ½ÃÀÛÇϱâ À§Çؼ­ ÀÌÀü ¿Àµð¿À »óŸ¦ Áö¿î´Ù.
1445                }
1446                else
1447                {
1448                        CT_ChannelChangeVideoMute(true);
1449                        DHL_VID_Stop();
1450                        DST_g_LastVideoStartTime = 0;
1451                }
1452        }
1453        if (apid != _apid)
1454        {
1455                if (apid)
1456                {
1457                        DHL_AUDIO_TYPE AudStreamType = DHL_AUDIO_NONE;
1458                        switch (atype) // ABNT NBR 15602-3:2007 Table 5 ? Strem_type
1459                        {
1460                                case 0x03: AudStreamType = DHL_AUDIO_MPEG1; break;
1461                                case 0x04: AudStreamType = DHL_AUDIO_MPEG2; break;
1462                                case 0x0F: AudStreamType = DHL_AUDIO_AAC_ADTS; break;
1463                                case 0x11: AudStreamType = DHL_AUDIO_AAC_LATM; break;
1464                        };
1465                        DHL_AUD_Start(apid, pcr == 0 ? 0x1FFF : pcr, AudStreamType);
1466                        CT_ChannelChangeAudioMute(false);
1467                        DST_g_LastAudioStartTime = DST_OS_GetTickCount();
1468                }
1469                else
1470                {
1471                        CT_ChannelChangeAudioMute(true);
1472                        DHL_AUD_Stop();
1473                        DST_g_LastAudioStartTime = 0;
1474                }       
1475        }
1476        _pcr  = pcr;
1477        _vpid  = vpid;
1478        _vtype = vtype;
1479        _apid = apid;
1480        _atype = atype;
1481}
1482
1483static void CT_AV(DS_U8 RF = 0, DHL_MODULATION_MODE demod = DHL_MODULATION_8VSB, 
1484                        DS_U16 program_number = 0, DS_U16 source_id = 0, bool bOn = false)
1485{
1486        if (bOn)
1487        {
1488                // ½ÅÈ£ Á¤º¸
1489                bool bLock = false;
1490                int ss = 0;
1491                DHL_TUNE_Info(RF, &ss, &bLock);
1492                CT_CallBack(CT_SIGNAL_INFO, RF, bLock, ss);
1493       
1494                // ¼Ò½º¾ÆÀ̵𿡠µû¶ó AV¸¦ ½ÃÀÛÇÑ´Ù.
1495                DS_U16 PcrPid = 0;
1496                DS_U16 VideoPid = 0;
1497                DS_U8  VideoType = 0;
1498                DS_U16 AudioPid = 0;
1499                DS_U8  AudioType = 0;
1500                CT_DB_GetVideoPid(RF, program_number, &PcrPid, &VideoPid, &VideoType);
1501               
1502                // DST_Printf("VideoPid = %d\n", VideoPid);
1503               
1504                CT_DB_GetAudioPid(RF, program_number, &AudioPid, &AudioType);
1505               
1506                 //DST_Printf("AudioPid = %d\n", AudioPid);
1507               
1508                CT_VideoAudio(PcrPid, VideoPid, VideoType, AudioPid, AudioType);
1509                CT_CallBack(CT_AV_START, RF, program_number,  source_id);
1510                CT_CallBack(CT_AV_INFO, RF, PcrPid, VideoPid, AudioPid, VideoType, AudioType);         
1511                // CC ¸ð´ÏÅ͸µÀ» ½ÃÀÛÇÑ´Ù.
1512               
1513                // AV »óÅ Á¤º¸ Äݹé
1514                CT_CallBack(CT_SIGNAL, RF, program_number, VideoPid ? DHL_VID_Alive() : 0, AudioPid ? DHL_AUD_Alive() : 0);
1515                CT_CallBack(CT_AUDIO_MODE, DHL_AUD_GetMode());
1516                CT_TunePSIP(RF, demod, program_number, source_id, bOn);
1517        }
1518        else
1519        {
1520                CT_TunePSIP(); // PSIP ¸ð´ÏÅ͸µ ÁßÁö
1521                CT_VideoAudio();
1522        }
1523}
1524
1525static void CT_Tune(DS_U8 RF=0, DHL_MODULATION_MODE demod = DHL_MODULATION_8VSB, DS_U16 program_number=0, DS_U16 source_id = 0, bool bOn= false)
1526{
1527        static bool bStart = false;
1528        static DS_U8 CurrentRF = 0;
1529        static DHL_MODULATION_MODE CurrentDemod = DHL_MODULATION_NULL;
1530        if (bOn)
1531        {
1532                if (bStart == false || CurrentRF != RF || CurrentDemod != demod)
1533                {
1534                        CT_AV();
1535                        DHL_TUN_Start(RF, demod);
1536                        DST_g_LastTuneTime = DST_OS_GetTickCount();
1537                        CurrentRF = RF;
1538                        CurrentDemod = demod;
1539                        bStart = true;
1540                }
1541                CT_AV(RF, demod, program_number, source_id, bOn);
1542        }
1543        else
1544        {
1545                CT_AV();
1546                if (bStart)
1547                {
1548                        DST_g_LastTuneTime = 0;
1549                        DHL_TUN_Stop();
1550                        bStart = false;
1551                }
1552        }
1553}
1554
1555struct AirCodeCVT
1556{
1557        DS_U8  vendor_id[3];
1558        DS_U8  hardware_version_id[4];
1559        DS_U8  software_version_id[4];
1560        DS_U8  so_id[2];
1561        DS_U8  download_type; /* 4bits */
1562        DS_U8  download_command; /* 4bits */
1563        DS_U16 frequency_vector; /* 16bits */
1564        DS_U8  modulation_type;
1565        DS_U16 PID;
1566};
1567
1568static bool DST_SCTESI_ParseAirCodeCVT(DS_U8 *p, AirCodeCVT *cvt)
1569{
1570        if (p == 0 || cvt == 0) return false;
1571        if (p[0] != 0x90) return false; // invalid table
1572        memset(cvt, 0, sizeof(AirCodeCVT));
1573        DS_U8 number_of_descriptor = p[8];
1574        int nPos = 9;
1575        DST_Printf("number_of_descriptor = %d", number_of_descriptor);
1576        for (int i = 0; i < number_of_descriptor; i++)
1577        {
1578                DS_U8 tag = p[nPos];
1579                DS_U8 length = p[nPos+1];
1580                DST_Printf("tag = %d\n", tag);
1581                DST_Printf("length = %d\n", length);
1582                switch (tag)
1583                {
1584                        case 0: // vendor_id
1585//                              T();
1586                                if (length == 3) memcpy(cvt->vendor_id, &p[nPos+2], length);
1587                                break;
1588                        case 1: // hardware_version_id
1589//                              T();
1590                                if (length == 4) memcpy(cvt->hardware_version_id, &p[nPos+2], length);
1591                                break;
1592                        case 2: // softeware_version_id
1593//                              T();
1594                                if (length == 4) memcpy(cvt->software_version_id, &p[nPos+2], length);
1595                                break;
1596                        case 0x80:
1597//                              T();
1598                                if (length == 2) memcpy(cvt->so_id, &p[nPos+2], length);
1599                                break;
1600                }
1601                nPos = nPos + length + 2;               
1602        }
1603        cvt->download_type = (p[nPos]&0xF0) >> 4;
1604        cvt->download_command = (p[nPos]&0x0F);
1605        cvt->frequency_vector = p[nPos+1]*256 + p[nPos+2];
1606        cvt->modulation_type = p[nPos+3];
1607        cvt->PID = (p[nPos+4]&0x1F)*256 + p[nPos+5];
1608        return true;
1609}
1610
1611static void CT_SI_Proc(DS_U32 RF, DS_U32 nRequestID, DS_U8** buff, DS_U32 nBuffLength)
1612{
1613//      DST_Printf("%s | RF = %d | nRequestID = %d\n", __func__, (int)RF, (int)nRequestID);
1614        CT_SI_Msg msg;
1615        msg.RF = RF;
1616        msg.nRequestID = nRequestID;
1617        msg.SI = 0;
1618        msg.CRC32 =  CalcCRC(buff[0]);
1619
1620        if (nRequestID == POS_TVCT)
1621        {
1622                if (DHL_PSI_ParseTVCT(buff, (TVCT **)&msg.SI)) DST_Printf("%s|%d|TVCT Parse Error\n", __func__, __LINE__);
1623        }
1624        if (nRequestID == POS_CVCT)
1625        {
1626                if (DHL_PSI_ParseCVCT(buff, (CVCT **)&msg.SI)) DST_Printf("%s|%d|CVCT Parse Error\n", __func__, __LINE__);
1627        }
1628        if (nRequestID == POS_STT)
1629        {
1630                DS_U8* p = buff[0];
1631                CT_CallBack(CT_RECEIVE_STT,  RF, p[9] * 0x1000000 + p[10] * 0x10000 + p[11] * 0x100 + p[12] ,  p[13], DST_OS_GetTickCount());
1632        }
1633        if (nRequestID == POS_MGT)
1634        {
1635                if (DHL_PSI_ParseMGTSection(buff[0], (MGT **)&msg.SI)) DST_Printf("%s|%d|MGT Parse Error\n", __func__, __LINE__);
1636        }
1637        if (nRequestID >= POS_EIT && nRequestID < POS_EIT+MAX_EIT_COUNT)
1638        {
1639                if (DHL_PSI_ParseEIT(buff, (EIT **)&msg.SI)) DST_Printf("%s|%d|EIT Parse Error\n", __func__, __LINE__);
1640        }
1641        if (nRequestID >= POS_ETT && nRequestID < POS_ETT+MAX_EIT_COUNT)
1642        {
1643                if (DHL_PSI_ParseETTSection(buff[0], (ETT **)&msg.SI)) DST_Printf("%s|%d|ETT Parse Error\n", __func__, __LINE__);
1644        }
1645        if (nRequestID == POS_PAT)
1646        {
1647                if (DHL_PSI_ParsePAT(buff, (MPEG_PAT **)&msg.SI)) DST_Printf("%s|%d|PAT Parse Error\n", __func__, __LINE__);
1648        }
1649        if (nRequestID >= POS_PMT && msg.nRequestID < POS_PMT+MAX_PMT_COUNT)
1650        {
1651                if (DHL_PSI_ParsePMT(buff[0], (MPEG_PMT **)&msg.SI)) DST_Printf("%s|%d|PMT Parse Error\n", __func__, __LINE__); 
1652        }
1653        if (nRequestID == POS_RFUPDATE)
1654        {
1655                CT_CallBack(CT_RECEIVE_RF_UPDATE, RF, (DS_U32)buff[0]);
1656        }
1657                if (nRequestID == POS_CVT) // CVT
1658        {
1659//              DST_g_ReceiveCVT++;
1660               
1661                // CMB´Â DDBµ¥ÀÌÅÍ¿¡ ¹Ýº¹µÇ´Â CVT ½Ç·Á¿Â´Ù.
1662                // CVT ÆÄÀÏÀ» °ËÃâÇÏ¿© 0x90À¸·Î ½ÃÀÛÇÏ´Â Å×À̺í·Î º¯È¯ÇÑ´Ù.
1663                // CVT°¡ ¿¬¼ÓÇØ¼­ ¿À±â ¶§¹®¿¡ ¼ö½ÅÇÑ CVT´Â ÀúÀåÇÏ¿© µÎ¾î Áߺ¹ 󸮸¦ ¹æÁöÇÑ´Ù.
1664                static DS_U8 received_cvt[300]; 
1665                DS_U8 cvt_new[300];
1666                DS_U8* p = buff[0];
1667                DS_U16 section_length = (p[1] & 0x0F) * 256 + p[2];
1668                bool bFind = false;
1669                for (int i = 26; i < section_length - 32; i++)  // CVT Å×ÀÌºí ¾ÕÀÇ 26¹ÙÀÌÆ®´Â ´õ¹Ì CVT Å×À̺íÀÇ ÃÖ¼Ò Å©±â´Â 32¹ÙÀÌÆ®
1670                {
1671                        if (p[i] == 0xD9 && p[i+1] == 0x30 && p[i+3] == 0x9F && p[i+4] == 0x9C && p[i+5] == 0x02)
1672                        {
1673                                if (i+p[i+6] > section_length) return; // ÀÔ·ÂµÈ µ¥ÀÌÅͱæÀ̺¸´Ù Å« °æ¿ì ¿¡·¯Ã³¸®
1674                                memset(cvt_new, 0, 300);
1675                                cvt_new[0] = 0x90;
1676                                memcpy(&cvt_new[1], &p[i], p[i+6] + 3);
1677                                if (!memcmp(cvt_new, received_cvt, 300)) return; // ÀÌ¹Ì ¹ÞÀ½
1678                                bFind = true;
1679                                break;
1680                        }
1681                }
1682
1683                if (bFind == false) 
1684                {
1685                        return;
1686                }
1687                static bool bReceiveValidCVT = false;
1688                if (bReceiveValidCVT == true) return;
1689                AirCodeCVT cvt;
1690                memset(&cvt, 0, sizeof(AirCodeCVT));
1691                if (DST_SCTESI_ParseAirCodeCVT(cvt_new, &cvt) == false) return;
1692#if 1
1693                DST_Printf("============================================\n");
1694                DST_Printf("Request ID = POS_CVT\n");
1695                DST_Printf("vendor_id %02X %02X %02X\n", cvt.vendor_id[0], cvt.vendor_id[1], cvt.vendor_id[2]);
1696                DST_Printf("hardware_version_id %02X %02X %02X %02X\n", cvt.hardware_version_id[0], cvt.hardware_version_id[1], cvt.hardware_version_id[2], cvt.hardware_version_id[3]);
1697                DST_Printf("software_version_id %02X %02X %02X %02X\n", cvt.software_version_id[0], cvt.software_version_id[1], cvt.software_version_id[2], cvt.software_version_id[3]);
1698                DST_Printf("so_id %02X %02X\n", cvt.so_id[0], cvt.so_id[1]);
1699                DST_Printf("download_type %d\n", cvt.download_type);
1700                DST_Printf("download_command %d\n", cvt.download_command);
1701                DST_Printf("frequency_vector %d\n", cvt.frequency_vector);
1702                DST_Printf("modulation_type %d\n", cvt.modulation_type);
1703                DST_Printf("PID 0x%X\n", cvt.PID);
1704                DST_Printf("============================================\n");
1705#endif
1706               
1707                // °¢ ÇÊµå °ªÀÇ À¯È¿¼º °Ë»ç             
1708                if (cvt.vendor_id[0] != 'D') return;
1709                if (cvt.vendor_id[1] != 'S') return;
1710                if (cvt.vendor_id[2] != 'T') return;
1711                if (cvt.hardware_version_id[0] != 'Z') return;
1712                if (cvt.hardware_version_id[1] != 'A') return;
1713                if (cvt.hardware_version_id[2] != 'S') return;
1714                if (cvt.hardware_version_id[3] != 'Q') return;
1715//              if (cvt.so_id[0] != DST_g_SO_ID/256) return;
1716//              if (cvt.so_id[1] != DST_g_SO_ID%256) return;
1717               
1718                // º¥´õ¾ÆÀ̵ð¿Í H/W ¹öÀüÀÌ ÀÏÄ¡ÇÏÁö ¾Ê´Â Á¤º¸°¡ °°Àº PID·Î ¿Ã °¡´É¼º ´ëºñÇÏ¿© ¹é¾÷ À§Ä¡´Â H/W ¹öÀü üũ ÀÌÈÄ·Î
1719                memcpy(received_cvt, cvt_new, 300); // »õ·Î ¹ÞÀº µ¥ÀÌÅ͸¦ ¹é¾÷
1720               
1721                int major = 0, minor = DST_GetAppShortVersionNumber(); 
1722                DST_Printf("major = %d minor = %d\n", major, minor);
1723                int new_major = cvt.software_version_id[0]*256+cvt.software_version_id[1];
1724                int new_minor = cvt.software_version_id[2]*256+cvt.software_version_id[3];
1725                DST_Printf("new_major = %d new_minor = %d\n", new_major, new_minor);
1726                if ((major * 0x10000 + minor) >= (new_major * 0x10000 + new_minor))
1727                {
1728                        DST_Printf("Old or Same version. ignore it.\n");
1729                        return;
1730                }
1731                if (cvt.download_command > 2) 
1732                {
1733                        DST_Printf("download_command invalid(%d)\n", cvt.download_command);
1734                        return;
1735                }
1736                if (cvt.frequency_vector == 0)
1737                {
1738                        DST_Printf("frequency_vector invalid(%d)\n", cvt.frequency_vector);
1739                        return;
1740                }
1741                if (cvt.modulation_type < 1 || cvt.modulation_type > 2)
1742                {
1743                        DST_Printf("modulation_type invalid(%d)\n", cvt.modulation_type);
1744                         return;
1745                }
1746                if (cvt.PID == 0) 
1747                {
1748                        DST_Printf("PID invalid(%d)\n", cvt.PID);
1749                        return;
1750                }
1751                bReceiveValidCVT = true;
1752#if 1
1753                switch (cvt.download_command)
1754                {
1755                        case 0: DST_Printf("Download Now\n"); break;
1756                        case 1: DST_Printf("Deferred Download\n"); break;
1757                        case 2: DST_Printf("No Exception\n"); break;
1758                }
1759                DST_Printf("OTC RF = %dHz\n", cvt.frequency_vector * 250000);
1760                switch (cvt.modulation_type)
1761                {
1762                        case 1: DST_Printf("64QAM\n"); break;
1763                        case 2: DST_Printf("256QAM\n"); break;
1764                }
1765#endif
1766                SWinEventMsg event;
1767                memset(&event, 0, sizeof(SWinEventMsg));
1768                event.cmd = WM_CVT;
1769                memcpy(&event.data[0], &cvt.software_version_id[0], 16);
1770                event.data32[4] = cvt.download_command;
1771                event.data32[5] = cvt.modulation_type;
1772                event.data32[6] = cvt.frequency_vector * 250000;
1773                event.data32[7] = cvt.PID;
1774                DST_SendWindowEvent(event);
1775#ifdef DSTAR
1776                DST_g_OTC_Modulation_type = (event.data32[5]==1)?(DHL_MODULATION_64QAM):(DHL_MODULATION_256QAM);
1777                DST_g_OTC_RF = event.data32[6];
1778                DST_g_OTC_PID = event.data32[7];
1779//              DST_OTC_Start();
1780#endif
1781        }
1782        if (nRequestID == POS_OTC_DII) // OTC_DII
1783        {
1784                DST_Printf("################## Request ID = POS_OTC_DII\n");
1785                 // DST_OTC_ParseDsmcc(buff[0]);
1786                DS_U8 *p = buff[0];
1787                if (p[0] != 0x3B) return; // TABLE ID
1788                DS_U16 section_length = ((p[1]&0x0F) * 0x100) + p[2];
1789                if (section_length < 48) return; // SECTION TOO SHORT
1790                if (p[10] != 0x10 || p[11] != 0x02) return; // DSMCC_DM_MSG_DII 0x1002
1791                DS_U8 adaptationLength = p[17];
1792                if (section_length < 48 + adaptationLength) return; // SECTION TOO SHORT
1793                p += adaptationLength; // adaptationLength ±æÀ̸¸Å­ Æ÷ÀÎÅÍ À̵¿
1794                DS_U16 blockSize = p[24] * 0x100 + p[25];
1795                DS_U32 moduleSz = p[42]* 0x1000000 +    p[43]* 0x10000 + p[44]* 0x100 + p[45];
1796                DST_Printf("blockSize = %d moduleSz = %d\n", blockSize, (int)moduleSz);
1797                CT_CallBack(CT_OTC_RECEIVE_DII, moduleSz, blockSize);
1798        }
1799        if (nRequestID == POS_OTC_DDB) // OTC_DDB
1800        {
1801                //DST_Printf("############## Request ID = POS_OTC_DDB\n");
1802                //DST_OTC_ParseDsmcc(buff[0]);
1803                DS_U8 *p = buff[0];
1804                if (p[0] != 0x3C) return; // TABLE ID
1805                //DS_U16 section_length = ((p[1]&0x0F) * 0x100) + p[2];
1806                //if (section_length < 48) return; // SECTION TOO SHORT
1807                if (p[10] != 0x10 || p[11] != 0x03) return; // DSMCC_DM_MSG_DDB 0x1003
1808                DS_U8 adaptationLength = p[17];
1809                //if (section_length < 48 + adaptationLength) return; // SECTION TOO SHORT
1810                p += adaptationLength; // adaptationLength ±æÀ̸¸Å­ Æ÷ÀÎÅÍ À̵¿
1811                DS_U16 blockSize = p[18] * 0x100 + p[19];
1812                DS_U16 blockNumber = p[24]* 0x100 + p[25];
1813                //DST_Printf("blockSize = %d blockNumber = %d\n", blockSize-6, blockNumber);
1814                CT_CallBack(CT_OTC_RECEIVE_DDB, blockNumber, (DS_U32)&p[26], blockSize-6);
1815        }
1816        if (msg.SI) DST_OS_SendMessage(gSIMsgQ, (DS_U32 *)&msg, sizeof(CT_SI_Msg));
1817}
1818
1819
1820// ÇÑ RF¿¡ ´ëÇÑ ¿ÀÅ佺ĵÀÌ ³¡³ª°í ³ª¼­ ´ÙÀ½ ä³Î·Î °¥¶§ ÇöÀç RF¿¡¼­ SI¸¦ ¹Þ¾Ò´ÂÁö ¿©ºÎ¸¦ ÆÇ´ÜÇØ¼­
1821// ä³Î¸ÊÀ» Áö¿ö¾ß ÇÑ´Ù.
1822static bool g_bRemovedOldChannel = false; // PAT/CVCT/TVCT Áß Çϳª¸¦ ¹ÞÀ¸¸é ÀÌÀü ä³ÎÀ» Áö¿î´Ù.
1823bool CT_ScanFindChannel()
1824{
1825        return g_bRemovedOldChannel;
1826}
1827
1828static void CT_ScanPSIP(DS_U8 RF=0, bool bOn=false)
1829{
1830        static bool bStart = false;
1831        static DS_U32 startTick = 0;
1832        static DHL_HANDLE hTVCT = 0;
1833        static DHL_HANDLE hCVCT = 0;
1834        static DHL_HANDLE hPAT = 0;
1835        static DHL_HANDLE hPMT[MAX_PMT_COUNT];
1836        static DS_U16 pmt_pid[MAX_PMT_COUNT];
1837        static int remain_pmt_count = 0;
1838       
1839       
1840        if (bOn)
1841        {
1842                if (bStart)
1843                {
1844                        T();
1845                        CT_SI_Msg msg;
1846                        DS_U32 retLen = 0;
1847                        while (DST_OS_ReceiveMessage_NoWait(gSIMsgQ, (DS_U32*)&msg, sizeof(CT_SI_Msg), &retLen) == noError)
1848                        {
1849                                if (RF == msg.RF) 
1850                                {
1851                                         // PAT/CVCT/TVCT Áß Çϳª¸¦ ¹ÞÀ¸¸é ÀÌÀü ä³ÎÀ» Áö¿î´Ù.
1852                                        if (msg.nRequestID == POS_TVCT || msg.nRequestID == POS_CVCT || msg.nRequestID == POS_PAT)
1853                                        {
1854                                                if (g_bRemovedOldChannel == false)
1855                                                {
1856                                                        T();
1857                                                        T();
1858                                                        T();
1859                                                        T();
1860                                                        JST_DB_Del(RF);
1861                                                        g_bRemovedOldChannel = true;
1862                                                }
1863                                        }
1864                                        if (msg.nRequestID == POS_TVCT)
1865                                        {
1866                                                T();
1867                                                TVCT *tvct = (TVCT*)msg.SI;
1868                                                if (CT_ChMapUpdateTVCT(RF, tvct, msg.CRC32))
1869                                                {
1870                                                        CT_ChMapUpdate();
1871                                                }
1872                                                CT_CallBack(CT_SCAN_RECEIVE_TVCT, msg.RF, (DS_U32)tvct);
1873                                        }
1874                                        if (msg.nRequestID == POS_CVCT)
1875                                        {
1876                                                T();
1877                                                CVCT *cvct = (CVCT*)msg.SI;
1878                                                if (CT_ChMapUpdateCVCT(RF, cvct, msg.CRC32))
1879                                                {
1880                                                        CT_ChMapUpdate();
1881                                                }
1882                                                CT_CallBack(CT_SCAN_RECEIVE_CVCT, msg.RF, (DS_U32)cvct);
1883                                        }
1884                                        if (msg.nRequestID == POS_PAT)
1885                                        {
1886                                                MPEG_PAT *pat = (MPEG_PAT*)msg.SI;
1887                                                if (CT_ChMapUpdatePAT(RF, pat, msg.CRC32)) // PAT°¡ °»½ÅµÇ¾ú´Ù
1888                                                {
1889                                                        // VCT°¡ ÀÖ´ø ä³Î¿¡¼­ VCT°¡ ¾ø´Â ä³Î·Î ½ºÆ®¸²ÀÌ º¯°æµÈ °æ¿ì ¹Ý¿µÇϱâ À§ÇÑ ÄÚµå
1890                                                        // VCT°¡ ¾ø´Â ä³ÎÀϼö ÀÖÀ¸´Ï VCT Á¤º¸¸¦ Áö¿ì°í »õ·Î ¹Þ¾Æº»´Ù.
1891                                                        DHL_SI_MonitorStop(&hTVCT);
1892                                                        DHL_SI_MonitorStop(&hCVCT);
1893                                                        // VCT Á¤º¸¸¦ Á¦°ÅÇÑ´Ù
1894                                                        CDB db;
1895                                                        db.Query("delete from tvct where rf = %d", RF);
1896                                                        db.Query("delete from tvct_sub where rf = %d", RF);
1897                                                        db.Query("delete from cvct where rf = %d", RF);
1898                                                        db.Query("delete from cvct_sub where rf = %d", RF);
1899                                                        // VCT ¸ð´ÏÅ͸µ Àç½ÃÀÛ
1900                                                        hTVCT = DHL_SI_MonitorTVCT(RF, POS_TVCT);
1901                                                        hCVCT = DHL_SI_MonitorCVCT(RF, POS_CVCT);
1902                                                }
1903                                                int nPos = 0;
1904                                                for (int i = 0; i < pat->numPrograms; i++)
1905                                                {
1906                                                        if (pat->programs[i].program_map_PID == 0) continue;
1907                                                        if (pat->programs[i].program_map_PID == 0x1FFF) continue;
1908                                                        if (pmt_pid[nPos] == pat->programs[i].program_map_PID) continue;
1909                                                        if (pmt_pid[nPos]) DHL_SI_MonitorStop(&hPMT[i]);
1910                                                        pmt_pid[nPos] = pat->programs[i].program_map_PID;
1911                                                        hPMT[nPos] = DHL_SI_MonitorPMT(RF, POS_PMT+nPos, pmt_pid[nPos]);
1912                                                        nPos++;
1913                                                        if (nPos >= MAX_PMT_COUNT) break;
1914                                                }
1915                                                remain_pmt_count = nPos;
1916                                        }
1917                                        if (msg.nRequestID >= POS_PMT && msg.nRequestID < POS_PMT+MAX_PMT_COUNT)
1918                                        {
1919                                                MPEG_PMT *pmt = (MPEG_PMT*)msg.SI;
1920                                                if (CT_ChMapUpdatePMT(RF, pmt, msg.nRequestID-POS_PMT+1, msg.CRC32))
1921                                                {
1922                                                        CT_ChMapUpdate();
1923                                                }
1924                                                remain_pmt_count--;
1925                                                CT_CallBack(CT_SCAN_RECEIVE_PMT, RF, pmt->program_number, remain_pmt_count);
1926                                                DST_Printf("remain_pmt_count = %d\n", remain_pmt_count);
1927                                        }
1928                                }
1929                                DST_FreeAtscTable(&msg.SI); // ¸Þ¸ð¸® ÇØÁ¦´Â ¿©±â¿¡¼­
1930                        } // while
1931                        CT_CallBack(CT_SCAN_PSIP_WAIT, RF, (DST_OS_GetTickCount() - startTick) * 1000/DST_OS_GetTicksPerSecond()); // PSIP ¸ðµðÅ͸µ ½ÃÀÛ ÈÄ ¸î msÀÌ Áö³µ´ÂÁö
1932                }
1933                else // bStart == false
1934                {
1935                        T();
1936                        CT_ScanPSIP();
1937                        bStart = true;
1938                        g_bRemovedOldChannel = false; 
1939                        startTick = DST_OS_GetTickCount();
1940                        hTVCT = DHL_SI_MonitorTVCT(RF, POS_TVCT);
1941                        hCVCT = DHL_SI_MonitorCVCT(RF, POS_CVCT);
1942                        hPAT = DHL_SI_MonitorPAT(RF, POS_PAT);
1943                }
1944        }
1945        else
1946        {
1947                if (bStart)
1948                {
1949                        T();
1950                        DHL_SI_MonitorStop(&hTVCT);
1951                        DHL_SI_MonitorStop(&hCVCT);
1952                        DHL_SI_MonitorStop(&hPAT);
1953                        for (int i = 0; i < MAX_PMT_COUNT; i++) 
1954                        {
1955                                DHL_SI_MonitorStop(&hPMT[i]);
1956                                pmt_pid[i] = 0;
1957                        }
1958                        bStart = false;
1959                        g_bRemovedOldChannel = false; 
1960                        startTick = 0;
1961                        CT_SI_Msg msg;
1962                        DS_U32 retLen = 0;
1963                        while (DST_OS_ReceiveMessage_NoWait(gSIMsgQ, (DS_U32*)&msg, sizeof(CT_SI_Msg), &retLen) == noError)
1964                        {
1965                                DST_Printf("Remove msg.nRequestID == %d\n", (int)msg.nRequestID);
1966                                DST_FreeAtscTable(&msg.SI);
1967                        }
1968                }
1969        }
1970}
1971
1972static void CT_Scan(DS_U8 RF=0, bool bOn=false)
1973{
1974        static bool bStart = false;
1975        static DS_U8 CurrentRF = 0;
1976        static DS_U32 startTick = 0;
1977        if (bOn)
1978        {
1979                if (bStart == false || CurrentRF != RF)
1980                {
1981                        CT_ScanPSIP();
1982                        DHL_TUN_Start(RF);
1983                        DST_g_LastTuneTime = DST_OS_GetTickCount();
1984                        CurrentRF = RF;
1985                        //bLock = false;
1986                        bStart = true;
1987                        startTick = DST_OS_GetTickCount();
1988                }
1989                CT_ScanPSIP(RF, bOn);
1990                int ss = 0;
1991                bool bLock = false;
1992                DHL_TUNE_Info(RF, &ss, &bLock);
1993                CT_CallBack(CT_SCAN_LOCK_WAIT, RF, (DST_OS_GetTickCount() - startTick) * 1000/DST_OS_GetTicksPerSecond() , bLock ? ss : 0);
1994        }
1995        else
1996        {
1997                CT_ScanPSIP(); // SCAN PSIP ¸ð´ÏÅ͸µ Ãë¼Ò
1998                if (bStart)
1999                {
2000                        DST_g_LastTuneTime = 0;
2001                        DHL_TUN_Stop();
2002                        bStart = false;
2003                        CurrentRF = 0;
2004                        startTick = 0;
2005                        //bLock = false;
2006                }
2007        }
2008}
2009
2010static void CT_RF_Update(DS_U8 RF=0, DHL_MODULATION_MODE demod = DHL_MODULATION_256QAM,  bool bOn=false)
2011{
2012        static bool bStart = false;
2013        static DHL_HANDLE hRfUpdate = 0;
2014        if (bOn)
2015        {
2016                if (bStart == false)
2017                {
2018                        DHL_TUN_Start(RF, demod);
2019                        hRfUpdate = DHL_SI_MonitorRFUpdate(RF,  POS_RFUPDATE);
2020                        bStart = true;
2021                }
2022                else
2023                {
2024                        // ½ÅÈ£ Á¤º¸
2025                        bool bLock = false;
2026                        int ss = 0;
2027                        DHL_TUNE_Info(RF, &ss, &bLock);
2028                        CT_CallBack(CT_SIGNAL_INFO, RF, bLock, ss);
2029                }
2030        }
2031        else
2032        {
2033                if (bStart == true)
2034                {
2035                        DHL_SI_MonitorStop(&hRfUpdate);
2036                        DHL_TUN_Stop();
2037                        bStart = false;
2038                }
2039        }
2040}
2041
2042// CMB OTC ¸¦ À§ÇØ ¸ÕÀú CVT¸¸ È®ÀÎÇÑ´Ù.
2043static void CT_CVT(DS_U8 RF=0, DHL_MODULATION_MODE demod = DHL_MODULATION_256QAM,  bool bOn=false)
2044{
2045        static bool bStart = false;
2046        static DHL_HANDLE hCVT = 0;
2047        if (bOn)
2048        {
2049                if (bStart == false)
2050                {
2051                        DHL_TUN_Start(RF, demod);
2052                        hCVT = DHL_SI_MonitorSCTE_CVT(RF,  POS_CVT);
2053                        bStart = true;
2054                }
2055                else
2056                {
2057                        // ½ÅÈ£ Á¤º¸
2058                        bool bLock = false;
2059                        int ss = 0;
2060                        DHL_TUNE_Info(RF, &ss, &bLock);
2061                        CT_CallBack(CT_SIGNAL_INFO, RF, bLock, ss);
2062                }
2063        }
2064        else
2065        {
2066                if (bStart == true)
2067                {
2068                        DHL_SI_MonitorStop(&hCVT);
2069                        DHL_TUN_Stop();
2070                        bStart = false;
2071                }
2072        }
2073}
2074
2075static void CT_OTC(DS_U8 RF=0, DHL_MODULATION_MODE demod = DHL_MODULATION_256QAM,  DS_U16 otc_pid = 0, bool bOn=false)
2076{
2077        static bool bStart = false;
2078        static DHL_HANDLE hDII = 0;
2079        static DHL_HANDLE hDDB = 0;
2080        if (bOn)
2081        {
2082                if (bStart == false)
2083                {
2084                        DHL_TUN_Start(RF, demod);
2085                        DST_g_LastTuneTime = DST_OS_GetTickCount();
2086                        //CT_CallBack(CT_OTC_START);
2087                        hDII = DHL_SI_MonitorSCTE_DII(RF,  POS_OTC_DII, otc_pid);
2088                        hDDB = DHL_SI_MonitorSCTE_DDB(RF, POS_OTC_DDB, otc_pid);
2089                        bStart = true;
2090                }
2091                else
2092                {
2093                        // ½ÅÈ£ Á¤º¸
2094                        bool bLock = false;
2095                        int ss = 0;
2096                        DHL_TUNE_Info(RF, &ss, &bLock);
2097                        CT_CallBack(CT_SIGNAL_INFO, RF, bLock, ss);
2098                }
2099        }
2100        else
2101        {
2102                if (bStart == true)
2103                {
2104                        DST_g_LastTuneTime = 0;
2105                        DHL_SI_MonitorStop(&hDII);
2106                        DHL_SI_MonitorStop(&hDDB);
2107                        DHL_TUN_Stop();
2108                        bStart = false;
2109                }
2110        }
2111//      if(DST_OTC_GetStatus() == CD_INBAND_DOWNLOAD)
2112//      {
2113//              if(hDII)
2114//              {
2115//                      DHL_SI_MonitorStop(&hDII);
2116//                      hDII = 0;
2117//              }
2118//              if(hDDB == 0)
2119//              {
2120//                      hDDB = DHL_SI_MonitorSCTE_DDB(RF, POS_OTC_DDB, otc_pid);
2121//              }
2122//      }
2123//      if(DST_OTC_GetStatus() == CD_INBAND_DOWNLOAD_UPDATE)
2124//      {
2125//              if(hDDB)
2126//              {
2127//                      DHL_SI_MonitorStop(&hDDB);
2128//                      hDDB = 0;
2129//              }
2130//      }       
2131}
2132
2133
2134static void CT_VideoFreezeEndProc()
2135{
2136        DST_Printf("DST_VideoFreezeEndProc\n");
2137        CT_ChannelChangeVideoMute(false);
2138}
2139
2140static void CT_SignalInfoCallBack(int nWidth, int nHeight, int RefreshRate, bool bInterlaced,   DHL_SOURCE_ASEPCT Aspect)
2141{
2142        CT_CallBack(CT_VIDEO_RESOLUTION, nWidth, nHeight, RefreshRate, bInterlaced, Aspect);
2143}
2144
2145void DST_708_Callback(DS_U8 *bytearray,int size);
2146void DST_IrCallBack(DS_U32 key, DS_U32 repeat, DS_U32 tick);
2147
2148static void tChannel(void)
2149{
2150        DHL_SYS_TV_Open(CT_SignalInfoCallBack, CT_VideoFreezeEndProc, 0, 
2151                CT_SI_Proc, DST_708_Callback, DST_IrCallBack);
2152        CT_Msg msg = {CMD_NULL, DHL_MODULATION_8VSB, 0,0};
2153        while (1)
2154        {
2155                DS_U32 retLen;
2156                CT_Msg tmp;
2157                bool bChanged = false;
2158                // ½×¿©ÀÖ´Â ¸ðµç ¸Þ½ÃÁö¸¦ °¡Á®¿Â´Ù.
2159                while (DST_OS_ReceiveMessage_Wait(gMsgQ, (DS_U32*)&tmp, sizeof(CT_Msg), &retLen, DST_OS_GetTicksPerSecond()/10) == noError)
2160                {
2161                        DST_Printf("\n\n\n\n\nReceive Cmd = %d RF = %d demod = %d program_number = %d\n\n\n\n\n\n", 
2162                                        tmp.Cmd, tmp.RF, tmp.demod, tmp.program_number);
2163                        if (msg.Cmd != tmp.Cmd || msg.RF != tmp.RF || msg.demod != tmp.demod || msg.program_number != tmp.program_number)
2164                        { 
2165                                msg = tmp;
2166                                bChanged = true;
2167                        }
2168                }
2169                ////DST_Printf("Current Cmd = %d RF = %d Minor = %d Mode = %d\n", msg.Cmd, msg.RF, msg.Minor, msg.Mode);
2170
2171                static DS_U16 program_number = 0;
2172                static DS_U16 source_id = 0;
2173                if (msg.Cmd == CMD_TUNE)
2174                {
2175                        DS_U16 new_program_number = 0;
2176                        DS_U16 new_source_id = 0;
2177                        CDB db;
2178                        if (msg.program_number == 0) // RF Æ©´×ÀÎ °æ¿ì
2179                        {
2180                                db.GetTable("select program_number, source_id from channel_db where rf = %d order by minor", msg.RF);
2181                                if(db.GetRow() > 0) // ù¹øÂ° Minor ä³Î
2182                                {
2183                                        new_program_number = atoi(db.GetResult(2));
2184                                        new_source_id = atoi(db.GetResult(3));
2185                                }
2186                        }
2187                        else
2188                        {
2189                                db.GetTable("select program_number, source_id from channel_db where rf = %d and program_number = %d", msg.RF, msg.program_number);
2190                                if(db.GetRow() > 0)
2191                                {
2192                                        new_program_number = atoi(db.GetResult(2));
2193                                        new_source_id = atoi(db.GetResult(3));
2194                                }
2195                        }
2196                        if (program_number != new_program_number || source_id != new_source_id)
2197                        {
2198                                program_number = new_program_number;
2199                                source_id = new_source_id;
2200                                bChanged = true;
2201                        }
2202                }
2203                else
2204                {
2205                        program_number = 0;
2206                        source_id = 0;
2207                }
2208               
2209
2210
2211                switch (msg.Cmd)
2212                {
2213                        case CMD_NULL:
2214                                break;
2215                        case CMD_TUNE:
2216                                CT_Scan();
2217                                CT_OTC();
2218                                CT_RF_Update();
2219                                CT_CVT();
2220                                CT_Tune(msg.RF, msg.demod, program_number, source_id, true);
2221                                if (bChanged) CT_CallBack(CT_TUNE_START, msg.RF, program_number, source_id);
2222                                CT_AutoScanMute(false);
2223                                break;
2224                        case CMD_SCAN:
2225                                CT_AutoScanMute(true);
2226                                CT_Tune();
2227                                CT_OTC();
2228                                CT_RF_Update();
2229                                CT_CVT();
2230                                CT_Scan(msg.RF, true);
2231                                if (bChanged) CT_CallBack(CT_SCAN_START, msg.RF);
2232                                break;
2233                        case CMD_RF_UPDATE:
2234                                CT_AutoScanMute(true);
2235                                CT_Tune();
2236                                CT_Scan();
2237                                CT_OTC();
2238                                CT_CVT();
2239                                CT_RF_Update(msg.RF, msg.demod, true);
2240                                if (bChanged) CT_CallBack(CT_RF_UPDATE_START, msg.RF);
2241                                break;
2242                       
2243                        case CMD_CVT:
2244                                CT_AutoScanMute(true);
2245                                CT_Tune();
2246                                CT_Scan();
2247                                CT_RF_Update();
2248                                CT_OTC();
2249                                CT_CVT(msg.RF, msg.demod, true);
2250//                              if (bChanged) CT_CallBack(CT_OTC_START, msg.RF);
2251                                break;
2252                               
2253                        case CMD_OTC:
2254                                CT_AutoScanMute(true);
2255                                CT_Tune();
2256                                CT_Scan();
2257                                CT_RF_Update();
2258                                CT_CVT();
2259                                CT_OTC(msg.RF, msg.demod, msg.program_number, true);
2260                                if (bChanged) CT_CallBack(CT_OTC_START, msg.RF, msg.program_number);
2261                                break;
2262                               
2263                        case CMD_OTC_STOP:
2264                                CT_OTC();
2265                                break;
2266                               
2267                        case CMD_STOP:
2268                                CT_Tune();
2269                                CT_Scan();
2270                                CT_OTC();
2271                                CT_RF_Update();
2272                                if (bChanged) CT_CallBack(CT_STOPPED);
2273                                break;
2274                }
2275                if (msg.Cmd == CMD_CLOSE) break;
2276        }
2277        CT_Tune();
2278        CT_Scan();
2279        DHL_SYS_TV_Close();
2280        CT_CallBack(CT_CLOSE, 0, 0, 0, 0);
2281        DST_OS_DeleteMessageQueue(gMsgQ);
2282        DST_OS_DeleteMessageQueue(gSIMsgQ);
2283        gMsgQ = 0;
2284        gSIMsgQ = 0;
2285        DST_DB_Close();
2286        g_callback = 0;
2287}
2288
2289static void CT_Init()
2290{
2291        static int taskID = 0;
2292        // ŽºÅ©¿Í ¸Þ½ÃÁöÅ¥ »ý¼º
2293        if (taskID == 0)
2294        {
2295                gMsgQ = DST_OS_CreateMessageQueue("qChannelTask", 0, 100, sizeof(CT_Msg));
2296                gSIMsgQ = DST_OS_CreateMessageQueue("qChannelTask", 0, 100, sizeof(CT_SI_Msg));
2297                taskID = DST_OS_SpawnTask((void (*)(void *)) tChannel, (char*)"tChannel", APP_TASK_PRIO_CHANNEL, WIN_MGR_TASK_STACKSIZE, 0);
2298        }
2299}
2300
2301// jstack open
2302void JST_Open(jst_callback callcack)
2303{
2304        g_callback = callcack;
2305        CT_Init();
2306}
2307
2308static void JST_SendMsg(int Cmd = CMD_NULL, DS_U32 RF = 0, 
2309                DHL_MODULATION_MODE demod = DHL_MODULATION_8VSB, DS_U16 program_number = 0)
2310{
2311        switch (demod)
2312        {
2313                case    DHL_MODULATION_64QAM:DST_Printf("%s|Cmd = %d|RF=%ld|64QAM|%d\n", __func__, Cmd, RF, program_number);break;
2314                case    DHL_MODULATION_256QAM:DST_Printf("%s|Cmd = %d|RF=%ld|256QAM|%d\n", __func__, Cmd, RF, program_number);break;
2315                case    DHL_MODULATION_8VSB:DST_Printf("%s|Cmd = %d|RF=%ld|8VSB|%d\n", __func__, Cmd, RF, program_number);break;
2316                case    DHL_MODULATION_16VSB:DST_Printf("%s|Cmd = %d|RF=%ld|16VSB|%d\n", __func__, Cmd, RF, program_number);break;
2317                default:
2318                        break;
2319        }
2320        CT_Init();
2321        CT_Msg msg;
2322        msg.Cmd = Cmd;
2323        msg.RF = RF;
2324        msg.demod =  demod;
2325        msg.program_number = program_number;
2326        if (gMsgQ) DST_OS_SendMessage(gMsgQ, (DS_U32 *)&msg, sizeof(CT_Msg));
2327} 
2328
2329// jstack close
2330void JST_Close()
2331{
2332        JST_SendMsg(CMD_CLOSE);
2333}
2334
2335// Channel Task Start
2336void JST_Tune(DS_U8 RF, DHL_MODULATION_MODE demod, DS_U16 program_number)
2337{
2338        JST_SendMsg(CMD_TUNE, RF, demod, program_number);
2339}
2340
2341// Channel Task Start
2342void JST_Scan(DS_U8 RF)
2343{
2344        JST_SendMsg(CMD_SCAN, RF);
2345}
2346
2347void JST_RFUpdate(DS_U8 RF)
2348{
2349        T();
2350        JST_SendMsg(CMD_RF_UPDATE, RF);
2351}
2352
2353void JST_CVT(DS_U8 RF, DHL_MODULATION_MODE demod)
2354{
2355        JST_SendMsg(CMD_CVT, RF, demod);
2356}
2357
2358void JST_OTC(DS_U8 RF, DHL_MODULATION_MODE demod, DS_U16 otc_pid)
2359{
2360        JST_SendMsg(CMD_OTC, RF, DHL_MODULATION_256QAM, otc_pid);
2361}
2362
2363void JST_OTC_STOP()
2364{
2365        JST_SendMsg(CMD_OTC_STOP);
2366}
2367
2368// Channel Task Stop
2369void JST_Stop(void)
2370{
2371        JST_SendMsg(CMD_STOP);
2372}
Note: See TracBrowser for help on using the repository browser.