2 // see TR-B14 4-296 (p.318)
10 char *subtitle_cnv_str[] = {
13 static void timecmp(int *,int *,int *,
15 void append_desc(EIT_CONTROL* eittop, int service_id, int event_id, EEVTDitem* eevtitem);
17 int parseEIThead(unsigned char *data, EIThead *h) {
20 memset(h, 0, sizeof(EIThead));
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);
41 int parseEITbody(unsigned char *data, EITbody *b)
47 memset(b, 0, sizeof(EITbody));
49 b->event_id = getBit(data, &boff, 16);
51 memcpy(b->start_time, data + boff / 8, 5);
52 /* b->start_time = getBit(data, &boff, 40); */
54 memcpy(b->duration, data + boff / 8, 3);
55 /* b->duration = getBit(data, &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);
62 tnum = (b->start_time[0] & 0xFF) << 8 | (b->start_time[1] & 0xFF);
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);
72 if(b->mm == 14 || b->mm == 15) {
74 b->mm = b->mm - 1 - (1 * 12);
81 memset(buf, '\0', sizeof(buf));
82 sprintf(buf, "%x", b->start_time[2]);
84 memset(buf, '\0', sizeof(buf));
85 sprintf(buf, "%x", b->start_time[3]);
87 memset(buf, '\0', sizeof(buf));
88 sprintf(buf, "%x", b->start_time[4]);
91 if((b->duration[0] == 0xFF) && (b->duration[1] == 0xFF) && (b->duration[2] == 0xFF)){
92 b->dhh = b->dhm = b->dss = 0;
94 memset(buf, '\0', sizeof(buf));
95 sprintf(buf, "%x", b->duration[0]);
97 memset(buf, '\0', sizeof(buf));
98 sprintf(buf, "%x", b->duration[1]);
100 memset(buf, '\0', sizeof(buf));
101 sprintf(buf, "%x", b->duration[2]);
107 int parseSEVTdesc(unsigned char *data, SEVTdesc *desc) {
110 memset(desc, 0, sizeof(SEVTdesc));
112 desc->descriptor_tag = getBit(data, &boff, 8);
113 if((desc->descriptor_tag & 0xFF) != 0x4D) {
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); */
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);
125 return desc->descriptor_length + 2;
128 int parseContentDesc(unsigned char *data, ContentDesc *desc) {
131 memset(desc, 0, sizeof(ContentDesc));
133 desc->descriptor_tag = getBit(data, &boff, 8);
134 if((desc->descriptor_tag & 0xFF) != 0x54) {
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;
147 int parseSeriesDesc(unsigned char *data, SeriesDesc *desc) {
150 memset(desc, 0, sizeof(SeriesDesc));
152 desc->descriptor_tag = getBit(data, &boff, 8);
153 if((desc->descriptor_tag & 0xFF) != 0xD5) {
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);
162 desc->expire_date = getBit(data, &boff, 16);
163 //memcpy(desc->expire_date, data + boff / 8, 2);
166 desc->episode_number = getBit(data, &boff, 12);
167 desc->last_episode_number = getBit(data, &boff, 12);
169 getStr(desc->series_name_char, data, &boff, desc->descriptor_length - 8);
170 return desc->descriptor_length + 2;
173 int parseComponentDesc(unsigned char *data, ComponentDesc *desc) {
176 memset(desc, 0, sizeof(ComponentDesc));
178 desc->descriptor_tag = getBit(data, &boff, 8);
179 if((desc->descriptor_tag & 0xFF) != 0x50) {
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);
189 getStr(desc->text_char, data, &boff, desc->descriptor_length - 6);
190 return desc->descriptor_length + 2;
193 int parseAudioComponentDesc(unsigned char *data, AudioComponentDesc *desc) {
196 memset(desc, 0, sizeof(AudioComponentDesc));
198 desc->descriptor_tag = getBit(data, &boff, 8);
199 if((desc->descriptor_tag & 0xFF) != 0xC4) {
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);
216 memcpy(desc->ISO_639_language_code_2, data + boff / 8, 3);
218 getStr(desc->text_char, data, &boff, desc->descriptor_length - desc->ES_multi_lingual_flag ? 12 : 9);
219 return desc->descriptor_length + 2;
222 char* parseComponentDescType(int componentDescType) {
223 static char str[MAXSECLEN];
224 memset(str, '\0', sizeof(str));
227 switch (componentDescType & 0xF0) {
232 strpart = "映像2160p ";
238 strpart = "映像1080i ";
247 strpart = "映像1080p ";
253 strcat(str, strpart);
255 switch (componentDescType & 0x0F) {
257 strpart = "アスペクト比4:3";
260 strpart = "アスペクト比16:9 パンベクトルあり";
263 strpart = "アスペクト比16:9 パンベクトルなし";
266 strpart = "アスペクト比 > 16:9";
269 strpart = "アスペクト比不明";
272 strcat(str, strpart);
277 char* parseAudioComponentDescType(int AudiocomponentDescType) {
278 static char str[MAXSECLEN];
279 memset(str, '\0', sizeof(str));
282 switch (AudiocomponentDescType) {
284 strpart = "音声1/0モード(シングルモノ)";
287 strpart = "音声1/0+1/0モード(デュアルモノ)";
290 strpart = "音声2/0モード(ステレオ)";
293 strpart = "音声2/1モード";
296 strpart = "音声3/0モード";
299 strpart = "音声2/2モード";
302 strpart = "音声3/1モード";
305 strpart = "音声3/2モード";
308 strpart = "音声3/2+LFEモード(3/2.1モード)";
311 strpart = "音声3/3.1モード";
314 strpart = "音声2/0/0-2/0/2-0.1モード";
317 strpart = "音声5/2.1モード";
320 strpart = "音声3/2/2.1モード";
323 strpart = "音声2/0/0-3/0/2-0.1モード";
326 strpart = "音声0/2/0-3/0/2-0.1モード";
329 strpart = "音声2/0/0-3/2/3-0.2モード";
332 strpart = "音声3/3/3-5/2/3-3/0/0.2モード";
335 strpart = "音声視覚障害者用解説";
338 strpart = "音声聴覚障害者用";
344 strcat(str, strpart);
349 int parseEEVTDhead(unsigned char *data, EEVTDhead *desc) {
352 memset(desc, 0, sizeof(EEVTDhead));
354 desc->descriptor_tag = getBit(data, &boff, 8);
355 if((desc->descriptor_tag & 0xFF) != 0x4E) {
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); */
365 desc->length_of_items = getBit(data, &boff, 8);
370 int parseEEVTDitem(unsigned char *data, EEVTDitem *desc) {
373 memset(desc, 0, sizeof(EEVTDitem));
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);
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); */
384 return desc->item_description_length + desc->item_length + 2;
387 int parseEEVTDtail(unsigned char *data, EEVTDtail *desc) {
390 memset(desc, 0, sizeof(EEVTDtail));
392 desc->text_length = getBit(data, &boff, 8);
393 memset(desc->text, 0, MAXSECLEN);
394 getStr(desc->text, data, &boff, desc->text_length);
396 return desc->text_length + 1;
399 int checkEEVTDitem(EEVTDitem *save, EEVTDitem *new, int descriptor_number) {
405 if(save->item_length != 0) {
407 memset(save->item, 0, MAXSECLEN);
408 getStr(save->item, (unsigned char*)swap.item, &boff, swap.item_length);
415 if(new->item_description_length == 0) {
417 memcpy(save->item + save->item_length, new->item, new->item_length);
418 save->item_length += new->item_length;
421 /* ブレーク。saveを印刷対象にする。saveをクリア? */
422 if(save->item_length != 0) {
425 memset(save->item, 0, MAXSECLEN);
426 getStr(save->item, (unsigned char*)swap.item, &boff, swap.item_length);
428 // swap save new -> swap save new
433 save->descriptor_number = descriptor_number;
437 save->descriptor_number = descriptor_number;
442 EIT_CONTROL *searcheit(EIT_CONTROL *top, int servid, int eventid)
448 if((cur->event_id == eventid) && (cur->servid == servid)){
456 char *strstr_eucjp(const char *str, const char *search)
461 while (*pos != '\0') {
462 if (*pos == *search) {
463 if (strncmp(pos, search, strlen(search)) == 0) {
467 if ((unsigned char)*pos == 0x8Fu) {
469 } else if ((unsigned char)*pos >= 0x80u) {
478 void conv_title_subtitle(EIT_CONTROL *eitptr)
486 for(lp = 0 ; subtitle_cnv_str[lp] != NULL ; lp++){
487 ptr = strstr(eitptr->title, subtitle_cnv_str[lp]);
492 if(ptr == eitptr->title){
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, "▽");
505 newsubtitle = calloc(1, ((strlen(ptr) + 1) + (strlen(eitptr->subtitle) + 1)));
506 memcpy(newsubtitle, ptr, strlen(ptr));
507 newsubtitle[strlen(ptr)] = ' ';
510 strcat(newsubtitle, eitptr->subtitle);
511 free(eitptr->subtitle);
512 eitptr->subtitle = newsubtitle ;
516 void enqueue(EIT_CONTROL *top, EIT_CONTROL *eitptr)
522 if(top->next == NULL){
529 rc = memcmp(&cur->yy, &eitptr->yy, (sizeof(int) * 3));
531 rc = memcmp(&cur->hh, &eitptr->hh, (sizeof(int) * 3));
534 free(eitptr->subtitle);
540 cur->prev->next = eitptr ;
541 eitptr->prev = cur->prev ;
545 conv_title_subtitle(eitptr);
551 cur->prev->next = eitptr ;
552 eitptr->prev = cur->prev ;
556 conv_title_subtitle(eitptr);
559 if(cur->next == NULL){
562 conv_title_subtitle(eitptr);
571 void dumpEIT(unsigned char *ptr, int serv_id, int original_network_id, int transport_stream_id, EIT_CONTROL *eittop)
582 EEVTDitem save_eevtitem;
585 EIT_CONTROL *curtmp ;
595 len = parseEIThead(ptr, &eith);
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));
605 len = parseEITbody(ptr, &eitb);
609 /* printf("evtid:%d\n", eitb.event_id); */
611 loop_blen = eitb.descriptors_loop_length;
612 loop_len -= loop_blen;
614 while(loop_blen > 0) {
617 //printf("desc_tag");
618 //int itt=getBit(*ptr,0,8);
621 len = parseSEVTdesc(ptr, &sevtd);
625 if(eith.service_id == 19304 &&
626 eitb.event_id == 46564) {
634 if(eith.service_id != serv_id){
640 timecmp(&ehh, &emm, &ess,
641 eitb.dhh, eitb.dhm, eitb.dss);
642 cur = searcheit(eittop, eith.service_id, eitb.event_id);
645 cur = calloc(1, sizeof(EIT_CONTROL));
650 cur->event_id = eitb.event_id ;
651 cur->servid = eith.service_id ;
652 cur->title = calloc(1, (strlen(sevtd.event_name) + 1));
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));
665 cur->ess = eitb.dss ;
666 cur->table_id = eith.table_id ;
667 if ( !curtmp ) enqueue(eittop, cur);
669 len = parseEEVTDhead(ptr, &eevthead);
672 if(eith.service_id == 19304 &&
673 eitb.event_id == 46564) {
682 loop_elen = eevthead.length_of_items;
683 loop_len -= loop_elen;
684 while(loop_elen > 0) {
685 len = parseEEVTDitem(ptr, &eevtitem);
691 if(checkEEVTDitem(&save_eevtitem, &eevtitem,
692 eevthead.descriptor_number)) {
695 if (eevtitem.descriptor_number>0){
696 //printf("descriptor_num %d\n",eevtitem.descriptor_number);
699 //printf("descriptor_num %d\n",eevtitem.descriptor_number);
701 printf("EEVT,%d,%d,%d,%s,%s\n",
704 eevtitem.descriptor_number, // 退避項目
705 eevtitem.item_description,
709 append_desc(eittop, eith.service_id, eitb.event_id, &eevtitem);
714 len = parseEEVTDtail(ptr, &eevttail);
717 printf("EEVTt,%d,%d,%d,%s\n",
720 eevthead.descriptor_number,
725 ContentDesc contentDesc;
726 SeriesDesc seriesDesc;
727 ComponentDesc componentDesc;
728 AudioComponentDesc audioComponentDesc;
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);
739 len = parseContentDesc(ptr, &contentDesc);
742 cur->content_type = (unsigned char)contentDesc.content_nibble_level_1;
747 len = parseSeriesDesc(ptr, &seriesDesc);
750 printf("Series,%d,%d,series=%d,repeat=%01x,pattern=%d,expire_valid=%d,expire=%04x,epinum=%d,lastepinum=%d,%s\n",
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);
765 len = parseComponentDesc(ptr, &componentDesc);
768 cur->video_type = componentDesc.component_type;
771 printf("Component,%d %d %s\n",
772 componentDesc.stream_content,
773 componentDesc.component_type,
774 parseComponentDescType(componentDesc.component_type));
779 len = parseAudioComponentDesc(ptr, &audioComponentDesc);
782 cur->audio_type = audioComponentDesc.component_type;
783 cur->multi_type = audioComponentDesc.ES_multi_lingual_flag;
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)
796 len = parseOTHERdesc(ptr);
805 if(checkEEVTDitem(&save_eevtitem, NULL, 0)) {
808 fprintf(stdout, "EEVT,%d,%d,%d,%s,%s\n",
811 save_eevtitem.descriptor_number,
812 save_eevtitem.item_description,
816 append_desc(eittop, eith.service_id, eitb.event_id, &save_eevtitem);
823 void append_desc(EIT_CONTROL* eittop, int service_id, int event_id, EEVTDitem* eevtitem) {
827 cur = searcheit(eittop, service_id, event_id);
833 str_alen = strlen( cur->desc );
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';
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");
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");
855 void timecmp(int *thh, int *tmm, int *tss,
856 int dhh, int dmm, int dss) {