Moved EIT handling code from dvb_tables into the eit grab module. Needs tidying up.

This commit is contained in:
Adam Sutton 2012-06-18 13:47:43 +01:00
parent 96668a6134
commit 3d5910bcf6
3 changed files with 234 additions and 237 deletions

View file

@ -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);
}

View file

@ -19,6 +19,9 @@
#include <string.h>
#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!

View file

@ -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