1
0
mirror of https://github.com/mpv-player/mpv synced 2025-01-31 04:02:06 +00:00

stream_dvb: support frontends with multiple delivery systems.

Most common case would be DVB-C / DVB-T combination cards.
Cards with multiple delivery systems are only supported
starting from DVBv5 API (Kernel 2.6.38).
In this case, we loop over all delivery systems and
just treat them as different cards would be treated:
They all get their own TUNER-type, channel-list parsing etc.
This commit is contained in:
Oliver Freyermuth 2016-01-19 00:18:08 +01:00 committed by wm4
parent c406f83d37
commit e904129b79
3 changed files with 122 additions and 59 deletions

View File

@ -40,38 +40,93 @@
#include "dvb_tune.h"
#include "common/msg.h"
int dvb_get_tuner_type(int fe_fd, struct mp_log *log)
int dvb_get_tuner_types(int fe_fd, struct mp_log *log, int** tuner_types)
{
#ifdef DVB_USE_S2API
/* S2API is the DVB API new since 2.6.28.
It allows to query frontends with multiple delivery systems. */
struct dtv_property p[] = {{ .cmd = DTV_ENUM_DELSYS }};
struct dtv_properties cmdseq = {.num = 1, .props = p};
mp_verbose(log, "Querying tuner type via DVBv5 API for frontend FD %d\n",
fe_fd);
if ((ioctl(fe_fd, FE_GET_PROPERTY, &cmdseq)) < -0) {
mp_err(log, "FE_GET_PROPERTY error: %d, FD: %d\n\n", errno, fe_fd);
return 0;
}
int num_tuner_types = p[0].u.buffer.len;
mp_verbose(log, "Number of supported delivery systems: %d\n", num_tuner_types);
if (num_tuner_types == 0) {
mp_err(log, "Frontend FD %d returned no delivery systems!", fe_fd);
return 0;
}
(*tuner_types) = talloc_array(NULL, int, num_tuner_types);
int supported_tuners = 0;
for(;p[0].u.buffer.len > 0; p[0].u.buffer.len--) {
fe_delivery_system_t delsys = p[0].u.buffer.data[p[0].u.buffer.len - 1];
/* Second level standards like like DVB-T2, DVB-S2 not treated here -
Cards can usually either only do S/T/C or both levels.
DVB-T2 probably needs more implementation details,
DVB-S2 is treated in the DVB-S branch already. */
switch (delsys) {
case SYS_DVBT:
mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-T\n");
(*tuner_types)[supported_tuners++] = TUNER_TER;
break;
case SYS_DVBC_ANNEX_AC:
mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-C\n");
(*tuner_types)[supported_tuners++] = TUNER_CBL;
break;
case SYS_DVBS:
mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-S\n");
(*tuner_types)[supported_tuners++] = TUNER_SAT;
break;
#ifdef DVB_ATSC
case SYS_ATSC:
mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-ATSC\n");
(*tuner_types)[supported_tuners++] = TUNER_ATSC;
break;
#endif
default:
mp_err(log, "UNKNOWN TUNER TYPE\n");
}
}
return supported_tuners;
#else
struct dvb_frontend_info fe_info;
int res = ioctl(fe_fd, FE_GET_INFO, &fe_info);
if (res < 0) {
mp_err(log, "FE_GET_INFO error: %d, FD: %d\n\n", errno, fe_fd);
return 0;
}
switch (fe_info.type) {
case FE_OFDM:
mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-T\n");
return TUNER_TER;
*tuner_types = talloc_array(NULL, int, 1);
(*tuner_types)[0] = TUNER_TER;
return 1;
case FE_QPSK:
mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-S\n");
return TUNER_SAT;
*tuner_types = talloc_array(NULL, int, 1);
(*tuner_types)[0] = TUNER_SAT;
return 1;
case FE_QAM:
mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-C\n");
return TUNER_CBL;
*tuner_types = talloc_array(NULL, int, 1);
(*tuner_types)[0] = TUNER_CBL;
return 1;
#ifdef DVB_ATSC
case FE_ATSC:
mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-ATSC\n");
return TUNER_ATSC;
*tuner_types = talloc_array(NULL, int, 1);
(*tuner_types)[0] = TUNER_ATSC;
return 1;
#endif
default:
mp_err(log, "UNKNOWN TUNER TYPE\n");
return 0;
}
#endif
}
int dvb_open_devices(dvb_priv_t *priv, int n, int demux_cnt)

View File

@ -23,7 +23,7 @@
struct mp_log;
int dvb_get_tuner_type(int fe_fd, struct mp_log *log);
int dvb_get_tuner_types(int fe_fd, struct mp_log *log, int** tuner_types);
int dvb_open_devices(dvb_priv_t *priv, int n, int demux_cnt);
int dvb_fix_demuxes(dvb_priv_t *priv, int cnt);
int dvb_set_ts_filt(dvb_priv_t *priv, int fd, uint16_t pid, dmx_pes_type_t pestype);

View File

@ -1046,78 +1046,86 @@ dvb_state_t *dvb_get_state(stream_t *stream)
continue;
}
type = dvb_get_tuner_type(fd, log);
mp_verbose(log, "Opened device %s, FD: %d\n", filename, fd);
int* tuner_types = NULL;
int num_tuner_types = dvb_get_tuner_types(fd, log, &tuner_types);
close(fd);
if (type != TUNER_SAT && type != TUNER_TER && type != TUNER_CBL &&
type != TUNER_ATSC) {
mp_verbose(log, "Frontend device %s offers %d supported delivery systems.\n",
filename, num_tuner_types);
for (int num_tuner_type=0; num_tuner_type<num_tuner_types; num_tuner_type++) {
type = tuner_types[num_tuner_type];
if (type != TUNER_SAT && type != TUNER_TER && type != TUNER_CBL &&
type != TUNER_ATSC) {
mp_verbose(log, "DVB_CONFIG, can't detect tuner type of "
"card %d, skipping\n", i);
continue;
}
}
void *talloc_ctx = talloc_new(NULL);
char *conf_file = NULL;
if (priv->cfg_file && priv->cfg_file[0])
void *talloc_ctx = talloc_new(NULL);
char *conf_file = NULL;
if (priv->cfg_file && priv->cfg_file[0])
conf_file = priv->cfg_file;
else {
else {
switch (type) {
case TUNER_TER:
conf_file = mp_find_config_file(talloc_ctx, global,
"channels.conf.ter");
break;
conf_file = mp_find_config_file(talloc_ctx, global,
"channels.conf.ter");
break;
case TUNER_CBL:
conf_file = mp_find_config_file(talloc_ctx, global,
"channels.conf.cbl");
break;
conf_file = mp_find_config_file(talloc_ctx, global,
"channels.conf.cbl");
break;
case TUNER_SAT:
conf_file = mp_find_config_file(talloc_ctx, global,
"channels.conf.sat");
break;
conf_file = mp_find_config_file(talloc_ctx, global,
"channels.conf.sat");
break;
case TUNER_ATSC:
conf_file = mp_find_config_file(talloc_ctx, global,
"channels.conf.atsc");
break;
conf_file = mp_find_config_file(talloc_ctx, global,
"channels.conf.atsc");
break;
}
if (conf_file) {
mp_verbose(log, "Ignoring other channels.conf files.\n");
mp_verbose(log, "Ignoring other channels.conf files.\n");
} else {
conf_file = mp_find_config_file(talloc_ctx, global,
"channels.conf");
conf_file = mp_find_config_file(talloc_ctx, global,
"channels.conf");
}
}
}
list = dvb_get_channels(log, priv->cfg_full_transponder, conf_file,
type);
talloc_free(talloc_ctx);
list = dvb_get_channels(log, priv->cfg_full_transponder, conf_file,
type);
talloc_free(talloc_ctx);
if (list == NULL)
if (list == NULL)
continue;
size = sizeof(dvb_card_config_t) * (state->count + 1);
tmp = realloc(state->cards, size);
size = sizeof(dvb_card_config_t) * (state->count + 1);
tmp = realloc(state->cards, size);
if (tmp == NULL) {
fprintf(stderr, "DVB_CONFIG, can't realloc %d bytes, skipping\n",
size);
if (tmp == NULL) {
mp_err(log, "DVB_CONFIG, can't realloc %d bytes, skipping\n",
size);
continue;
}
cards = tmp;
}
cards = tmp;
name = malloc(20);
if (name == NULL) {
fprintf(stderr, "DVB_CONFIG, can't realloc 20 bytes, skipping\n");
name = malloc(20);
if (name == NULL) {
mp_err(log, "DVB_CONFIG, can't realloc 20 bytes, skipping\n");
continue;
}
}
state->cards = cards;
state->cards[state->count].devno = i;
state->cards[state->count].list = list;
state->cards[state->count].type = type;
snprintf(name, 20, "DVB-%c card n. %d",
type == TUNER_TER ? 'T' : (type == TUNER_CBL ? 'C' : 'S'),
state->count + 1);
state->cards[state->count].name = name;
state->count++;
state->cards = cards;
state->cards[state->count].devno = i;
state->cards[state->count].list = list;
state->cards[state->count].type = type;
snprintf(name, 20, "DVB-%c card n. %d",
type == TUNER_TER ? 'T' : (type == TUNER_CBL ? 'C' : 'S'),
state->count + 1);
state->cards[state->count].name = name;
state->count++;
}
talloc_free(tuner_types);
}
if (state->count == 0) {