mirror of https://github.com/mpv-player/mpv
dvb: Add multiple frontends support: MAX_FRONTENDS now 8.
This commit is contained in:
parent
3c4667c862
commit
04d04033e6
|
@ -1,7 +1,7 @@
|
|||
/* dvbtune - tune.c
|
||||
|
||||
Copyright (C) Dave Chapman 2001,2002
|
||||
Copyright (C) Rozhuk Ivan <rozhuk.im@gmail.com> 2016
|
||||
Copyright (C) Rozhuk Ivan <rozhuk.im@gmail.com> 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",
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
#include <linux/dvb/audio.h>
|
||||
#include <linux/dvb/version.h>
|
||||
|
||||
#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;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
dvbstream
|
||||
(C) Dave Chapman <dave@dchapman.com> 2001, 2002.
|
||||
(C) Rozhuk Ivan <rozhuk.im@gmail.com> 2016
|
||||
(C) Rozhuk Ivan <rozhuk.im@gmail.com> 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,20 +1173,19 @@ 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);
|
||||
for (unsigned int i = 0; i < MAX_ADAPTERS; i++) {
|
||||
list = NULL;
|
||||
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) {
|
||||
mp_verbose(log, "DVB_CONFIG, can't open device %s, skipping\n",
|
||||
filename);
|
||||
if (fd < 0)
|
||||
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. */
|
||||
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 == 0) {
|
||||
if (delsys_mask[f] == 0) {
|
||||
mp_verbose(log, "Frontend device %s has no supported delivery systems.\n",
|
||||
filename);
|
||||
continue; /* Skip tuner. */
|
||||
|
@ -1190,9 +1193,8 @@ dvb_state_t *dvb_get_state(stream_t *stream)
|
|||
mp_verbose(log, "Frontend device %s offers some supported delivery systems.\n",
|
||||
filename);
|
||||
/* Create channel list for adapter. */
|
||||
list = NULL;
|
||||
for (delsys = 0; delsys < SYS_DVB__COUNT__; delsys++) {
|
||||
if (!DELSYS_IS_SET(delsys_mask, delsys))
|
||||
if (!DELSYS_IS_SET(delsys_mask[f], delsys))
|
||||
continue; /* Skip unsupported. */
|
||||
|
||||
switch (delsys) {
|
||||
|
@ -1204,14 +1206,14 @@ dvb_state_t *dvb_get_state(stream_t *stream)
|
|||
conf_file_name = "channels.conf.atsc";
|
||||
break;
|
||||
case SYS_DVBT:
|
||||
if (DELSYS_IS_SET(delsys_mask, SYS_DVBT2))
|
||||
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, SYS_DVBS2))
|
||||
if (DELSYS_IS_SET(delsys_mask[f], SYS_DVBS2))
|
||||
continue; /* Add all channels later with S2. */
|
||||
/* PASSTOUTH */
|
||||
case SYS_DVBS2:
|
||||
|
@ -1235,10 +1237,11 @@ dvb_state_t *dvb_get_state(stream_t *stream)
|
|||
}
|
||||
}
|
||||
|
||||
list = dvb_get_channels(log, list, priv->cfg_full_transponder, conf_file,
|
||||
delsys, delsys_mask);
|
||||
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)
|
||||
continue;
|
||||
|
@ -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++;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue