stream_dvb: Also demux PMT if possible, reactivate TPID parsing.

If VDR-channel-config is used, we know the service_id.
Using that, PMT can be extracted from PAT (code for that
inspired by szap-s2 again).
For this, we need to demux PAT with a special filter-setup,
and once PMT was found it can be added to the PID-list.
PMT is only resolved the first time one tunes to a channel,
then stored in the channel-list in memory.

With PMT available, ffmpeg can safely decode the teletext-pids.
This commit is contained in:
Oliver Freyermuth
2015-01-04 23:22:02 +01:00
committed by wm4
parent ef463aa103
commit f309ecebe5
4 changed files with 113 additions and 12 deletions

View File

@@ -187,6 +187,74 @@ int dvb_set_ts_filt(dvb_priv_t *priv, int fd, uint16_t pid, dmx_pes_type_t pesty
return 1;
}
int dvb_get_pmt_pid(dvb_priv_t *priv, int card, int service_id) {
/* We need special filters on the demux,
so open one locally, and close also here. */
char demux_dev[32];
sprintf(demux_dev, "/dev/dvb/adapter%d/demux0", card);
struct dmx_sct_filter_params fparams;
memset(&fparams, 0, sizeof(fparams));
fparams.pid = 0;
fparams.filter.filter[0] = 0x00;
fparams.filter.mask[0] = 0xff;
fparams.timeout = 0;
fparams.flags = DMX_IMMEDIATE_START | DMX_CHECK_CRC;
int pat_fd;
if ((pat_fd = open(demux_dev, O_RDWR)) < 0) {
MP_ERR(priv, "Opening PAT DEMUX failed, error: %d", errno);
return -1;
}
if (ioctl(pat_fd, DMX_SET_FILTER, &fparams) == -1) {
MP_ERR(priv, "ioctl DMX_SET_FILTER failed, error: %d", errno);
close(pat_fd);
return -1;
}
int bytes_read;
int section_length;
unsigned char buft[4096];
unsigned char *bufptr = buft;
int pmt_pid = -1;
bool pat_read = false;
while (!pat_read) {
if (((bytes_read = read(pat_fd, bufptr, sizeof(buft))) < 0) && errno == EOVERFLOW)
bytes_read = read(pat_fd, bufptr, sizeof(buft));
if (bytes_read < 0) {
MP_ERR(priv, "PAT: read_sections: read error: %d", errno);
close(pat_fd);
return -1;
}
section_length = ((bufptr[1] & 0x0f) << 8) | bufptr[2];
if (bytes_read != section_length + 3) {
continue;
}
bufptr += 8;
section_length -= 8;
/* assumes one section contains the whole pat */
pat_read = true;
while (section_length > 0) {
int this_service_id = (bufptr[0] << 8) | bufptr[1];
if (this_service_id == service_id) {
pmt_pid = ((bufptr[2] & 0x1f) << 8) | bufptr[3];
section_length = 0;
}
bufptr += 4;
section_length -= 4;
}
}
close(pat_fd);
return pmt_pid;
}
int dvb_demux_stop(int fd)
{