OSDN Git Service

stop using trunk directory in rectool
[rec10/rec10-git.git] / dist / trunk / tstools / epgdump / eit.c
1 // -*- tab-width:4 -*-
2 // see TR-B14 4-296 (p.318)
3
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8 #include "eit.h"
9
10 char            *subtitle_cnv_str[] = {
11         NULL
12 };
13 static void timecmp(int *,int *,int *,
14                                         int, int, int);
15 void append_desc(EIT_CONTROL* eittop, int service_id, int event_id, EEVTDitem* eevtitem);
16
17 int parseEIThead(unsigned char *data, EIThead *h) {
18         int boff = 0;
19
20         memset(h, 0, sizeof(EIThead));
21
22         h->table_id = getBit(data, &boff, 8);
23         h->section_syntax_indicator = getBit(data, &boff, 1);
24         h->reserved_future_use = getBit(data, &boff, 1);
25         h->reserved1 = getBit(data, &boff, 2);
26         h->section_length =getBit(data, &boff,12);
27         h->service_id = getBit(data, &boff, 16);
28         h->reserved2 = getBit(data, &boff, 2);
29         h->version_number = getBit(data, &boff, 5);
30         h->current_next_indicator = getBit(data, &boff, 1);
31         h->section_number = getBit(data, &boff, 8);
32         h->last_section_number = getBit(data, &boff, 8);
33         h->transport_stream_id = getBit(data, &boff, 16);
34         h->original_network_id = getBit(data, &boff, 16);
35         h->segment_last_section_number = getBit(data, &boff, 8);
36         h->last_table_id = getBit(data, &boff, 8);
37   
38         return 14;
39 }
40
41 int parseEITbody(unsigned char *data, EITbody *b)
42 {
43         int boff = 0;
44         int tnum;
45         char buf[4];
46
47         memset(b, 0, sizeof(EITbody));
48
49         b->event_id = getBit(data, &boff, 16);
50
51         memcpy(b->start_time, data + boff / 8, 5);
52         /* b->start_time = getBit(data, &boff, 40); */
53         boff += 40;
54         memcpy(b->duration, data + boff / 8, 3);
55         /* b->duration = getBit(data, &boff, 24); */
56         boff += 24;
57         b->running_status = getBit(data, &boff, 3);
58         b->free_CA_mode = getBit(data, &boff, 1);
59         b->descriptors_loop_length = getBit(data, &boff, 12);
60
61         /* 日付変換 */
62         tnum = (b->start_time[0] & 0xFF) << 8 | (b->start_time[1] & 0xFF);
63   
64         b->yy = (tnum - 15078.2) / 365.25;
65         b->mm = ((tnum - 14956.1) - (int)(b->yy * 365.25)) / 30.6001;
66         b->dd = (tnum - 14956) - (int)(b->yy * 365.25) - (int)(b->mm * 30.6001);
67
68         if(b->dd == 0) {
69                 printf("aa");
70         }
71
72         if(b->mm == 14 || b->mm == 15) {
73                 b->yy += 1;
74                 b->mm = b->mm - 1 - (1 * 12);
75         } else {
76                 b->mm = b->mm - 1;
77         }
78
79         b->yy += 1900;
80   
81         memset(buf, '\0', sizeof(buf));
82         sprintf(buf, "%x", b->start_time[2]);
83         b->hh = atoi(buf);
84         memset(buf, '\0', sizeof(buf));
85         sprintf(buf, "%x", b->start_time[3]);
86         b->hm = atoi(buf);
87         memset(buf, '\0', sizeof(buf));
88         sprintf(buf, "%x", b->start_time[4]);
89         b->ss = atoi(buf);
90
91         if((b->duration[0] == 0xFF) && (b->duration[1] == 0xFF) && (b->duration[2] == 0xFF)){
92                 b->dhh = b->dhm = b->dss = 0;
93         }else{
94                 memset(buf, '\0', sizeof(buf));
95                 sprintf(buf, "%x", b->duration[0]);
96                 b->dhh = atoi(buf);
97                 memset(buf, '\0', sizeof(buf));
98                 sprintf(buf, "%x", b->duration[1]);
99                 b->dhm = atoi(buf);
100                 memset(buf, '\0', sizeof(buf));
101                 sprintf(buf, "%x", b->duration[2]);
102                 b->dss = atoi(buf);
103         }
104         return 12;
105 }
106
107 int parseSEVTdesc(unsigned char *data, SEVTdesc *desc) {
108         int boff = 0;
109   
110         memset(desc, 0, sizeof(SEVTdesc));
111
112         desc->descriptor_tag = getBit(data, &boff, 8);
113         if((desc->descriptor_tag & 0xFF) != 0x4D) {
114                 return -1;
115         }
116         desc->descriptor_length = getBit(data, &boff, 8);
117         memcpy(desc->ISO_639_language_code, data + boff / 8, 3);
118         /* desc->ISO_639_language_code = getBit(data, &boff, 24); */
119         boff += 24;
120         desc->event_name_length = getBit(data, &boff, 8);
121         getStr(desc->event_name, data, &boff, desc->event_name_length);
122         desc->text_length = getBit(data, &boff, 8);
123         getStr(desc->text, data, &boff, desc->text_length);
124
125         return desc->descriptor_length + 2;
126 }
127
128 int parseContentDesc(unsigned char *data, ContentDesc *desc) {
129         int boff = 0;
130   
131         memset(desc, 0, sizeof(ContentDesc));
132
133         desc->descriptor_tag = getBit(data, &boff, 8);
134         if((desc->descriptor_tag & 0xFF) != 0x54) {
135                 return -1;
136         }
137         desc->descriptor_length = getBit(data, &boff, 8);
138         //memcpy(desc->content, data+(boff/8), desc->descriptor_length);
139         // FIXME: 1つ目のコンテント記述子のみパース
140         desc->content_nibble_level_1 = getBit(data, &boff, 4);
141         desc->content_nibble_level_2 = getBit(data, &boff, 4);
142         desc->user_nibble_1 = getBit(data, &boff, 4);
143         desc->user_nibble_2 = getBit(data, &boff, 4);
144         return desc->descriptor_length + 2;
145 }
146
147 int parseSeriesDesc(unsigned char *data, SeriesDesc *desc) {
148         int boff = 0;
149   
150         memset(desc, 0, sizeof(SeriesDesc));
151
152         desc->descriptor_tag = getBit(data, &boff, 8);
153         if((desc->descriptor_tag & 0xFF) != 0xD5) {
154                 return -1;
155         }
156         desc->descriptor_length = getBit(data, &boff, 8);
157         desc->series_id = getBit(data, &boff, 16);
158         desc->repeat_label = getBit(data, &boff, 4);
159         desc->program_pattern = getBit(data, &boff, 3);
160         desc->expire_date_valid_flag = getBit(data, &boff, 1);
161
162         desc->expire_date = getBit(data, &boff, 16);
163         //memcpy(desc->expire_date, data + boff / 8, 2);
164         //boff += 16;
165
166         desc->episode_number = getBit(data, &boff, 12);
167         desc->last_episode_number = getBit(data, &boff, 12);
168
169         getStr(desc->series_name_char, data, &boff, desc->descriptor_length - 8);
170         return desc->descriptor_length + 2;
171 }
172
173 int parseComponentDesc(unsigned char *data, ComponentDesc *desc) {
174         int boff = 0;
175   
176         memset(desc, 0, sizeof(ComponentDesc));
177
178         desc->descriptor_tag = getBit(data, &boff, 8);
179         if((desc->descriptor_tag & 0xFF) != 0x50) {
180                 return -1;
181         }
182         desc->descriptor_length = getBit(data, &boff, 8);
183         desc->reserved_future_use = getBit(data, &boff, 4);
184         desc->stream_content = getBit(data, &boff, 4);
185         desc->component_type = getBit(data, &boff, 8);
186         desc->component_tag = getBit(data, &boff, 8);
187         memcpy(desc->ISO_639_language_code, data + boff / 8, 3);
188         boff += 24;
189         getStr(desc->text_char, data, &boff, desc->descriptor_length - 6);
190         return desc->descriptor_length + 2;
191 }
192
193 int parseAudioComponentDesc(unsigned char *data, AudioComponentDesc *desc) {
194         int boff = 0;
195   
196         memset(desc, 0, sizeof(AudioComponentDesc));
197
198         desc->descriptor_tag = getBit(data, &boff, 8);
199         if((desc->descriptor_tag & 0xFF) != 0xC4) {
200                 return -1;
201         }
202         desc->descriptor_length = getBit(data, &boff, 8);
203         desc->reserved_future_use_1 = getBit(data, &boff, 4);
204         desc->stream_content = getBit(data, &boff, 4);
205         desc->component_type = getBit(data, &boff, 8);
206         desc->component_tag = getBit(data, &boff, 8);
207         desc->stream_type = getBit(data, &boff, 8);
208         desc->simulcast_group_tag = getBit(data, &boff, 8);
209         desc->ES_multi_lingual_flag = getBit(data, &boff, 1);
210         desc->main_component_flag = getBit(data, &boff, 1);
211         desc->quality_indicator = getBit(data, &boff, 2);
212         desc->sampling_rate = getBit(data, &boff, 3);
213         desc->reserved_future_use_2 = getBit(data, &boff, 1);
214         memcpy(desc->ISO_639_language_code_1, data + boff / 8, 3);
215         boff += 24;
216         memcpy(desc->ISO_639_language_code_2, data + boff / 8, 3);
217         boff += 24;
218         getStr(desc->text_char, data, &boff, desc->descriptor_length - desc->ES_multi_lingual_flag ? 12 : 9);
219         return desc->descriptor_length + 2;
220 }
221
222 char* parseComponentDescType(int componentDescType) {
223         static char str[MAXSECLEN];
224         memset(str, '\0', sizeof(str));
225         char *strpart;
226
227         switch (componentDescType & 0xF0) {
228         case 0x00 :
229                 strpart = "映像480i ";
230                 break;
231         case 0x90 :
232                 strpart = "映像2160p ";
233                 break;
234         case 0xA0 :
235                 strpart = "映像480p ";
236                 break;
237         case 0xB0 :
238                 strpart = "映像1080i ";
239                 break;
240         case 0xC0 :
241                 strpart = "映像720p ";
242                 break;
243         case 0xD0 :
244                 strpart = "映像240p ";
245                 break;
246         case 0xE0 :
247                 strpart = "映像1080p ";
248                 break;
249         default :
250                 strpart = "映像不明 ";
251                 break;
252         }
253         strcat(str, strpart);
254
255         switch (componentDescType & 0x0F) {
256         case 0x01 :
257                 strpart = "アスペクト比4:3";
258                 break;
259         case 0x02 :
260                 strpart = "アスペクト比16:9 パンベクトルあり";
261                 break;
262         case 0x03 :
263                 strpart = "アスペクト比16:9 パンベクトルなし";
264                 break;
265         case 0x04 :
266                 strpart = "アスペクト比 > 16:9";
267                 break;
268         default :
269                 strpart = "アスペクト比不明";
270                 break;
271         }
272         strcat(str, strpart);
273
274         return str;
275 }
276
277 char* parseAudioComponentDescType(int AudiocomponentDescType) {
278         static char str[MAXSECLEN];
279         memset(str, '\0', sizeof(str));
280         char *strpart;
281
282         switch (AudiocomponentDescType) {
283         case 0x01 :
284                 strpart = "音声1/0モード(シングルモノ)";
285                 break;
286         case 0x02 :
287                 strpart = "音声1/0+1/0モード(デュアルモノ)";
288                 break;
289         case 0x03 :
290                 strpart = "音声2/0モード(ステレオ)";
291                 break;
292         case 0x04 :
293                 strpart = "音声2/1モード";
294                 break;
295         case 0x05 :
296                 strpart = "音声3/0モード";
297                 break;
298         case 0x06 :
299                 strpart = "音声2/2モード";
300                 break;
301         case 0x07 :
302                 strpart = "音声3/1モード";
303                 break;
304         case 0x08 :
305                 strpart = "音声3/2モード";
306                 break;
307         case 0x09 :
308                 strpart = "音声3/2+LFEモード(3/2.1モード)";
309                 break;
310         case 0x0A :
311                 strpart = "音声3/3.1モード";
312                 break;
313         case 0x0B :
314                 strpart = "音声2/0/0-2/0/2-0.1モード";
315                 break;
316         case 0x0C :
317                 strpart = "音声5/2.1モード";
318                 break;
319         case 0x0D :
320                 strpart = "音声3/2/2.1モード";
321                 break;
322         case 0x0E :
323                 strpart = "音声2/0/0-3/0/2-0.1モード";
324                 break;
325         case 0x0F :
326                 strpart = "音声0/2/0-3/0/2-0.1モード";
327                 break;
328         case 0x10 :
329                 strpart = "音声2/0/0-3/2/3-0.2モード";
330                 break;
331         case 0x11 :
332                 strpart = "音声3/3/3-5/2/3-3/0/0.2モード";
333                 break;
334         case 0x40 :
335                 strpart = "音声視覚障害者用解説";
336                 break;
337         case 0x41 :
338                 strpart = "音声聴覚障害者用";
339                 break;
340         default :
341                 strpart = "音声不明";
342                 break;
343         }
344         strcat(str, strpart);
345
346         return str;
347 }
348
349 int parseEEVTDhead(unsigned char *data, EEVTDhead *desc) {
350         int boff = 0;
351   
352         memset(desc, 0, sizeof(EEVTDhead));
353
354         desc->descriptor_tag = getBit(data, &boff, 8);
355         if((desc->descriptor_tag & 0xFF) != 0x4E) {
356                 return -1;
357         }
358         desc->descriptor_length = getBit(data, &boff, 8);
359         desc->descriptor_number = getBit(data, &boff, 4);
360         desc->last_descriptor_number = getBit(data, &boff, 4);
361         memcpy(desc->ISO_639_language_code, data + boff / 8, 3);
362         /* desc->ISO_639_language_code = getBit(data, &boff, 24); */
363         boff += 24;
364
365         desc->length_of_items = getBit(data, &boff, 8);
366
367         return 7;
368 }
369
370 int parseEEVTDitem(unsigned char *data, EEVTDitem *desc) {
371         int boff = 0;
372   
373         memset(desc, 0, sizeof(EEVTDitem));
374
375         desc->item_description_length = getBit(data, &boff, 8);
376         memset(desc->item_description, 0, MAXSECLEN);
377         getStr(desc->item_description, data, &boff, desc->item_description_length);
378
379         desc->item_length = getBit(data, &boff, 8);
380         memset(desc->item, 0, MAXSECLEN);
381         memcpy(desc->item, data + (boff / 8), desc->item_length);
382         /* getStr(desc->item, data, &boff, desc->item_length); */
383
384         return desc->item_description_length + desc->item_length + 2;
385 }
386
387 int parseEEVTDtail(unsigned char *data, EEVTDtail *desc) {
388         int boff = 0;
389   
390         memset(desc, 0, sizeof(EEVTDtail));
391
392         desc->text_length = getBit(data, &boff, 8);
393         memset(desc->text, 0, MAXSECLEN);
394         getStr(desc->text, data, &boff, desc->text_length);
395
396         return desc->text_length + 1;
397 }
398
399 int checkEEVTDitem(EEVTDitem *save, EEVTDitem *new, int descriptor_number) {
400
401         EEVTDitem swap;
402         int boff = 0;
403
404         if(new == NULL) {
405                 if(save->item_length != 0) {
406                         swap = *save;
407                         memset(save->item, 0, MAXSECLEN);
408                         getStr(save->item, (unsigned char*)swap.item, &boff, swap.item_length);
409                         return 1;
410                 } else {
411                         return 0;
412                 }
413         }
414
415         if(new->item_description_length == 0) {
416                 /* 続き 保存 */
417                 memcpy(save->item + save->item_length, new->item, new->item_length);
418                 save->item_length += new->item_length;
419                 return 0;
420         } else {
421                 /* ブレーク。saveを印刷対象にする。saveをクリア? */
422                 if(save->item_length != 0) {
423                         /* 退避済みがあり */
424                         swap = *save;
425                         memset(save->item, 0, MAXSECLEN);
426                         getStr(save->item, (unsigned char*)swap.item, &boff, swap.item_length);
427
428                         // swap save new -> swap save new
429                         //         b   c -> ( c)    c   b
430                         swap = *new;
431                         *new = *save;
432                         *save = swap;
433                         save->descriptor_number = descriptor_number;
434                         return 1;
435                 } else {
436                         *save = *new;
437                         save->descriptor_number = descriptor_number;
438                         return 0;
439                 }
440         }
441 }
442 EIT_CONTROL     *searcheit(EIT_CONTROL *top, int servid, int eventid)
443 {
444         EIT_CONTROL     *cur ;
445         cur = top ;
446
447         while(cur != NULL){
448                 if((cur->event_id == eventid) && (cur->servid == servid)){
449                         return cur ;
450                 }
451
452                 cur = cur->next ;
453         }
454         return NULL ;
455 }
456 char    *strstr_eucjp(const char *str, const char *search)
457 {
458         char *pos ;
459         pos = (char *)str ;
460
461         while (*pos != '\0') {
462                 if (*pos == *search) {
463                         if (strncmp(pos, search, strlen(search)) == 0) {
464                                 return pos ;
465                         }
466                 }
467                 if ((unsigned char)*pos == 0x8Fu) {
468                         pos += 3 ;
469                 } else if ((unsigned char)*pos >= 0x80u) {
470                         pos += 2 ;
471                 } else {
472                         pos += 1 ;
473                 }
474         }
475
476         return NULL ;
477 }
478 void    conv_title_subtitle(EIT_CONTROL *eitptr)
479 {
480         int             lp = 0 ;
481 //      size_t  addsize ;
482         char    *ptr ;
483         char    *ptr2 ;
484         char    *newsubtitle ;
485
486         for(lp = 0 ; subtitle_cnv_str[lp] != NULL ; lp++){
487                 ptr = strstr(eitptr->title, subtitle_cnv_str[lp]);
488                 if(ptr == NULL){
489                         continue ;
490                 }
491                 // タイトルがなくならないように
492                 if(ptr == eitptr->title){
493                         continue ;
494                 }
495                 /*
496                 ptr2 = ptr ;
497                 for( ; (unsigned char)*ptr2 == 0x20u ; ptr2++ );
498                 for( ; (unsigned char)*ptr2 == 0xA1u && (unsigned char)*(ptr2+1) == 0xA1u ; ptr2 += 2);
499                 for( ; (unsigned char)*ptr2 == 0x20u ; ptr2++ );
500                 newsubtitle = calloc(1, ((strlen(ptr2) + 2) + (strlen(eitptr->subtitle) + 1)));
501                 memcpy(newsubtitle, ptr2, strlen(ptr2));
502 //              *(newsubtitle+strlen(ptr)) = ' ';
503                 strcat(newsubtitle, "▽");
504                 */
505                 newsubtitle = calloc(1, ((strlen(ptr) + 1) + (strlen(eitptr->subtitle) + 1)));
506                 memcpy(newsubtitle, ptr, strlen(ptr));
507                 newsubtitle[strlen(ptr)] = ' ';
508
509                 *ptr = '\0';
510                 strcat(newsubtitle, eitptr->subtitle);
511                 free(eitptr->subtitle);
512                 eitptr->subtitle = newsubtitle ;
513                 return ;
514         }
515 }
516 void    enqueue(EIT_CONTROL *top, EIT_CONTROL *eitptr)
517 {
518         EIT_CONTROL     *cur ;
519         cur = top ;
520         int             rc ;
521
522         if(top->next == NULL){
523                 top->next = eitptr ;
524                 eitptr->prev = top ;
525                 return ;
526         }
527         cur = top->next ;
528         while(cur != NULL){
529                 rc = memcmp(&cur->yy, &eitptr->yy, (sizeof(int) * 3));
530                 if(rc == 0){
531                         rc = memcmp(&cur->hh, &eitptr->hh, (sizeof(int) * 3));
532                         if(rc == 0){
533                                 free(eitptr->title);
534                                 free(eitptr->subtitle);
535                                 free(eitptr);
536                                 return ;
537                         }
538                         if(rc > 0){
539                                 if(cur->prev != 0){
540                                         cur->prev->next = eitptr ;
541                                         eitptr->prev = cur->prev ;
542                                 }
543                                 cur->prev = eitptr ;
544                                 eitptr->next = cur ;
545                                 conv_title_subtitle(eitptr);
546                                 return ;
547                         }
548                 }
549                 if(rc > 0){
550                         if(cur->prev != 0){
551                                 cur->prev->next = eitptr ;
552                                 eitptr->prev = cur->prev ;
553                         }
554                         cur->prev = eitptr ;
555                         eitptr->next = cur ;
556                         conv_title_subtitle(eitptr);
557                         return ;
558                 }
559                 if(cur->next == NULL){
560                         cur->next = eitptr ;
561                         eitptr->prev = cur ;
562                         conv_title_subtitle(eitptr);
563                         return ;
564                 }
565                 cur = cur->next ;
566         }
567         return ;
568
569 }
570
571 void dumpEIT(unsigned char *ptr, int serv_id, int original_network_id, int transport_stream_id, EIT_CONTROL *eittop)
572 {
573
574         EIThead  eith;
575         EITbody  eitb;
576         SEVTdesc sevtd;
577
578         EEVTDhead eevthead;
579         EEVTDitem eevtitem;
580         EEVTDtail eevttail;
581
582         EEVTDitem save_eevtitem;
583
584         EIT_CONTROL     *cur ;
585         EIT_CONTROL     *curtmp ;
586
587         int len = 0;
588         int loop_len = 0;
589         int loop_blen = 0;
590         int loop_elen = 0;
591
592         int ehh, emm, ess;
593
594         /* EIT */
595         len = parseEIThead(ptr, &eith); 
596
597         ptr += len;
598         loop_len = eith.section_length - (len - 3 + 4); // 3は共通ヘッダ長 4はCRC
599         while(loop_len > 0) {
600                 /* 連続する拡張イベントは、漢字コードが泣き別れして
601                    分割されるようだ。連続かどうかは、item_description_lengthが
602                    設定されているかどうかで判断できるようだ。 */
603                 memset(&save_eevtitem, 0, sizeof(EEVTDitem));
604
605                 len = parseEITbody(ptr, &eitb);
606                 ptr += len;
607                 loop_len -= len;
608
609                 /* printf("evtid:%d\n", eitb.event_id); */
610
611                 loop_blen = eitb.descriptors_loop_length;
612                 loop_len -= loop_blen;
613
614                 while(loop_blen > 0) {
615
616                         /*yukikaze-test*/
617                         //printf("desc_tag");
618                         //int itt=getBit(*ptr,0,8);
619                         //printf("%x",itt);
620
621                         len = parseSEVTdesc(ptr, &sevtd);
622                         if(len > 0) {
623
624                                 /*
625                                   if(eith.service_id == 19304 && 
626                                   eitb.event_id == 46564) {
627                                   printf("aa");
628                                   }
629                                 */
630
631                                 ehh = eitb.hh;
632                                 emm = eitb.hm;
633                                 ess = eitb.ss;
634                                 if(eith.service_id != serv_id){
635                                         ptr += len;
636                                         loop_blen -= len;
637                                         continue ;
638                                 }
639
640                                 timecmp(&ehh, &emm, &ess,
641                                                 eitb.dhh, eitb.dhm, eitb.dss);
642                                 cur = searcheit(eittop, eith.service_id, eitb.event_id);
643                                 if(cur == NULL){
644                                         curtmp = NULL;
645                                         cur = calloc(1, sizeof(EIT_CONTROL));
646                                 }
647                                 else {
648                                         curtmp = cur;
649                                 }
650                                 cur->event_id = eitb.event_id ;
651                                 cur->servid = eith.service_id ;
652                                 cur->title = calloc(1, (strlen(sevtd.event_name) + 1));
653
654                                 memcpy(cur->title, sevtd.event_name, strlen(sevtd.event_name));
655                                 cur->subtitle = calloc(1, (strlen(sevtd.text) + 1));
656                                 memcpy(cur->subtitle, sevtd.text, strlen(sevtd.text));
657                                 cur->yy = eitb.yy;
658                                 cur->mm = eitb.mm;
659                                 cur->dd = eitb.dd;
660                                 cur->hh = eitb.hh;
661                                 cur->hm = eitb.hm;
662                                 cur->ss = eitb.ss;
663                                 cur->ehh = eitb.dhh;
664                                 cur->emm = eitb.dhm;
665                                 cur->ess = eitb.dss ;
666                                 cur->table_id = eith.table_id ;
667                                 if ( !curtmp ) enqueue(eittop, cur);
668                         } else {
669                                 len = parseEEVTDhead(ptr, &eevthead);
670
671                                 /*
672                                 if(eith.service_id == 19304 && 
673                                 eitb.event_id == 46564) {
674                                 printf("aa");
675                                 }
676                                 */
677
678                                 if(len > 0) {
679                                         ptr += len;
680                                         loop_blen -= len;
681
682                                         loop_elen = eevthead.length_of_items;
683                                         loop_len -= loop_elen;
684                                         while(loop_elen > 0) {
685                                                 len = parseEEVTDitem(ptr, &eevtitem);
686
687                                                 ptr += len;
688                                                 loop_elen -= len;
689                                                 loop_blen -= len;
690
691                                                 if(checkEEVTDitem(&save_eevtitem, &eevtitem, 
692                                                         eevthead.descriptor_number)) {
693
694                                                         {
695                                                                 if (eevtitem.descriptor_number>0){
696                                                                         //printf("descriptor_num %d\n",eevtitem.descriptor_number);
697                                                                 }
698                                                                 /* long format */
699                                                                 //printf("descriptor_num %d\n",eevtitem.descriptor_number);
700 #if 0
701                                                                 printf("EEVT,%d,%d,%d,%s,%s\n",
702                                                                         eith.service_id,
703                                                                         eitb.event_id,
704                                                                         eevtitem.descriptor_number, // 退避項目
705                                                                         eevtitem.item_description,
706                                                                         eevtitem.item);
707 #endif
708                                                         }
709                                                         append_desc(eittop, eith.service_id, eitb.event_id, &eevtitem);
710
711                                                 }
712                                         }
713
714                                         len = parseEEVTDtail(ptr, &eevttail);
715 #if 0
716                                         { /* long format */
717                                                 printf("EEVTt,%d,%d,%d,%s\n", 
718                                                                 eith.service_id,
719                                                                 eitb.event_id,
720                                                                 eevthead.descriptor_number,
721                                                                 eevttail.text);
722                                         }
723 #endif
724                                 } else {
725                                         ContentDesc                     contentDesc;
726                                         SeriesDesc                      seriesDesc;
727                                         ComponentDesc           componentDesc;
728                                         AudioComponentDesc      audioComponentDesc;
729
730                                         if((eith.original_network_id == original_network_id) && (eith.transport_stream_id == transport_stream_id)){
731                                                 cur = searcheit(eittop, eith.service_id, eitb.event_id);
732                                         }
733                                         else {
734                                                 cur = NULL;
735                                         }
736
737                                         switch (*ptr) {
738                                         case 0x54 :
739                                                 len = parseContentDesc(ptr, &contentDesc);
740                                                 if (len > 0) {
741                                                         if(cur != NULL){
742                                                                 cur->content_type = (unsigned char)contentDesc.content_nibble_level_1;
743                                                         }
744                                                 }
745                                                 break;
746                                         case 0xD5 :
747                                                 len = parseSeriesDesc(ptr, &seriesDesc);
748                                                 if (len > 0) {
749                                                         #if 0
750                                                                 printf("Series,%d,%d,series=%d,repeat=%01x,pattern=%d,expire_valid=%d,expire=%04x,epinum=%d,lastepinum=%d,%s\n",
751                                                                         eith.service_id,
752                                                                         eitb.event_id,
753                                                                         seriesDesc.series_id,
754                                                                         seriesDesc.repeat_label,
755                                                                         seriesDesc.program_pattern,
756                                                                         seriesDesc.expire_date_valid_flag,
757                                                                         seriesDesc.expire_date,
758                                                                         seriesDesc.episode_number,
759                                                                         seriesDesc.last_episode_number,
760                                                                         seriesDesc.series_name_char);
761                                                         #endif
762                                                 }
763                                                 break;
764                                         case 0x50 :
765                                                 len = parseComponentDesc(ptr, &componentDesc);
766                                                 if (len > 0) {
767                                                         if(cur != NULL){
768                                                                 cur->video_type = componentDesc.component_type;
769                                                         }
770                                                         #if 0
771                                                         printf("Component,%d %d %s\n",
772                                                                 componentDesc.stream_content, 
773                                                                 componentDesc.component_type, 
774                                                                 parseComponentDescType(componentDesc.component_type));
775                                                         #endif
776                                                 }
777                                                 break;
778                                         case 0xC4 :
779                                                 len = parseAudioComponentDesc(ptr, &audioComponentDesc);
780                                                 if (len > 0) {
781                                                         if(cur != NULL){
782                                                                 cur->audio_type = audioComponentDesc.component_type;
783                                                                 cur->multi_type = audioComponentDesc.ES_multi_lingual_flag;
784                                                         }
785                                                         #if 0
786                                                         printf("AudioComponent,%d %d %d %s\n",
787                                                                 audioComponentDesc.component_type, 
788                                                                 audioComponentDesc.ES_multi_lingual_flag, 
789                                                                 audioComponentDesc.sampling_rate, 
790                                                                 parseAudioComponentDescType(audioComponentDesc.component_type)
791                                                                 );
792                                                         #endif
793                                                 }
794                                                 break;
795                                         default :
796                                                 len = parseOTHERdesc(ptr);
797                                         }
798                                 }
799                         }
800                         ptr += len;
801                         loop_blen -= len;
802                 }
803                 /* 最後のブレークチェック */
804
805                 if(checkEEVTDitem(&save_eevtitem, NULL, 0)) {
806 #if 0
807                         { /* long format */
808                                 fprintf(stdout, "EEVT,%d,%d,%d,%s,%s\n", 
809                                                 eith.service_id,
810                                                 eitb.event_id,
811                                                 save_eevtitem.descriptor_number,
812                                                 save_eevtitem.item_description,
813                                                 save_eevtitem.item);
814                         }
815 #endif
816                         append_desc(eittop, eith.service_id, eitb.event_id, &save_eevtitem);
817                 }
818         }
819
820         return;
821 }
822
823 void append_desc(EIT_CONTROL* eittop, int service_id, int event_id, EEVTDitem* eevtitem) {
824         EIT_CONTROL *cur;
825         int str_alen = 0;
826
827         cur = searcheit(eittop, service_id, event_id);
828         if (cur == NULL) {
829                 return;
830         }
831
832         if ( cur->desc ) {
833                 str_alen = strlen( cur->desc );
834         }
835         else {
836                 str_alen = 0;
837         }
838         //eevtitem->item_description_length = strlen(eevtitem->item_description);
839         //eevtitem->item_length = strlen(eevtitem->item);
840         cur->desc = realloc(cur->desc, str_alen + eevtitem->item_description_length + eevtitem->item_length + 1000);
841         if ( !str_alen ) *cur->desc = '\0';
842
843         if ( eevtitem->item_description_length && !strstr(cur->desc, eevtitem->item_description) ) {
844                 strcat(cur->desc + str_alen, eevtitem->item_description);
845                 strcat(cur->desc, "\t");
846         }
847
848         if ( eevtitem->item_length && !strstr(cur->desc, eevtitem->item) ) {
849                 strcat(cur->desc + str_alen, eevtitem->item);
850         //printf("%s\n",eevtitem->item);
851                 strcat(cur->desc, "\\n");
852         }
853 }
854
855 void timecmp(int *thh, int *tmm, int *tss,
856                          int dhh, int dmm, int dss) {
857
858         int ama;
859
860         *tss += dss;
861         ama = *tss % 60;
862         *tmm += (*tss / 60);
863         *tss = ama;
864
865         *tmm += dmm;
866         ama   = *tmm % 60;
867         *thh += (*tmm / 60);
868         *tmm  = ama;
869
870         *thh += dhh;
871
872 }