-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Simon Farnsworth wrote: > Simon Kilvington wrote: >> Hi, >> >> does anyone know where the logical channel numbers are >> transmitted in FreeView? - ie BBC1 is 1, BBC News is 80, etc - I've been >> looking at the PAT and PMTs with dvbsnoop but can't see anything >> obvious. >> > > It's in the NIT, using a private descriptor - scan from dvb-apps > (http://linuxtv.org/hg/dvb-apps/file/9311c900f746/util/scan/scan.c) > knows about them, and they're fully specced in the DTG 'D-Book' (see > http://dtg.org.uk/publications/books.html). thanks for the info the reason I wanted to know was because when I did a scan with mythtv I had to give it each frequency by hand, then it only managed to find the channel numbers for the channels on one mux - though this may be because the nit on my transmitter seems to be split into two bits - one nit has the info for 5 muxs, the other nit has the info for the other mux anyway, I wrote a small program that will get the channel numbers out of the nit(s) and dump some sql statements that you can use to update the channel numbers in an existing mythtv database - I've attached it here, compile it like this: gcc -o get-lcns get-lcns.c and run it like this (you'll probably need different dvbtune params): dvbtune -f 722166667 -qam 16 -cr 3_4 && ./get-lcns > lcns it will print a load of sql commands to stdout, so the > will put them in the "lcns" file. You can just pipe the output into mysql, like this: cat lcns | mysql -umythtv -pmythtv mythconverg to update your channel table - -- Simon Kilvington -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.4 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFITqcYmt9ZifioJSwRAiFvAJsF3JkuO7XbPw9/FVyCLSU76cYDTwCfV1sx kr74Bd1GCOJRxltIedK11aY= =kfY/ -----END PGP SIGNATURE-----
/* * dvbtune -f 722166667 -qam 16 -cr 3_4 && dvbsnoop 0x10 * * NIT: * PID=0x10 * TID=0x40 * tag=0x83 */ #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <stdbool.h> #include <stdarg.h> #include <errno.h> #include <sys/ioctl.h> #include <sys/select.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <linux/dvb/dmx.h> #define TIMEOUT 30 #define MAX_TABLE_LEN 4096 /* Network Information Table PID and TID */ #define PID_NIT 0x0010 #define TID_NIT 0x40 #define TAG_LCN 0x83 bool read_nit(char *, unsigned int, unsigned char *); bool read_table(char *, uint16_t, uint8_t, unsigned int, unsigned char *); void fatal(char *, ...); int main(void) { unsigned char nit[MAX_TABLE_LEN]; unsigned char *data; unsigned int section_len; unsigned int nit_len; unsigned int descriptors_loop_len; unsigned int transport_stream_id; unsigned int ntransport_ids; unsigned int transport_ids[6]; unsigned int i; /* * Malvern transmitter (repeater for Sutton Coldfield) broadcasts 2 NITs * one has the LCNs for 5 MUXs * the other has the LCNs for the other MUX */ ntransport_ids = 0; while(ntransport_ids < 6) { bzero(nit, MAX_TABLE_LEN); if(!read_nit("/dev/dvb/adapter0/demux0", TIMEOUT, nit)) fatal("Unable to read NIT"); /* generic header */ data = nit; section_len = ((data[1] & 0x0f) << 8) | data[2]; data += 8; /* header + CRC */ nit_len = section_len - (5 + 4); /* skip the first descriptors loop */ descriptors_loop_len = ((data[0] & 0x0f) << 8) | data[1]; data += descriptors_loop_len + 4; nit_len -= descriptors_loop_len + 4; while(nit_len > 6) { transport_stream_id = (data[0] << 8) | data[1]; /* have we already seen it */ for(i=0; i<ntransport_ids; i++) if(transport_stream_id == transport_ids[i]) continue; transport_ids[ntransport_ids++] = transport_stream_id; fprintf(stderr, "transport_stream_id=0x%x\n", transport_stream_id); descriptors_loop_len = ((data[4] & 0x0f) << 8) | data[5]; data += 6; nit_len -= descriptors_loop_len + 6; while(descriptors_loop_len > 0) { unsigned char desc_tag = data[0]; unsigned char desc_len = data[1] + 2; data += 2; if(desc_tag == TAG_LCN) { for(i=0; i<desc_len; i+=4) { unsigned int sid, lcn; sid = (data[i] << 8) | data[i+1]; lcn = ((data[i+2] & 0x03) << 8) | data[i+3]; printf("UPDATE channel SET chanid=\"%u\", channum=\"%u\" WHERE serviceid=\"%u\";\n", lcn + 1000, lcn, sid); } } data += desc_len - 2; descriptors_loop_len -= desc_len; } } } return 0; } /* * output buffer must be at least MAX_TABLE_LEN bytes * returns false if it timesout */ bool read_nit(char *demux, unsigned int timeout, unsigned char *out) { /* read it from the DVB card */ if(!read_table(demux, PID_NIT, TID_NIT, timeout, out)) { fatal("Unable to read NIT"); return false; } return true; } /* * output buffer must be at least MAX_TABLE_LEN bytes * returns false if it timesout */ bool read_table(char *device, uint16_t pid, uint8_t tid, unsigned int secs, unsigned char *out) { int fd_data; struct dmx_sct_filter_params sctFilterParams; fd_set readfds; struct timeval timeout; int n; if((fd_data = open(device, O_RDWR)) < 0) { fatal("open '%s': %s", device, strerror(errno)); return false; } memset(&sctFilterParams, 0, sizeof(sctFilterParams)); sctFilterParams.pid = pid; sctFilterParams.timeout = 0; sctFilterParams.flags = DMX_IMMEDIATE_START; sctFilterParams.filter.filter[0] = tid; sctFilterParams.filter.mask[0] = 0xff; if(ioctl(fd_data, DMX_SET_FILTER, &sctFilterParams) < 0) { fatal("ioctl DMX_SET_FILTER: %s", strerror(errno)); close(fd_data); return false; } timeout.tv_sec = secs; timeout.tv_usec = 0; do { /* we check for out[0]==tid to see if we read the table */ out[0] = ~tid; FD_ZERO(&readfds); FD_SET(fd_data, &readfds); if(select(fd_data + 1, &readfds, NULL, NULL, &timeout) < 0) { if(errno == EINTR) continue; fatal("read_table: select: %s", strerror(errno)); close(fd_data); return false; } if(FD_ISSET(fd_data, &readfds)) { if((n = read(fd_data, out, MAX_TABLE_LEN)) < 0) { fatal("read: %s", strerror(errno)); close(fd_data); return false; } } else { fatal("Timeout reading %s", device); close(fd_data); return false; } } while(out[0] != tid); close(fd_data); return true; } void fatal(char *message, ...) { va_list ap; va_start(ap, message); vfprintf(stderr, message, ap); fprintf(stderr, "\n"); va_end(ap); exit(EXIT_FAILURE); }
Attachment:
get-lcns.c.sig
Description: Binary data
_______________________________________________ linux-dvb mailing list linux-dvb@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb