Hi, On Sun, Jun 12, 2005 at 02:55:41PM +0200, Johannes Stezenbach wrote: > On Sat, Jun 11, 2005 at 08:43:33PM +0200, Matthias Mueller wrote: > > static int set_demux(int dmxfd, int pid, int audio, int dvr) > > { > > struct dmx_pes_filter_params pesfilter; > > > > - if (pid <= 0 || pid >= 0x1fff) /* ignore this pid to allow radio services */ > > + if (pid < 0 || pid >= 0x1fff) /* ignore this pid to allow radio services */ > > return TRUE; > > Unfortunately there are channels.conf files which > use 0 for "no video/audio pid" which is OK since 0 is no valid > video/audio pid. You need to handle this in read_channels. I had a look at read_channels, my first thought was changing vpid/apid to -1 if they are 0, but vpid/apid are declared as unsigned int. Is it safe, to change them to signed int? > > - pesfilter.pes_type = audio ? DMX_PES_AUDIO : DMX_PES_VIDEO; > > + pesfilter.pes_type = audio; Changed audio to pes_type to avoid confusion. > > +int get_pmt(char *dmxdev, int sid) > > +{ > > + int patfd,count; > > + int pmt=0; > > + int patread=0; > > How about some whitespace? fixed > > + int section_length; > > + unsigned char buft[4096]; > > + unsigned char *buf = buft; > > + struct dmx_sct_filter_params f; > > + > > + memset(&f, 0, sizeof(f)); > > + f.pid = 0; > > + f.filter.filter[0] = (uint8_t) 0x42; > > + f.filter.filter[0] = 0xff; > > Huh? > - you should rename this function to get_pmt_pid() > - the PAT has table_id 0, not 0x42 > - the (uint8_t) cast is unnecessary > - you probably meant to set f.filter.mask[0], but luckily this > error cancels out your previous one :-) renamed, regarding 0x42, i copied the values from the wrong line in scan.c ;-) f.filter.mask[0] = 0xff is corrected, too. > > @@ -230,10 +290,12 @@ > > static > > int zap_to(unsigned int adapter, unsigned int frontend, unsigned int demux, > > unsigned int sat_no, unsigned int freq, unsigned int pol, > > - unsigned int sr, unsigned int vpid, unsigned int apid, int dvr) > > + unsigned int sr, unsigned int vpid, unsigned int apid, int sid, > > This line adds trailing whitespace fixed > > @@ -293,13 +374,30 @@ > > > > if (diseqc(fefd, sat_no, pol, hiband)) > > if (do_tune(fefd, ifreq, sr)) > > - if (set_demux(videofd, vpid, 0, dvr)) > > - if (set_demux(audiofd, apid, 1, dvr)) > > - result = TRUE; > > + if (set_demux(videofd, vpid, DMX_PES_OTHER, dvr)) > > + if (set_demux(audiofd, apid, DMX_PES_OTHER, dvr)) { > > Argh! This just disabled live decoding on FF cards :-( Sorry, forgot to change that back and only tested it on my system with budget-card. Changed back to DMX_PES_VIDEO/AUDIO. > > + if (pmt) { > > + pmtpid=get_pmt(dmxdev, sid); > > + if (pmtpid < 0) { > > + result = FALSE; > > + } > > + if (pmtpid == 0) { > > + fprintf(stderr,"couldn't find pmt for sid %04x\n",sid); > > + result = FALSE; > > + } > > + if (set_demux(patfd, 0, DMX_PES_OTHER, dvr)) > > + if (set_demux(pmtfd, pmtpid, DMX_PES_OTHER, dvr)) > > indentation I thought I got all ;-) Btw. I was looking for indent-options, to fix all these indentation errors, but didn't find one. Is there something like that out there? > > + result = TRUE; > > + } else { > > + result = TRUE; > > + } > > + } > > > + unsigned int demux, int dvr, int pmt) > > please rename "pmt" to something more descriptive, e.g. "rec_psi" fixed. So the only thing missing should be correct handling of channels with no audio/video pid. Matthias -------------- next part -------------- --- szap.c.orig 2005-06-11 09:42:05.000000000 +0200 +++ szap.c 2005-06-12 15:25:54.000000000 +0200 @@ -84,13 +84,14 @@ " -l lnb-type (DVB-S Only) (use -l help to print types) or \n" " -l low[,high[,switch]] in Mhz\n" " -i : run interactively, allowing you to type in channel names\n" + " -p : add pat and pmt to TS recording (implies -r)\n" " or -n numbers for zapping\n"; -static int set_demux(int dmxfd, int pid, int audio, int dvr) +static int set_demux(int dmxfd, int pid, int pes_type, int dvr) { struct dmx_pes_filter_params pesfilter; - if (pid <= 0 || pid >= 0x1fff) /* ignore this pid to allow radio services */ + if (pid < 0 || pid >= 0x1fff) /* ignore this pid to allow radio services */ return TRUE; if (dvr) { @@ -102,7 +103,7 @@ pesfilter.pid = pid; pesfilter.input = DMX_IN_FRONTEND; pesfilter.output = dvr ? DMX_OUT_TS_TAP : DMX_OUT_DECODER; - pesfilter.pes_type = audio ? DMX_PES_AUDIO : DMX_PES_VIDEO; + pesfilter.pes_type = pes_type; pesfilter.flags = DMX_IMMEDIATE_START; if (ioctl(dmxfd, DMX_SET_PES_FILTER, &pesfilter) == -1) { @@ -114,6 +115,65 @@ return TRUE; } +int get_pmt_pid(char *dmxdev, int sid) +{ + int patfd, count; + int pmt_pid = 0; + int patread = 0; + int section_length; + unsigned char buft[4096]; + unsigned char *buf = buft; + struct dmx_sct_filter_params f; + + memset(&f, 0, sizeof(f)); + f.pid = 0; + f.filter.filter[0] = 0x00; + f.filter.mask[0] = 0xff; + f.timeout = 0; + f.flags = DMX_IMMEDIATE_START | DMX_CHECK_CRC; + + if ((patfd = open(dmxdev, O_RDWR)) < 0) { + perror("openening pat demux failed"); + return -1; + } + + if (ioctl(patfd, DMX_SET_FILTER, &f) == -1) { + perror("ioctl DMX_SET_FILTER failed"); + close(patfd); + return -1; + } + + while (!patread){ + if (((count = read(patfd, buf, sizeof(buft))) < 0) && errno == EOVERFLOW) + count = read(patfd, buf, sizeof(buft)); + if (count < 0) { + perror("read_sections: read error"); + close(patfd); + return -1; + } + + section_length = ((buf[1] & 0x0f) << 8) | buf[2]; + if (count != section_length + 3) + continue; + + buf+=8; + section_length-=8; + + patread=1; /* assumes one section contains the whole pat */ + while (section_length > 0) { + int service_id = (buf[0] << 8) | buf[1]; + if (service_id == sid) { + pmt_pid = ((buf[2] & 0x1f) << 8) | buf[3]; + section_length = 0; + } + buf += 4; + section_length -= 4; + } + } + + close(patfd); + return pmt_pid; +} struct diseqc_cmd { struct dvb_diseqc_master_cmd cmd; @@ -230,10 +290,12 @@ static int zap_to(unsigned int adapter, unsigned int frontend, unsigned int demux, unsigned int sat_no, unsigned int freq, unsigned int pol, - unsigned int sr, unsigned int vpid, unsigned int apid, int dvr) + unsigned int sr, unsigned int vpid, unsigned int apid, int sid, + int dvr, int rec_psi) { char fedev[128], dmxdev[128]; - static int fefd, videofd, audiofd; + static int fefd, videofd, audiofd, patfd, pmtfd; + int pmtpid; uint32_t ifreq; int hiband, result; static struct dvb_frontend_info fe_info; @@ -274,6 +336,25 @@ close(fefd); return FALSE; } + + if (rec_psi){ + if ((patfd = open(dmxdev, O_RDWR)) < 0) { + perror("opening audio demux failed"); + close(audiofd); + close(videofd); + close(fefd); + return FALSE; + } + + if ((pmtfd = open(dmxdev, O_RDWR)) < 0) { + perror("opening audio demux failed"); + close(patfd); + close(audiofd); + close(videofd); + close(fefd); + return FALSE; + } + } } hiband = 0; @@ -293,13 +374,30 @@ if (diseqc(fefd, sat_no, pol, hiband)) if (do_tune(fefd, ifreq, sr)) - if (set_demux(videofd, vpid, 0, dvr)) - if (set_demux(audiofd, apid, 1, dvr)) - result = TRUE; + if (set_demux(videofd, vpid, DMX_PES_VIDEO, dvr)) + if (set_demux(audiofd, apid, DMX_PES_AUDIO, dvr)) { + if (rec_psi) { + pmtpid = get_pmt_pid(dmxdev, sid); + if (pmtpid < 0) { + result = FALSE; + } + if (pmtpid == 0) { + fprintf(stderr,"couldn't find pmt-pid for sid %04x\n",sid); + result = FALSE; + } + if (set_demux(patfd, 0, DMX_PES_OTHER, dvr)) + if (set_demux(pmtfd, pmtpid, DMX_PES_OTHER, dvr)) + result = TRUE; + } else { + result = TRUE; + } + } check_frontend (fefd, dvr); if (!interactive) { + close(patfd); + close(pmtfd); close(audiofd); close(videofd); close(fefd); @@ -312,14 +410,14 @@ static int read_channels(const char *filename, int list_channels, uint32_t chan_no, const char *chan_name, unsigned int adapter, unsigned int frontend, - unsigned int demux, int dvr) + unsigned int demux, int dvr, int rec_psi) { FILE *cfp; char buf[4096]; char inp[256]; char *field, *tmp, *p; unsigned int line; - unsigned int freq, pol, sat_no, sr, vpid, apid; + unsigned int freq, pol, sat_no, sr, vpid, apid, sid; int ret; again: @@ -405,14 +503,19 @@ apid = strtoul(field, NULL, 0); + if (!(field = strsep(&tmp, ":"))) + goto syntax_err; + + sid = strtoul(field, NULL, 0); + printf("sat %u, frequency = %u MHz %c, symbolrate %u, " - "vpid = 0x%04x, apid = 0x%04x\n", - sat_no, freq, pol ? 'V' : 'H', sr, vpid, apid); + "vpid = 0x%04x, apid = 0x%04x sid = 0x%04x\n", + sat_no, freq, pol ? 'V' : 'H', sr, vpid, apid, sid); fclose(cfp); ret = zap_to(adapter, frontend, demux, - sat_no, freq * 1000, pol, sr, vpid, apid, dvr); + sat_no, freq * 1000, pol, sr, vpid, apid, sid, dvr, rec_psi); if (interactive) goto again; @@ -475,11 +578,11 @@ int list_channels = 0; unsigned int chan_no = 0; const char *chan_name = NULL; - unsigned int adapter = 0, frontend = 0, demux = 0, dvr = 0; + unsigned int adapter = 0, frontend = 0, demux = 0, dvr = 0, rec_psi = 0; int opt, copt = 0; lnb_type = *lnb_enum(0); - while ((opt = getopt(argc, argv, "hqrn:a:f:d:c:l:xi")) != -1) { + while ((opt = getopt(argc, argv, "hqrpn:a:f:d:c:l:xi")) != -1) { switch (opt) { case '?': @@ -501,6 +604,9 @@ case 'f': frontend = strtoul(optarg, NULL, 0); break; + case 'p': + rec_psi = 1; + break; case 'd': demux = strtoul(optarg, NULL, 0); break; @@ -551,8 +657,11 @@ printf("reading channels from file '%s'\n", chanfile); + if (rec_psi) + dvr=1; + if (!read_channels(chanfile, list_channels, chan_no, chan_name, - adapter, frontend, demux, dvr)) + adapter, frontend, demux, dvr, rec_psi)) return TRUE; return FALSE;