summaryrefslogtreecommitdiffstats
path: root/stream/dvb_tune.c
diff options
context:
space:
mode:
Diffstat (limited to 'stream/dvb_tune.c')
-rw-r--r--stream/dvb_tune.c68
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)
{