From 3d5910bcf6d29abdcc9f19132a836ff47aa7d2b3 Mon Sep 17 00:00:00 2001 From: Adam Sutton Date: Mon, 18 Jun 2012 13:47:43 +0100 Subject: [PATCH] Moved EIT handling code from dvb_tables into the eit grab module. Needs tidying up. --- src/dvb/dvb_tables.c | 229 ----------------------------------------- src/epggrab/eit.c | 236 ++++++++++++++++++++++++++++++++++++++++++- src/epggrab/eit.h | 6 -- 3 files changed, 234 insertions(+), 237 deletions(-) diff --git a/src/dvb/dvb_tables.c b/src/dvb/dvb_tables.c index 743ed66f..cb7d39e8 100644 --- a/src/dvb/dvb_tables.c +++ b/src/dvb/dvb_tables.c @@ -41,7 +41,6 @@ #include "psi.h" #include "notify.h" #include "cwc.h" -#include "epggrab/eit.h" static void dvb_table_add_pmt(th_dvb_mux_instance_t *tdmi, int pmt_pid); @@ -320,95 +319,6 @@ tdt_add(th_dvb_mux_instance_t *tdmi, struct dmx_sct_filter_params *fparams, tdt_open_fd(tdmi, tdt); } - -/** - * DVB Descriptor; Short Event - */ -static int -dvb_desc_short_event(uint8_t *ptr, int len, - char *title, size_t titlelen, - char *desc, size_t desclen, - char *dvb_default_charset) -{ - int r; - - if(len < 4) - return -1; - ptr += 3; len -= 3; - - if((r = dvb_get_string_with_len(title, titlelen, ptr, len, dvb_default_charset)) < 0) - return -1; - ptr += r; len -= r; - - if((r = dvb_get_string_with_len(desc, desclen, ptr, len, dvb_default_charset)) < 0) - return -1; - - return 0; -} - -/** - * DVB Descriptor; Extended Event - */ -static int -dvb_desc_extended_event(uint8_t *ptr, int len, - char *desc, size_t desclen, - char *item, size_t itemlen, - char *text, size_t textlen, - char *dvb_default_charset) -{ - int count = ptr[4], r; - uint8_t *localptr = ptr + 5, *items = localptr; - int locallen = len - 5; - - /* terminate buffers */ - desc[0] = '\0'; item[0] = '\0'; text[0] = '\0'; - - while (items < (localptr + count)) - { - /* this only makes sense if we have 2 or more character left in buffer */ - if ((desclen - strlen(desc)) > 2) - { - /* get description -> append to desc if space left */ - if (desc[0] != '\0') - strncat(desc, "\n", 1); - if((r = dvb_get_string_with_len(desc + strlen(desc), - desclen - strlen(desc), - items, (localptr + count) - items, - dvb_default_charset)) < 0) - return -1; - } - - items += 1 + items[0]; - - /* this only makes sense if we have 2 or more character left in buffer */ - if ((itemlen - strlen(item)) > 2) - { - /* get item -> append to item if space left */ - if (item[0] != '\0') - strncat(item, "\n", 1); - if((r = dvb_get_string_with_len(item + strlen(item), - itemlen - strlen(item), - items, (localptr + count) - items, - dvb_default_charset)) < 0) - return -1; - } - - /* go to next item */ - items += 1 + items[0]; - } - - localptr += count; - locallen -= count; - count = localptr[0]; - - /* get text */ - if((r = dvb_get_string_with_len(text, textlen, localptr, locallen, dvb_default_charset)) < 0) - return -1; - - return 0; -} - - /** * DVB Descriptor; Service */ @@ -437,139 +347,6 @@ dvb_desc_service(uint8_t *ptr, int len, uint8_t *typep, return 0; } - -/** - * DVB EIT (Event Information Table) - */ -static int -dvb_eit_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, - uint8_t tableid, void *opaque) -{ - service_t *t; - channel_t *ch; - th_dvb_adapter_t *tda = tdmi->tdmi_adapter; - - uint16_t serviceid; - uint16_t transport_stream_id; - - uint16_t event_id; - time_t start_time, stop_time; - - int ok; - int duration; - int dllen; - uint8_t dtag, dlen; - - char title[256]; - char desc[5000]; - char extdesc[5000]; - char extitem[5000]; - char exttext[5000]; - uint8_t genre[10]; // max 10 genres - int genre_idx = 0; - - lock_assert(&global_lock); - - // printf("EIT!, tid = %x\n", tableid); - - if(tableid < 0x4e || tableid > 0x6f || len < 11) - return -1; - - serviceid = ptr[0] << 8 | ptr[1]; - // version = ptr[2] >> 1 & 0x1f; - // section_number = ptr[3]; - // last_section_number = ptr[4]; - transport_stream_id = ptr[5] << 8 | ptr[6]; - // original_network_id = ptr[7] << 8 | ptr[8]; - // segment_last_section_number = ptr[9]; - // last_table_id = ptr[10]; - - if((ptr[2] & 1) == 0) { - /* current_next_indicator == next, skip this */ - return -1; - } - - len -= 11; - ptr += 11; - - /* Search all muxes on adapter */ - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) - if(tdmi->tdmi_transport_stream_id == transport_stream_id) - break; - - if(tdmi == NULL) - return -1; - - t = dvb_transport_find(tdmi, serviceid, 0, NULL); - if(t == NULL || !t->s_enabled || (ch = t->s_ch) == NULL) - return 0; - - if(!t->s_dvb_eit_enable) - return 0; - - while(len >= 12) { - ok = 1; - event_id = ptr[0] << 8 | ptr[1]; - start_time = dvb_convert_date(&ptr[2]); - duration = bcdtoint(ptr[7] & 0xff) * 3600 + - bcdtoint(ptr[8] & 0xff) * 60 + - bcdtoint(ptr[9] & 0xff); - dllen = ((ptr[10] & 0x0f) << 8) | ptr[11]; - - len -= 12; - ptr += 12; - - if(dllen > len) break; - stop_time = start_time + duration; - - *title = 0; - *desc = 0; - while(dllen > 0) { - dtag = ptr[0]; - dlen = ptr[1]; - - len -= 2; ptr += 2; dllen -= 2; - - if(dlen > len) break; - - switch(dtag) { - case DVB_DESC_SHORT_EVENT: - if(dvb_desc_short_event(ptr, dlen, - title, sizeof(title), - desc, sizeof(desc), - t->s_dvb_default_charset)) ok = 0; - break; - - case DVB_DESC_CONTENT: - if(dlen >= 2) { - if (genre_idx < 10) - genre[genre_idx++] = (*ptr); - } - break; - case DVB_DESC_EXT_EVENT: - if(dvb_desc_extended_event(ptr, dlen, - extdesc, sizeof(extdesc), - extitem, sizeof(extitem), - exttext, sizeof(exttext), - t->s_dvb_default_charset)) ok = 0; - break; - default: - break; - } - - len -= dlen; ptr += dlen; dllen -= dlen; - } - - /* Pass to EIT handler */ - if (ok) - eit_callback(ch, event_id, start_time, stop_time, - title, desc, extitem, extdesc, exttext, - genre, genre_idx); - } - return 0; -} - - /** * DVB SDT (Service Description Table) */ @@ -1242,12 +1019,6 @@ dvb_table_add_default_dvb(th_dvb_mux_instance_t *tdmi) fp->filter.mask[0] = 0xff; tdt_add(tdmi, fp, dvb_sdt_callback, NULL, "sdt", TDT_QUICKREQ | TDT_CRC, 0x11, NULL); - - /* Event Information table */ - - fp = dvb_fparams_alloc(); - tdt_add(tdmi, fp, dvb_eit_callback, NULL, "eit", - TDT_CRC, 0x12, NULL); } diff --git a/src/epggrab/eit.c b/src/epggrab/eit.c index 8ba807ec..60ffb9b7 100644 --- a/src/epggrab/eit.c +++ b/src/epggrab/eit.c @@ -19,6 +19,9 @@ #include #include "tvheadend.h" #include "channels.h" +#include "dvb/dvb.h" +#include "dvb/dvb_support.h" +#include "service.h" #include "epg.h" #include "epggrab/eit.h" @@ -36,8 +39,7 @@ longest_string ( const char *a, const char *b ) if (strlen(a) - strlen(b) >= 0) return a; } -// called from dvb_tables.c -void eit_callback ( channel_t *ch, int id, time_t start, time_t stop, +static void eit_callback ( channel_t *ch, int id, time_t start, time_t stop, const char *title, const char *desc, const char *extitem, const char *extdesc, const char *exttext, @@ -95,14 +97,244 @@ void eit_callback ( channel_t *ch, int id, time_t start, time_t stop, free(uri); } + +/** + * DVB Descriptor; Short Event + */ +static int +dvb_desc_short_event(uint8_t *ptr, int len, + char *title, size_t titlelen, + char *desc, size_t desclen, + char *dvb_default_charset) +{ + int r; + + if(len < 4) + return -1; + ptr += 3; len -= 3; + + if((r = dvb_get_string_with_len(title, titlelen, ptr, len, dvb_default_charset)) < 0) + return -1; + ptr += r; len -= r; + + if((r = dvb_get_string_with_len(desc, desclen, ptr, len, dvb_default_charset)) < 0) + return -1; + + return 0; +} + +/** + * DVB Descriptor; Extended Event + */ +static int +dvb_desc_extended_event(uint8_t *ptr, int len, + char *desc, size_t desclen, + char *item, size_t itemlen, + char *text, size_t textlen, + char *dvb_default_charset) +{ + int count = ptr[4], r; + uint8_t *localptr = ptr + 5, *items = localptr; + int locallen = len - 5; + + /* terminate buffers */ + desc[0] = '\0'; item[0] = '\0'; text[0] = '\0'; + + while (items < (localptr + count)) + { + /* this only makes sense if we have 2 or more character left in buffer */ + if ((desclen - strlen(desc)) > 2) + { + /* get description -> append to desc if space left */ + if (desc[0] != '\0') + strncat(desc, "\n", 1); + if((r = dvb_get_string_with_len(desc + strlen(desc), + desclen - strlen(desc), + items, (localptr + count) - items, + dvb_default_charset)) < 0) + return -1; + } + + items += 1 + items[0]; + + /* this only makes sense if we have 2 or more character left in buffer */ + if ((itemlen - strlen(item)) > 2) + { + /* get item -> append to item if space left */ + if (item[0] != '\0') + strncat(item, "\n", 1); + if((r = dvb_get_string_with_len(item + strlen(item), + itemlen - strlen(item), + items, (localptr + count) - items, + dvb_default_charset)) < 0) + return -1; + } + + /* go to next item */ + items += 1 + items[0]; + } + + localptr += count; + locallen -= count; + count = localptr[0]; + + /* get text */ + if((r = dvb_get_string_with_len(text, textlen, localptr, locallen, dvb_default_charset)) < 0) + return -1; + + return 0; +} + + +/** + * DVB EIT (Event Information Table) + */ +static int +_eit_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, + uint8_t tableid, void *opaque) +{ + service_t *t; + channel_t *ch; + th_dvb_adapter_t *tda = tdmi->tdmi_adapter; + epggrab_module_t *mod = (epggrab_module_t*)opaque; + + uint16_t serviceid; + uint16_t transport_stream_id; + + uint16_t event_id; + time_t start_time, stop_time; + + int ok; + int duration; + int dllen; + uint8_t dtag, dlen; + + char title[256]; + char desc[5000]; + char extdesc[5000]; + char extitem[5000]; + char exttext[5000]; + uint8_t genre[10]; // max 10 genres + int genre_idx = 0; + + /* Global disable */ + if (!mod->enabled) return 0; + + lock_assert(&global_lock); + + // printf("EIT!, tid = %x\n", tableid); + + if(tableid < 0x4e || tableid > 0x6f || len < 11) + return -1; + + serviceid = ptr[0] << 8 | ptr[1]; + // version = ptr[2] >> 1 & 0x1f; + // section_number = ptr[3]; + // last_section_number = ptr[4]; + transport_stream_id = ptr[5] << 8 | ptr[6]; + // original_network_id = ptr[7] << 8 | ptr[8]; + // segment_last_section_number = ptr[9]; + // last_table_id = ptr[10]; + + if((ptr[2] & 1) == 0) { + /* current_next_indicator == next, skip this */ + return -1; + } + + len -= 11; + ptr += 11; + + /* Search all muxes on adapter */ + LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) + if(tdmi->tdmi_transport_stream_id == transport_stream_id) + break; + + if(tdmi == NULL) + return -1; + + t = dvb_transport_find(tdmi, serviceid, 0, NULL); + if(t == NULL || !t->s_enabled || (ch = t->s_ch) == NULL) + return 0; + + if(!t->s_dvb_eit_enable) + return 0; + + while(len >= 12) { + ok = 1; + event_id = ptr[0] << 8 | ptr[1]; + start_time = dvb_convert_date(&ptr[2]); + duration = bcdtoint(ptr[7] & 0xff) * 3600 + + bcdtoint(ptr[8] & 0xff) * 60 + + bcdtoint(ptr[9] & 0xff); + dllen = ((ptr[10] & 0x0f) << 8) | ptr[11]; + + len -= 12; + ptr += 12; + + if(dllen > len) break; + stop_time = start_time + duration; + + *title = 0; + *desc = 0; + while(dllen > 0) { + dtag = ptr[0]; + dlen = ptr[1]; + + len -= 2; ptr += 2; dllen -= 2; + + if(dlen > len) break; + + switch(dtag) { + case DVB_DESC_SHORT_EVENT: + if(dvb_desc_short_event(ptr, dlen, + title, sizeof(title), + desc, sizeof(desc), + t->s_dvb_default_charset)) ok = 0; + break; + + case DVB_DESC_CONTENT: + if(dlen >= 2) { + if (genre_idx < 10) + genre[genre_idx++] = (*ptr); + } + break; + case DVB_DESC_EXT_EVENT: + if(dvb_desc_extended_event(ptr, dlen, + extdesc, sizeof(extdesc), + extitem, sizeof(extitem), + exttext, sizeof(exttext), + t->s_dvb_default_charset)) ok = 0; + break; + default: + break; + } + + len -= dlen; ptr += dlen; dllen -= dlen; + } + + /* Pass to EIT handler */ + if (ok) + eit_callback(ch, event_id, start_time, stop_time, + title, desc, extitem, extdesc, exttext, + genre, genre_idx); + } + return 0; +} + /* ************************************************************************ * Module Setup * ***********************************************************************/ +static void _eit_tune ( epggrab_module_t *m, th_dvb_mux_instance_t *tdmi ) +{ + tdt_add(tdmi, NULL, _eit_callback, NULL, "eit", TDT_CRC, 0x12, NULL); +} + void eit_init ( epggrab_module_list_t *list ) { _eit_mod.id = strdup("eit"); _eit_mod.name = strdup("EIT: On-Air Grabber"); + _eit_mod.tune = _eit_tune; *((uint8_t*)&_eit_mod.flags) = EPGGRAB_MODULE_OTA; LIST_INSERT_HEAD(list, &_eit_mod, link); // Note: this is mostly ignored anyway as EIT is treated as a special case! diff --git a/src/epggrab/eit.h b/src/epggrab/eit.h index be58edeb..c278718b 100644 --- a/src/epggrab/eit.h +++ b/src/epggrab/eit.h @@ -24,10 +24,4 @@ void eit_init ( epggrab_module_list_t *list ); void eit_load ( void ); -void eit_callback ( struct channel *ch, int id, time_t start, time_t stop, - const char *title, const char *desc, - const char *extitem, const char *extdesc, - const char *exttext, - const uint8_t *genres, int genre_cnt ); - #endif