diff options
author | Oliver Freyermuth <o.freyermuth@googlemail.com> | 2015-01-04 23:22:02 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2015-01-06 19:52:27 +0100 |
commit | f309ecebe5da1eb7daa93a2b8bda3e956d8ebfec (patch) | |
tree | 52b367e68d1f6bd87c293ce5155950919b62b21e /stream/dvb_tune.c | |
parent | ef463aa1038eec1bf01216f87b1681fdf4973793 (diff) | |
download | mpv-f309ecebe5da1eb7daa93a2b8bda3e956d8ebfec.tar.bz2 mpv-f309ecebe5da1eb7daa93a2b8bda3e956d8ebfec.tar.xz |
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.
Diffstat (limited to 'stream/dvb_tune.c')
-rw-r--r-- | stream/dvb_tune.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/stream/dvb_tune.c b/stream/dvb_tune.c index 673109152a..873ac91ec5 100644 --- a/stream/dvb_tune.c +++ b/stream/dvb_tune.c @@ -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) { |