void dvb_table_sdt_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, uint8_t *table, ssize_t *table_length) { const uint8_t *p = buf, *endbuf = buf + buflen - 4; struct dvb_table_sdt *sdt = (void *)table; struct dvb_table_sdt_service **head = &sdt->service; size_t size = offsetof(struct dvb_table_sdt, service); if (*table_length > 0) { /* find end of curent list */ while (*head != NULL) head = &(*head)->next; } else { if (p + size > endbuf) { dvb_logerr("SDT table was truncated. Need %zu bytes, but has only %zu.", size, buflen); return; } memcpy(sdt, p, size); *table_length = sizeof(struct dvb_table_sdt); bswap16(sdt->network_id); sdt->service = NULL; } p += size; size = offsetof(struct dvb_table_sdt_service, descriptor); while (p + size <= endbuf) { struct dvb_table_sdt_service *service; service = malloc(sizeof(struct dvb_table_sdt_service)); memcpy(service, p, size); p += size; bswap16(service->service_id); bswap16(service->bitfield); service->descriptor = NULL; service->next = NULL; *head = service; head = &(*head)->next; /* get the descriptors for each program */ dvb_parse_descriptors(parms, p, service->section_length, &service->descriptor); p += service->section_length; } if (endbuf - p) dvb_logerr("PAT table has %zu spurious bytes at the end.", endbuf - p); }
void atsc_table_vct_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, ssize_t buflen, uint8_t *table, ssize_t *table_length) { const uint8_t *p = buf, *endbuf = buf + buflen - 4; struct atsc_table_vct *vct = (void *)table; struct atsc_table_vct_channel **head = &vct->channel; int i, n; size_t size = offsetof(struct atsc_table_vct, channel); if (p + size > endbuf) { dvb_logerr("VCT table was truncated. Need %zu bytes, but has only %zu.", size, buflen); return; } if (*table_length > 0) { /* find end of curent list */ while (*head != NULL) head = &(*head)->next; } else { memcpy(vct, p, size); *table_length = sizeof(struct atsc_table_vct); vct->channel = NULL; vct->descriptor = NULL; } p += size; size = offsetof(struct atsc_table_vct_channel, descriptor); for (n = 0; n < vct->num_channels_in_section; n++) { struct atsc_table_vct_channel *channel; if (p + size > endbuf) { dvb_logerr("VCT channel table is missing %d elements", vct->num_channels_in_section - n + 1); vct->num_channels_in_section = n; break; } channel = malloc(sizeof(struct atsc_table_vct_channel)); memcpy(channel, p, size); p += size; /* Fix endiannes of the copied fields */ for (i = 0; i < ARRAY_SIZE(channel->__short_name); i++) bswap16(channel->__short_name[i]); bswap32(channel->carrier_frequency); bswap16(channel->channel_tsid); bswap16(channel->program_number); bswap32(channel->bitfield1); bswap16(channel->bitfield2); bswap16(channel->source_id); bswap16(channel->bitfield3); /* Short name is always UTF-16 */ iconv_to_charset(parms, channel->short_name, sizeof(channel->short_name), (const unsigned char *)channel->__short_name, sizeof(channel->__short_name), "UTF-16", output_charset); /* Fill descriptors */ channel->descriptor = NULL; channel->next = NULL; *head = channel; head = &(*head)->next; /* get the descriptors for each program */ dvb_parse_descriptors(parms, p, channel->descriptors_length, &channel->descriptor); p += channel->descriptors_length; } /* Get extra descriptors */ size = sizeof(union atsc_table_vct_descriptor_length); while (p + size <= endbuf) { union atsc_table_vct_descriptor_length *d = (void *)p; bswap16(d->descriptor_length); p += size; dvb_parse_descriptors(parms, p, d->descriptor_length, &vct->descriptor); } if (endbuf - p) dvb_logerr("VCT table has %zu spurious bytes at the end.", endbuf - p); }