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 /* getStr(desc->content, data, &boff, desc->descriptor_length); */
140 return desc->descriptor_length + 2;
143 int parseSeriesDesc(unsigned char *data, SeriesDesc *desc) {
146 memset(desc, 0, sizeof(SeriesDesc));
148 desc->descriptor_tag = getBit(data, &boff, 8);
149 if((desc->descriptor_tag & 0xFF) != 0xD5) {
152 desc->descriptor_length = getBit(data, &boff, 8);
153 desc->series_id = getBit(data, &boff, 16);
154 desc->repeat_label = getBit(data, &boff, 4);
155 desc->program_pattern = getBit(data, &boff, 3);
156 desc->expire_date_valid_flag = getBit(data, &boff, 1);
158 desc->expire_date = getBit(data, &boff, 16);
159 //memcpy(desc->expire_date, data + boff / 8, 2);
162 desc->episode_number = getBit(data, &boff, 12);
163 desc->last_episode_number = getBit(data, &boff, 12);
165 getStr(desc->series_name_char, data, &boff, desc->descriptor_length - 8);
166 return desc->descriptor_length + 2;
169 int parseEEVTDhead(unsigned char *data, EEVTDhead *desc) {
172 memset(desc, 0, sizeof(EEVTDhead));
174 desc->descriptor_tag = getBit(data, &boff, 8);
175 if((desc->descriptor_tag & 0xFF) != 0x4E) {
178 desc->descriptor_length = getBit(data, &boff, 8);
179 desc->descriptor_number = getBit(data, &boff, 4);
180 desc->last_descriptor_number = getBit(data, &boff, 4);
181 memcpy(desc->ISO_639_language_code, data + boff / 8, 3);
182 /* desc->ISO_639_language_code = getBit(data, &boff, 24); */
185 desc->length_of_items = getBit(data, &boff, 8);
190 int parseEEVTDitem(unsigned char *data, EEVTDitem *desc) {
193 memset(desc, 0, sizeof(EEVTDitem));
195 desc->item_description_length = getBit(data, &boff, 8);
196 memset(desc->item_description, 0, MAXSECLEN);
197 getStr(desc->item_description, data, &boff, desc->item_description_length);
199 desc->item_length = getBit(data, &boff, 8);
200 memset(desc->item, 0, MAXSECLEN);
201 memcpy(desc->item, data + (boff / 8), desc->item_length);
202 /* getStr(desc->item, data, &boff, desc->item_length); */
204 return desc->item_description_length + desc->item_length + 2;
207 int parseEEVTDtail(unsigned char *data, EEVTDtail *desc) {
210 memset(desc, 0, sizeof(EEVTDtail));
212 desc->text_length = getBit(data, &boff, 8);
213 memset(desc->text, 0, MAXSECLEN);
214 getStr(desc->text, data, &boff, desc->text_length);
216 return desc->text_length + 1;
219 int checkEEVTDitem(EEVTDitem *save, EEVTDitem *new, int descriptor_number) {
225 if(save->item_length != 0) {
227 memset(save->item, 0, MAXSECLEN);
228 getStr(save->item, (unsigned char*)swap.item, &boff, swap.item_length);
235 if(new->item_description_length == 0) {
237 memcpy(save->item + save->item_length, new->item, new->item_length);
238 save->item_length += new->item_length;
241 /* ブレーク。saveを印刷対象にする。saveをクリア? */
242 if(save->item_length != 0) {
245 memset(save->item, 0, MAXSECLEN);
246 getStr(save->item, (unsigned char*)swap.item, &boff, swap.item_length);
248 // swap save new -> swap save new
253 save->descriptor_number = descriptor_number;
257 save->descriptor_number = descriptor_number;
262 EIT_CONTROL *searcheit(EIT_CONTROL *top, int servid, int eventid)
268 if((cur->event_id == eventid) && (cur->servid == servid)){
276 char *strstr_eucjp(const char *str, const char *search)
281 while (*pos != '\0') {
282 if (*pos == *search) {
283 if (strncmp(pos, search, strlen(search)) == 0) {
287 if ((unsigned char)*pos == 0x8Fu) {
289 } else if ((unsigned char)*pos >= 0x80u) {
298 void conv_title_subtitle(EIT_CONTROL *eitptr)
306 for(lp = 0 ; subtitle_cnv_str[lp] != NULL ; lp++){
307 ptr = strstr(eitptr->title, subtitle_cnv_str[lp]);
312 if(ptr == eitptr->title){
317 for( ; (unsigned char)*ptr2 == 0x20u ; ptr2++ );
318 for( ; (unsigned char)*ptr2 == 0xA1u && (unsigned char)*(ptr2+1) == 0xA1u ; ptr2 += 2);
319 for( ; (unsigned char)*ptr2 == 0x20u ; ptr2++ );
320 newsubtitle = calloc(1, ((strlen(ptr2) + 2) + (strlen(eitptr->subtitle) + 1)));
321 memcpy(newsubtitle, ptr2, strlen(ptr2));
322 // *(newsubtitle+strlen(ptr)) = ' ';
323 strcat(newsubtitle, "▽");
325 newsubtitle = calloc(1, ((strlen(ptr) + 1) + (strlen(eitptr->subtitle) + 1)));
326 memcpy(newsubtitle, ptr, strlen(ptr));
327 newsubtitle[strlen(ptr)] = ' ';
330 strcat(newsubtitle, eitptr->subtitle);
331 free(eitptr->subtitle);
332 eitptr->subtitle = newsubtitle ;
336 void enqueue(EIT_CONTROL *top, EIT_CONTROL *eitptr)
342 if(top->next == NULL){
349 rc = memcmp(&cur->yy, &eitptr->yy, (sizeof(int) * 3));
351 rc = memcmp(&cur->hh, &eitptr->hh, (sizeof(int) * 3));
354 free(eitptr->subtitle);
360 cur->prev->next = eitptr ;
361 eitptr->prev = cur->prev ;
365 conv_title_subtitle(eitptr);
371 cur->prev->next = eitptr ;
372 eitptr->prev = cur->prev ;
376 conv_title_subtitle(eitptr);
379 if(cur->next == NULL){
382 conv_title_subtitle(eitptr);
391 void dumpEIT(unsigned char *ptr, int serv_id, int original_network_id, int transport_stream_id, EIT_CONTROL *eittop)
402 EEVTDitem save_eevtitem;
405 EIT_CONTROL *curtmp ;
415 len = parseEIThead(ptr, &eith);
418 loop_len = eith.section_length - (len - 3 + 4); // 3は共通ヘッダ長 4はCRC
419 while(loop_len > 0) {
420 /* 連続する拡張イベントは、漢字コードが泣き別れして
421 分割されるようだ。連続かどうかは、item_description_lengthが
422 設定されているかどうかで判断できるようだ。 */
423 memset(&save_eevtitem, 0, sizeof(EEVTDitem));
425 len = parseEITbody(ptr, &eitb);
429 /* printf("evtid:%d\n", eitb.event_id); */
431 loop_blen = eitb.descriptors_loop_length;
432 loop_len -= loop_blen;
434 while(loop_blen > 0) {
437 //printf("desc_tag");
438 //int itt=getBit(*ptr,0,8);
441 len = parseSEVTdesc(ptr, &sevtd);
445 if(eith.service_id == 19304 &&
446 eitb.event_id == 46564) {
454 if(eith.service_id != serv_id){
460 timecmp(&ehh, &emm, &ess,
461 eitb.dhh, eitb.dhm, eitb.dss);
462 cur = searcheit(eittop, eith.service_id, eitb.event_id);
465 cur = calloc(1, sizeof(EIT_CONTROL));
470 cur->event_id = eitb.event_id ;
471 cur->servid = eith.service_id ;
472 cur->title = calloc(1, (strlen(sevtd.event_name) + 1));
474 memcpy(cur->title, sevtd.event_name, strlen(sevtd.event_name));
475 cur->subtitle = calloc(1, (strlen(sevtd.text) + 1));
476 memcpy(cur->subtitle, sevtd.text, strlen(sevtd.text));
485 cur->ess = eitb.dss ;
486 cur->table_id = eith.table_id ;
487 if ( !curtmp ) enqueue(eittop, cur);
489 len = parseEEVTDhead(ptr, &eevthead);
492 if(eith.service_id == 19304 &&
493 eitb.event_id == 46564) {
502 loop_elen = eevthead.length_of_items;
503 loop_len -= loop_elen;
504 while(loop_elen > 0) {
505 len = parseEEVTDitem(ptr, &eevtitem);
511 if(checkEEVTDitem(&save_eevtitem, &eevtitem,
512 eevthead.descriptor_number)) {
515 if (eevtitem.descriptor_number>0){
516 //printf("descriptor_num %d\n",eevtitem.descriptor_number);
519 //printf("descriptor_num %d\n",eevtitem.descriptor_number);
521 printf("EEVT,%d,%d,%d,%s,%s\n",
524 eevtitem.descriptor_number, // 退避項目
525 eevtitem.item_description,
529 append_desc(eittop, eith.service_id, eitb.event_id, &eevtitem);
534 len = parseEEVTDtail(ptr, &eevttail);
537 printf("EEVTt,%d,%d,%d,%s\n",
540 eevthead.descriptor_number,
545 ContentDesc contentDesc;
546 len = parseContentDesc(ptr, &contentDesc);
548 //int header_printed = 0;
549 for (int i = 0; i < contentDesc.descriptor_length - 1; i+=2) {
551 if (0xff == (unsigned char)contentDesc.content[i])
555 if (!header_printed) {
556 fprintf(out, "Content,%d,%d\n",
563 //fprintf(out, ",%02x%02x", (unsigned char)contentDesc.content[i], (unsigned char)contentDesc.content[i+1]);
566 if((eith.original_network_id == original_network_id) && (eith.transport_stream_id == transport_stream_id)){
567 cur = searcheit(eittop, eith.service_id, eitb.event_id);
569 cur->content_type = (unsigned char)(contentDesc.content[0] >> 4);
571 fprintf(stdout, "%s:", cur->title);
572 fprintf(stdout, ",%02x%02x", (unsigned char)contentDesc.content[0], (unsigned char)contentDesc.content[1]);
573 fprintf(stdout, ",%02x%02x\n", (unsigned char)contentDesc.content[2], (unsigned char)contentDesc.content[3]);
578 if (header_printed) {
584 SeriesDesc seriesDesc;
585 len = parseSeriesDesc(ptr, &seriesDesc);
588 printf("Series,%d,%d,series=%d,repeat=%01x,pattern=%d,expire_valid=%d,expire=%04x,epinum=%d,lastepinum=%d,%s\n",
591 seriesDesc.series_id,
592 seriesDesc.repeat_label,
593 seriesDesc.program_pattern,
594 seriesDesc.expire_date_valid_flag,
595 seriesDesc.expire_date,
596 seriesDesc.episode_number,
597 seriesDesc.last_episode_number,
598 seriesDesc.series_name_char);
601 len = parseOTHERdesc(ptr);
611 if(checkEEVTDitem(&save_eevtitem, NULL, 0)) {
614 fprintf(stdout, "EEVT,%d,%d,%d,%s,%s\n",
617 save_eevtitem.descriptor_number,
618 save_eevtitem.item_description,
622 append_desc(eittop, eith.service_id, eitb.event_id, &save_eevtitem);
629 void append_desc(EIT_CONTROL* eittop, int service_id, int event_id, EEVTDitem* eevtitem) {
633 cur = searcheit(eittop, service_id, event_id);
639 str_alen = strlen( cur->desc );
644 //eevtitem->item_description_length = strlen(eevtitem->item_description);
645 //eevtitem->item_length = strlen(eevtitem->item);
646 cur->desc = realloc(cur->desc, str_alen + eevtitem->item_description_length + eevtitem->item_length + 1000);
647 if ( !str_alen ) *cur->desc = '\0';
649 if ( eevtitem->item_description_length && !strstr(cur->desc, eevtitem->item_description) ) {
650 strcat(cur->desc + str_alen, eevtitem->item_description);
651 strcat(cur->desc, "\t");
654 if ( eevtitem->item_length && !strstr(cur->desc, eevtitem->item) ) {
655 strcat(cur->desc + str_alen, eevtitem->item);
656 //printf("%s\n",eevtitem->item);
657 strcat(cur->desc, "\\n");
661 void timecmp(int *thh, int *tmm, int *tss,
662 int dhh, int dmm, int dss) {