[linux-dvb] szap-pmt.diff
Matthias Mueller
matthias.mueller at rz.uni-karlsruhe.de
Sun Jun 12 15:27:31 CEST 2005
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;
More information about the linux-dvb
mailing list