From 04d04033e66934b9799d52c80515908e29daa2dc Mon Sep 17 00:00:00 2001 From: rim Date: Fri, 15 Dec 2017 15:37:30 +0300 Subject: [PATCH] dvb: Add multiple frontends support: MAX_FRONTENDS now 8. --- stream/dvb_tune.c | 25 +++---- stream/dvb_tune.h | 3 +- stream/dvbin.h | 9 ++- stream/stream_dvb.c | 154 +++++++++++++++++++++++--------------------- 4 files changed, 101 insertions(+), 90 deletions(-) diff --git a/stream/dvb_tune.c b/stream/dvb_tune.c index 7c24af104e..d9b350f876 100644 --- a/stream/dvb_tune.c +++ b/stream/dvb_tune.c @@ -1,7 +1,7 @@ /* dvbtune - tune.c Copyright (C) Dave Chapman 2001,2002 - Copyright (C) Rozhuk Ivan 2016 + Copyright (C) Rozhuk Ivan 2016 - 2017 Modified for use with MPlayer, for details see the changelog at http://svn.mplayerhq.hu/mplayer/trunk/ @@ -82,7 +82,7 @@ unsigned int dvb_get_tuner_delsys_mask(int fe_fd, struct mp_log *log) #ifdef DVB_USE_S2API /* S2API is the DVB API new since 2.6.28. It allows to query frontends with multiple delivery systems. */ - mp_verbose(log, "Querying tuner type via DVBv5 API for frontend FD %d\n", + mp_verbose(log, "Querying tuner frontend type via DVBv5 API for frontend FD %d\n", fe_fd); prop[0].cmd = DTV_ENUM_DELSYS; if (ioctl(fe_fd, FE_GET_PROPERTY, &cmdseq) < 0) { @@ -98,14 +98,14 @@ unsigned int dvb_get_tuner_delsys_mask(int fe_fd, struct mp_log *log) for (i = 0; i < delsys_count; i++) { delsys = (unsigned int)prop[0].u.buffer.data[i]; DELSYS_SET(ret_mask, delsys); - mp_verbose(log, "DVBv5: Tuner type seems to be %s\n", get_dvb_delsys(delsys)); + mp_verbose(log, "DVBv5: Tuner frontend type seems to be %s\n", get_dvb_delsys(delsys)); } return ret_mask; old_api: #endif - mp_verbose(log, "Querying tuner type via pre-DVBv5 API for frontend FD %d\n", + mp_verbose(log, "Querying tuner frontend type via pre-DVBv5 API for frontend FD %d\n", fe_fd); memset(&fe_info, 0x00, sizeof(struct dvb_frontend_info)); @@ -119,7 +119,7 @@ old_api: prop[0].u.data = 0x0300; /* Fail, assume 3.0 */ } - mp_verbose(log, "DVBv3: Queried tuner type of device named '%s', FD: %d\n", + mp_verbose(log, "DVBv3: Queried tuner frontend type of device named '%s', FD: %d\n", fe_info.name, fe_fd); switch (fe_info.type) { case FE_OFDM: @@ -158,29 +158,30 @@ old_api: break; #endif default: - mp_err(log, "DVBv3: Unknown tuner type: %d\n", fe_info.type); + mp_err(log, "DVBv3: Unknown tuner frontend type: %d\n", fe_info.type); return ret_mask; } for (delsys = 0; delsys < SYS_DVB__COUNT__; delsys ++) { if (!DELSYS_IS_SET(ret_mask, delsys)) continue; /* Skip unsupported. */ - mp_verbose(log, "DVBv3: Tuner type seems to be %s\n", get_dvb_delsys(delsys)); + mp_verbose(log, "DVBv3: Tuner frontend type seems to be %s\n", get_dvb_delsys(delsys)); } return ret_mask; } -int dvb_open_devices(dvb_priv_t *priv, unsigned int n, unsigned int demux_cnt) +int dvb_open_devices(dvb_priv_t *priv, unsigned int adapter, + unsigned int frontend, unsigned int demux_cnt) { unsigned int i; char frontend_dev[PATH_MAX], dvr_dev[PATH_MAX], demux_dev[PATH_MAX]; - dvb_state_t* state = priv->state; - snprintf(frontend_dev, sizeof(frontend_dev), "/dev/dvb/adapter%u/frontend0", n); - snprintf(dvr_dev, sizeof(dvr_dev), "/dev/dvb/adapter%u/dvr0", n); - snprintf(demux_dev, sizeof(demux_dev), "/dev/dvb/adapter%u/demux0", n); + snprintf(frontend_dev, sizeof(frontend_dev), "/dev/dvb/adapter%u/frontend%u", adapter, frontend); + snprintf(dvr_dev, sizeof(dvr_dev), "/dev/dvb/adapter%u/dvr0", adapter); + snprintf(demux_dev, sizeof(demux_dev), "/dev/dvb/adapter%u/demux0", adapter); + MP_VERBOSE(priv, "DVB_OPEN_DEVICES: frontend: %s\n", frontend_dev); state->fe_fd = open(frontend_dev, O_RDWR | O_NONBLOCK | O_CLOEXEC); if (state->fe_fd < 0) { MP_ERR(priv, "ERROR OPENING FRONTEND DEVICE %s: ERRNO %d\n", diff --git a/stream/dvb_tune.h b/stream/dvb_tune.h index 756f730008..d7a790171f 100644 --- a/stream/dvb_tune.h +++ b/stream/dvb_tune.h @@ -26,7 +26,8 @@ struct mp_log; const char *get_dvb_delsys(unsigned int delsys); unsigned int dvb_get_tuner_delsys_mask(int fe_fd, struct mp_log *log); -int dvb_open_devices(dvb_priv_t *priv, unsigned int n, unsigned int demux_cnt); +int dvb_open_devices(dvb_priv_t *priv, unsigned int adapter, + unsigned int frontend, unsigned int demux_cnt); int dvb_fix_demuxes(dvb_priv_t *priv, unsigned int cnt); int dvb_set_ts_filt(dvb_priv_t *priv, int fd, uint16_t pid, dmx_pes_type_t pestype); int dvb_get_pmt_pid(dvb_priv_t *priv, int card, int service_id); diff --git a/stream/dvbin.h b/stream/dvbin.h index 284ccbd450..01a70588a5 100644 --- a/stream/dvbin.h +++ b/stream/dvbin.h @@ -26,6 +26,9 @@ #include #include +#define MAX_ADAPTERS 16 +#define MAX_FRONTENDS 8 + #undef DVB_ATSC #if defined(DVB_API_VERSION_MINOR) @@ -69,7 +72,8 @@ typedef struct { unsigned int freq, srate, diseqc; char pol; unsigned int tpid, dpid1, dpid2, progid, ca, pids[DMX_FILTER_SIZE], pids_cnt; - bool is_dvb_x2; + bool is_dvb_x2; /* Used only in dvb_get_channels() and parse_vdr_par_string(), use delsys. */ + unsigned int frontend; unsigned int delsys; unsigned int stream_id; unsigned int service_id; @@ -90,7 +94,7 @@ typedef struct { typedef struct { int devno; - unsigned int delsys_mask; + unsigned int delsys_mask[MAX_FRONTENDS]; dvb_channels_list_t *list; } dvb_adapter_config_t; @@ -98,6 +102,7 @@ typedef struct { unsigned int adapters_count; dvb_adapter_config_t *adapters; unsigned int cur_adapter; + unsigned int cur_frontend; int fe_fd; int dvr_fd; diff --git a/stream/stream_dvb.c b/stream/stream_dvb.c index c53753ad31..02c5878ca9 100644 --- a/stream/stream_dvb.c +++ b/stream/stream_dvb.c @@ -2,7 +2,7 @@ dvbstream (C) Dave Chapman 2001, 2002. - (C) Rozhuk Ivan 2016 + (C) Rozhuk Ivan 2016 - 2017 Original authors: Nico, probably Arpi @@ -62,7 +62,6 @@ #error GPL only #endif -#define MAX_ADAPTERS 16 #define CHANNEL_LINE_LEN 256 #define min(a, b) ((a) <= (b) ? (a) : (b)) @@ -253,6 +252,7 @@ static dvb_channels_list_t *dvb_get_channels(struct mp_log *log, dvb_channels_list_t *list_add, int cfg_full_transponder, char *filename, + unsigned int frontend, int delsys, unsigned int delsys_mask) { dvb_channels_list_t *list = list_add; @@ -331,6 +331,7 @@ static dvb_channels_list_t *dvb_get_channels(struct mp_log *log, ptr->freq = 0; ptr->service_id = -1; ptr->is_dvb_x2 = false; + ptr->frontend = frontend; ptr->delsys = delsys; ptr->diseqc = 0; ptr->stream_id = NO_STREAM_ID_FILTER; @@ -791,9 +792,10 @@ int dvb_set_channel(stream_t *stream, unsigned int adapter, unsigned int n) state->retry = 0; //empty both the stream's and driver's buffer while (dvb_streaming_read(stream, buf, sizeof(buf)) > 0) {} - if (state->cur_adapter != adapter) { + if (state->cur_adapter != adapter || + state->cur_frontend != channel->frontend) { dvbin_close(stream); - if (!dvb_open_devices(priv, devno, channel->pids_cnt)) { + if (!dvb_open_devices(priv, devno, channel->frontend, channel->pids_cnt)) { MP_ERR(stream, "DVB_SET_CHANNEL, COULDN'T OPEN DEVICES OF " "ADAPTER: %d, EXIT\n", devno); return 0; @@ -805,14 +807,13 @@ int dvb_set_channel(stream_t *stream, unsigned int adapter, unsigned int n) return 0; } } else { - if (!dvb_open_devices(priv, devno, channel->pids_cnt)) { + if (!dvb_open_devices(priv, devno, channel->frontend, channel->pids_cnt)) { MP_ERR(stream, "DVB_SET_CHANNEL2, COULDN'T OPEN DEVICES OF " "ADAPTER: %d, EXIT\n", devno); return 0; } } - state->cur_adapter = adapter; state->retry = 5; new_list->current = n; MP_VERBOSE(stream, "DVB_SET_CHANNEL: new channel name=%s, adapter: %d, " @@ -830,8 +831,10 @@ int dvb_set_channel(stream_t *stream, unsigned int adapter, unsigned int n) return 0; } - state->last_freq = channel->freq; state->is_on = 1; + state->last_freq = channel->freq; + state->cur_adapter = adapter; + state->cur_frontend = channel->frontend; if (channel->service_id != -1) { /* We need the PMT-PID in addition. @@ -994,6 +997,8 @@ void dvbin_close(stream_t *stream) state->fe_fd = state->dvr_fd = -1; state->is_on = 0; + state->cur_adapter = -1; + state->cur_frontend = -1; pthread_mutex_lock(&global_dvb_state_lock); dvb_free_state(state); @@ -1044,8 +1049,6 @@ static int dvb_streaming_start(stream_t *stream, char *progname) } - - static int dvb_open(stream_t *stream) { // I don't force the file format because, although it's almost always TS, @@ -1081,6 +1084,7 @@ static int dvb_open(stream_t *stream) // The following setup only has to be done once. state->cur_adapter = -1; + state->cur_frontend = -1; for (i = 0; i < state->adapters_count; i++) { if (state->adapters[i].devno == priv->cfg_devno) { state->cur_adapter = i; @@ -1133,7 +1137,7 @@ dvb_state_t *dvb_get_state(stream_t *stream) struct mp_log *log = stream->log; struct mpv_global *global = stream->global; dvb_priv_t *priv = stream->priv; - unsigned int delsys, delsys_mask, size; + unsigned int delsys, delsys_mask[MAX_FRONTENDS], size; char filename[PATH_MAX], *conf_file; const char *conf_file_name; void *talloc_ctx; @@ -1169,75 +1173,74 @@ dvb_state_t *dvb_get_state(stream_t *stream) state->switching_channel = false; state->stream_used = true; state->fe_fd = state->dvr_fd = -1; - for (int i = 0; i < MAX_ADAPTERS; i++) { - snprintf(filename, sizeof(filename), "/dev/dvb/adapter%d/frontend0", i); - int fd = open(filename, O_RDONLY | O_NONBLOCK | O_CLOEXEC); - if (fd < 0) { - mp_verbose(log, "DVB_CONFIG, can't open device %s, skipping\n", - filename); - continue; - } - - mp_verbose(log, "Opened device %s, FD: %d\n", filename, fd); - delsys_mask = dvb_get_tuner_delsys_mask(fd, log); - delsys_mask &= DELSYS_SUPP_MASK; /* Filter unsupported delivery systems. */ - close(fd); - if (delsys_mask == 0) { - mp_verbose(log, "Frontend device %s has no supported delivery systems.\n", - filename); - continue; /* Skip tuner. */ - } - mp_verbose(log, "Frontend device %s offers some supported delivery systems.\n", - filename); - /* Create channel list for adapter. */ + for (unsigned int i = 0; i < MAX_ADAPTERS; i++) { list = NULL; - for (delsys = 0; delsys < SYS_DVB__COUNT__; delsys++) { - if (!DELSYS_IS_SET(delsys_mask, delsys)) - continue; /* Skip unsupported. */ - - switch (delsys) { - case SYS_DVBC_ANNEX_A: - case SYS_DVBC_ANNEX_C: - conf_file_name = "channels.conf.cbl"; - break; - case SYS_ATSC: - conf_file_name = "channels.conf.atsc"; - break; - case SYS_DVBT: - if (DELSYS_IS_SET(delsys_mask, SYS_DVBT2)) - continue; /* Add all channels later with T2. */ - /* PASSTOUTH */ - case SYS_DVBT2: - conf_file_name = "channels.conf.ter"; - break; - case SYS_DVBS: - if (DELSYS_IS_SET(delsys_mask, SYS_DVBS2)) - continue; /* Add all channels later with S2. */ - /* PASSTOUTH */ - case SYS_DVBS2: - conf_file_name = "channels.conf.sat"; - break; - default: + for (unsigned int f = 0; f < MAX_FRONTENDS; f++) { + snprintf(filename, sizeof(filename), "/dev/dvb/adapter%u/frontend%u", i, f); + int fd = open(filename, O_RDONLY | O_NONBLOCK | O_CLOEXEC); + if (fd < 0) continue; - } - if (priv->cfg_file && priv->cfg_file[0]) { - talloc_ctx = NULL; - conf_file = priv->cfg_file; - } else { - talloc_ctx = talloc_new(NULL); - conf_file = mp_find_config_file(talloc_ctx, global, conf_file_name); - if (conf_file) { - mp_verbose(log, "Ignoring other channels.conf files.\n"); - } else { - conf_file = mp_find_config_file(talloc_ctx, global, - "channels.conf"); + mp_verbose(log, "Opened device %s, FD: %d\n", filename, fd); + delsys_mask[f] = dvb_get_tuner_delsys_mask(fd, log); + delsys_mask[f] &= DELSYS_SUPP_MASK; /* Filter unsupported delivery systems. */ + close(fd); + if (delsys_mask[f] == 0) { + mp_verbose(log, "Frontend device %s has no supported delivery systems.\n", + filename); + continue; /* Skip tuner. */ + } + mp_verbose(log, "Frontend device %s offers some supported delivery systems.\n", + filename); + /* Create channel list for adapter. */ + for (delsys = 0; delsys < SYS_DVB__COUNT__; delsys++) { + if (!DELSYS_IS_SET(delsys_mask[f], delsys)) + continue; /* Skip unsupported. */ + + switch (delsys) { + case SYS_DVBC_ANNEX_A: + case SYS_DVBC_ANNEX_C: + conf_file_name = "channels.conf.cbl"; + break; + case SYS_ATSC: + conf_file_name = "channels.conf.atsc"; + break; + case SYS_DVBT: + if (DELSYS_IS_SET(delsys_mask[f], SYS_DVBT2)) + continue; /* Add all channels later with T2. */ + /* PASSTOUTH */ + case SYS_DVBT2: + conf_file_name = "channels.conf.ter"; + break; + case SYS_DVBS: + if (DELSYS_IS_SET(delsys_mask[f], SYS_DVBS2)) + continue; /* Add all channels later with S2. */ + /* PASSTOUTH */ + case SYS_DVBS2: + conf_file_name = "channels.conf.sat"; + break; + default: + continue; } - } - list = dvb_get_channels(log, list, priv->cfg_full_transponder, conf_file, - delsys, delsys_mask); - talloc_free(talloc_ctx); + if (priv->cfg_file && priv->cfg_file[0]) { + talloc_ctx = NULL; + conf_file = priv->cfg_file; + } else { + talloc_ctx = talloc_new(NULL); + conf_file = mp_find_config_file(talloc_ctx, global, conf_file_name); + if (conf_file) { + mp_verbose(log, "Ignoring other channels.conf files.\n"); + } else { + conf_file = mp_find_config_file(talloc_ctx, global, + "channels.conf"); + } + } + + list = dvb_get_channels(log, list, priv->cfg_full_transponder, + conf_file, f, delsys, delsys_mask[f]); + talloc_free(talloc_ctx); + } } /* Add adapter with non zero channel list. */ if (list == NULL) @@ -1256,7 +1259,8 @@ dvb_state_t *dvb_get_state(stream_t *stream) state->adapters = adapters; state->adapters[state->adapters_count].devno = i; - state->adapters[state->adapters_count].delsys_mask = delsys_mask; + memcpy(&state->adapters[state->adapters_count].delsys_mask, + &delsys_mask, (sizeof(unsigned int) * MAX_FRONTENDS)); state->adapters[state->adapters_count].list = list; state->adapters_count++; }