From 6f35d4df5afdd01c9f95cea573ba8b7bf7e89d0a Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 18 Jan 2016 17:50:12 +0100 Subject: cache: add mechanism for disabling readahead Will be used in a following commit. --- stream/cache.c | 17 ++++++++++++++++- stream/stream.h | 1 + 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'stream') diff --git a/stream/cache.c b/stream/cache.c index ff5dd9fca6..8c18d18b1a 100644 --- a/stream/cache.c +++ b/stream/cache.c @@ -96,7 +96,10 @@ struct priv { bool idle; // cache thread has stopped reading int64_t reads; // number of actual read attempts performed + bool enable_readahead; // actively read beyond read() position int64_t read_filepos; // client read position (mirrors cache->pos) + int64_t read_min; // file position until which the thread should + // read even if readahead is disabled int64_t eof_pos; @@ -208,6 +211,11 @@ static void cache_fill(struct priv *s) goto done; } + if (!s->enable_readahead && s->read_min <= s->max_filepos) { + s->idle = true; + return; + } + if (mp_cancel_test(s->cache->cancel)) goto done; @@ -372,6 +380,10 @@ static int cache_get_cached_control(stream_t *cache, int cmd, void *arg) case STREAM_CTRL_GET_CACHE_IDLE: *(int *)arg = s->idle; return STREAM_OK; + case STREAM_CTRL_SET_READAHEAD: + s->enable_readahead = *(int *)arg; + pthread_cond_signal(&s->wakeup); + return STREAM_OK; case STREAM_CTRL_GET_TIME_LENGTH: *(double *)arg = s->stream_time_length; return s->stream_time_length ? STREAM_OK : STREAM_UNSUPPORTED; @@ -447,6 +459,7 @@ static void cache_execute_control(struct priv *s) } else if (pos_changed || (ok && control_needs_flush(s->control))) { MP_VERBOSE(s, "Dropping cache due to control()\n"); s->read_filepos = stream_tell(s->stream); + s->read_min = s->read_filepos; s->control_flush = true; cache_drop_contents(s); } @@ -503,6 +516,7 @@ static int cache_fill_buffer(struct stream *cache, char *buffer, int max_len) double retry_time = 0; int64_t retry = s->reads - 1; // try at least 1 read on EOF while (1) { + s->read_min = s->read_filepos + max_len + 64 * 1024; readb = read_buffer(s, buffer, max_len, s->read_filepos); s->read_filepos += readb; if (readb > 0) @@ -541,7 +555,7 @@ static int cache_seek(stream_t *cache, int64_t pos) MP_ERR(s, "Attempting to seek before cached data in unseekable stream.\n"); r = 0; } else { - cache->pos = s->read_filepos = pos; + cache->pos = s->read_filepos = s->read_min = pos; s->eof = false; // so that cache_read() will actually wait for new data pthread_cond_signal(&s->wakeup); } @@ -616,6 +630,7 @@ int stream_cache_init(stream_t *cache, stream_t *stream, struct priv *s = talloc_zero(NULL, struct priv); s->log = cache->log; s->eof_pos = -1; + s->enable_readahead = true; cache_drop_contents(s); diff --git a/stream/stream.h b/stream/stream.h index 11e70bcb7d..ab37c3b4bd 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -72,6 +72,7 @@ enum stream_ctrl { STREAM_CTRL_GET_CACHE_FILL, STREAM_CTRL_GET_CACHE_IDLE, STREAM_CTRL_RESUME_CACHE, + STREAM_CTRL_SET_READAHEAD, // stream_memory.c STREAM_CTRL_SET_CONTENTS, -- cgit v1.2.3 From 8a9b64329c0e387dc59a1fca477a43c50f59ff34 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 19 Jan 2016 18:36:06 +0100 Subject: Relicense some non-MPlayer source files to LGPL 2.1 or later This covers source files which were added in mplayer2 and mpv times only, and where all code is covered by LGPL relicensing agreements. There are probably more files to which this applies, but I'm being conservative here. A file named ao_sdl.c exists in MPlayer too, but the mpv one is a complete rewrite, and was added some time after the original ao_sdl.c was removed. The same applies to vo_sdl.c, for which the SDL2 API is radically different in addition (MPlayer supports SDL 1.2 only). common.c contains only code written by me. But common.h is a strange case: although it originally was named mp_common.h and exists in MPlayer too, by now it contains only definitions written by uau and me. The exceptions are the CONTROL_ defines - thus not changing the license of common.h yet. codec_tags.c contained once large tables generated from MPlayer's codecs.conf, but all of these tables were removed. From demux_playlist.c I'm removing a code fragment from someone who was not asked; this probably could be done later (see commit 15dccc37). misc.c is a bit complicated to reason about (it was split off mplayer.c and thus contains random functions out of this file), but actually all functions have been added post-MPlayer. Except get_relative_time(), which was written by uau, but looks similar to 3 different versions of something similar in each of the Unix/win32/OSX timer source files. I'm not sure what that means in regards to copyright, so I've just moved it into another still-GPL source file for now. screenshot.c once had some minor parts of MPlayer's vf_screenshot.c, but they're all gone. --- stream/cache_file.c | 15 ++++++++------- stream/stream_avdevice.c | 14 +++++++------- stream/stream_memory.c | 14 +++++++------- 3 files changed, 22 insertions(+), 21 deletions(-) (limited to 'stream') diff --git a/stream/cache_file.c b/stream/cache_file.c index 901b3f6f3b..4cf7060e83 100644 --- a/stream/cache_file.c +++ b/stream/cache_file.c @@ -1,19 +1,20 @@ /* * This file is part of mpv. * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. * * mpv is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see . + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see . */ + #include #include diff --git a/stream/stream_avdevice.c b/stream/stream_avdevice.c index d1fd74f1b3..9734b7b6f5 100644 --- a/stream/stream_avdevice.c +++ b/stream/stream_avdevice.c @@ -1,18 +1,18 @@ /* * This file is part of mpv. * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. * * mpv is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see . + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see . */ #include "config.h" diff --git a/stream/stream_memory.c b/stream/stream_memory.c index a451e0f722..4bcb860c49 100644 --- a/stream/stream_memory.c +++ b/stream/stream_memory.c @@ -1,18 +1,18 @@ /* * This file is part of mpv. * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. * * mpv is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see . + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see . */ #include -- cgit v1.2.3 From e904129b79dffb0ac2c661b164157064d03b9095 Mon Sep 17 00:00:00 2001 From: Oliver Freyermuth Date: Tue, 19 Jan 2016 00:18:08 +0100 Subject: 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. --- stream/dvb_tune.c | 75 ++++++++++++++++++++++++++++++++----- stream/dvb_tune.h | 2 +- stream/stream_dvb.c | 104 ++++++++++++++++++++++++++++------------------------ 3 files changed, 122 insertions(+), 59 deletions(-) (limited to 'stream') diff --git a/stream/dvb_tune.c b/stream/dvb_tune.c index 7ec4bcd9e8..1f982d6887 100644 --- a/stream/dvb_tune.c +++ b/stream/dvb_tune.c @@ -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) diff --git a/stream/dvb_tune.h b/stream/dvb_tune.h index 50c598f810..dafa1175bd 100644 --- a/stream/dvb_tune.h +++ b/stream/dvb_tune.h @@ -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); diff --git a/stream/stream_dvb.c b/stream/stream_dvb.c index 8bc6c4e200..b5ac6ea17a 100644 --- a/stream/stream_dvb.c +++ b/stream/stream_dvb.c @@ -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_typecfg_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) { -- cgit v1.2.3 From ab59c5f5227ea1ea03169f24c99ca75fae80ad1a Mon Sep 17 00:00:00 2001 From: Oliver Freyermuth Date: Wed, 20 Jan 2016 00:29:47 +0100 Subject: stream_dvb: don't requery tuner type, rely on initial query. Saves one unnecessary additional ioctl per tuning by just reusing existing information. Should also fix the case of multiple supported delivery types since we now rely on the initial query from the chosen configuration after channel list parsing instead of requerying the device. --- stream/dvb_tune.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'stream') diff --git a/stream/dvb_tune.c b/stream/dvb_tune.c index 1f982d6887..3c1095cc5d 100644 --- a/stream/dvb_tune.c +++ b/stream/dvb_tune.c @@ -442,8 +442,10 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend, int timeout) { int hi_lo = 0, dfd; + + dvb_state_t* state = priv->state; + struct dvb_frontend_parameters feparams; - struct dvb_frontend_info fe_info; MP_VERBOSE(priv, "TUNE_IT, fd_frontend %d, freq %lu, srate %lu, " "pol %c, tone %i, diseqc %u\n", fd_frontend, @@ -451,12 +453,8 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend, tone, diseqc); memset(&feparams, 0, sizeof(feparams)); - if (ioctl(fd_frontend, FE_GET_INFO, &fe_info) < 0) { - MP_FATAL(priv, "FE_GET_INFO FAILED\n"); - return -1; - } - MP_VERBOSE(priv, "Using DVB card \"%s\"\n", fe_info.name); + MP_VERBOSE(priv, "Using DVB card \"%s\"\n", state->cards[state->card].name); { /* discard stale QPSK events */ @@ -467,8 +465,8 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend, } } - switch (fe_info.type) { - case FE_OFDM: + switch (state->tuner_type) { + case TUNER_TER: if (freq < 1000000) freq *= 1000UL; feparams.frequency = freq; @@ -487,7 +485,7 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend, return -1; } break; - case FE_QPSK: + case TUNER_SAT: // DVB-S if (freq > 2200000) { // this must be an absolute frequency @@ -565,7 +563,7 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend, } #endif break; - case FE_QAM: + case TUNER_CBL: feparams.frequency = freq; feparams.inversion = specInv; feparams.u.qam.symbol_rate = srate; @@ -578,7 +576,7 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend, } break; #ifdef DVB_ATSC - case FE_ATSC: + case TUNER_ATSC: feparams.frequency = freq; feparams.u.vsb.modulation = modulation; MP_VERBOSE(priv, "tuning ATSC to %d, modulation=%d\n", freq, modulation); -- cgit v1.2.3 From 346cf7abf0a6c2ca4404440e24dd79f27fb39a23 Mon Sep 17 00:00:00 2001 From: Oliver Freyermuth Date: Wed, 20 Jan 2016 00:35:54 +0100 Subject: stream_dvb: improve messages on delivery-type detection. No need use use all capital letters, and don't warn if DVB-S2 is supported in addition since we handle that in DVB-S case already. Also, print the delivery system number for still unhandled delivery systems to simplify debugging. --- stream/dvb_tune.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'stream') diff --git a/stream/dvb_tune.c b/stream/dvb_tune.c index 3c1095cc5d..80a240e71b 100644 --- a/stream/dvb_tune.c +++ b/stream/dvb_tune.c @@ -69,25 +69,29 @@ int dvb_get_tuner_types(int fe_fd, struct mp_log *log, int** tuner_types) 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"); + 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"); + 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"); + 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"); + mp_verbose(log, "Tuner type seems to be DVB-ATSC\n"); (*tuner_types)[supported_tuners++] = TUNER_ATSC; break; #endif + case SYS_DVBS2: + // We actually handle that in the DVB-S branch, ok to ignore here. + mp_verbose(log, "Tuner supports DVB-S2\n"); + break; default: - mp_err(log, "UNKNOWN TUNER TYPE\n"); + mp_err(log, "Unhandled tuner type: %d\n", delsys); } } return supported_tuners; @@ -101,29 +105,29 @@ int dvb_get_tuner_types(int fe_fd, struct mp_log *log, int** tuner_types) switch (fe_info.type) { case FE_OFDM: - mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-T\n"); + mp_verbose(log, "Tuner type seems to be DVB-T\n"); *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"); + mp_verbose(log, "Tuner type seems to be DVB-S\n"); *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"); + mp_verbose(log, "Tuner type seems to be DVB-C\n"); *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"); + mp_verbose(log, "Tuner type seems to be DVB-ATSC\n"); *tuner_types = talloc_array(NULL, int, 1); (*tuner_types)[0] = TUNER_ATSC; return 1; #endif default: - mp_err(log, "UNKNOWN TUNER TYPE\n"); + mp_err(log, "Unknown tuner type: %d\n", fe_info.type); return 0; } #endif -- cgit v1.2.3 From b2a5c16a9d8a2b2103d60f0ac1c512800161ac74 Mon Sep 17 00:00:00 2001 From: Oliver Freyermuth Date: Wed, 20 Jan 2016 20:46:15 +0100 Subject: stream_dvb: use DVBv5 API also for DVB-C tuning. Using the new API is a necessity for multiple-delivery-system devices, since the old API does not offer a way to switch the delivery system of the card. This should in principle also be done for DVB-T / ATSC, especially since most DVB-T devices also support DVB-C, but I can not test such an implementation due to lack of hardware (currently) so it seems better to leave the existing, tested code-path in place for now. --- stream/dvb_tune.c | 47 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) (limited to 'stream') diff --git a/stream/dvb_tune.c b/stream/dvb_tune.c index 80a240e71b..de43907217 100644 --- a/stream/dvb_tune.c +++ b/stream/dvb_tune.c @@ -470,7 +470,7 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend, } switch (state->tuner_type) { - case TUNER_TER: + case TUNER_TER: { if (freq < 1000000) freq *= 1000UL; feparams.frequency = freq; @@ -488,8 +488,9 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend, MP_ERR(priv, "ERROR tuning channel\n"); return -1; } - break; - case TUNER_SAT: + } + break; + case TUNER_SAT: { // DVB-S if (freq > 2200000) { // this must be an absolute frequency @@ -566,8 +567,35 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend, return -1; } #endif - break; - case TUNER_CBL: + } + break; + case TUNER_CBL: { +#ifdef DVB_USE_S2API + /* S2API is the DVB API new since 2.6.28. + * It is also needed for devices supporting multiple delivery systems, + * commonly DVB-C + DVB-T are supported here. + */ + fe_delivery_system_t delsys = SYS_DVBC_ANNEX_AC; + struct dtv_property p[] = { + { .cmd = DTV_DELIVERY_SYSTEM, .u.data = delsys }, + { .cmd = DTV_FREQUENCY, .u.data = freq }, + { .cmd = DTV_INVERSION, .u.data = specInv }, + { .cmd = DTV_MODULATION, .u.data = modulation }, + { .cmd = DTV_SYMBOL_RATE, .u.data = srate }, + { .cmd = DTV_INNER_FEC, .u.data = HP_CodeRate }, + { .cmd = DTV_TUNE }, + }; + struct dtv_properties cmdseq = { + .num = sizeof(p) / sizeof(p[0]), + .props = p + }; + MP_VERBOSE(priv, "tuning DVB-C to %d, srate=%d using DVBv5 API...\n", + freq, srate); + if ((ioctl(fd_frontend, FE_SET_PROPERTY, &cmdseq)) == -1) { + MP_ERR(priv, "ERROR tuning channel\n"); + return -1; + } +#else feparams.frequency = freq; feparams.inversion = specInv; feparams.u.qam.symbol_rate = srate; @@ -578,9 +606,11 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend, MP_ERR(priv, "ERROR tuning channel\n"); return -1; } - break; +#endif + } + break; #ifdef DVB_ATSC - case TUNER_ATSC: + case TUNER_ATSC: { feparams.frequency = freq; feparams.u.vsb.modulation = modulation; MP_VERBOSE(priv, "tuning ATSC to %d, modulation=%d\n", freq, modulation); @@ -588,7 +618,8 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend, MP_ERR(priv, "ERROR tuning channel\n"); return -1; } - break; + } + break; #endif default: MP_VERBOSE(priv, "Unknown FE type. Aborting\n"); -- cgit v1.2.3 From 9a2a0b0bba600a76d405c64c7c8331ad3fade22f Mon Sep 17 00:00:00 2001 From: Oliver Freyermuth Date: Wed, 20 Jan 2016 20:56:10 +0100 Subject: stream_dvb: add verbose output in non-DVBv5 querying. May help in future debugging in case of old kernels with modern / obscure devices. --- stream/dvb_tune.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'stream') diff --git a/stream/dvb_tune.c b/stream/dvb_tune.c index de43907217..7b19f2df39 100644 --- a/stream/dvb_tune.c +++ b/stream/dvb_tune.c @@ -102,7 +102,9 @@ int dvb_get_tuner_types(int fe_fd, struct mp_log *log, int** tuner_types) mp_err(log, "FE_GET_INFO error: %d, FD: %d\n\n", errno, fe_fd); return 0; } - + + mp_verbose(log, "Queried tuner type of device named '%s', FD: %d\n", + fe_info.name, fe_fd); switch (fe_info.type) { case FE_OFDM: mp_verbose(log, "Tuner type seems to be DVB-T\n"); -- cgit v1.2.3 From ff4bd73fcbad60c1734891aca78d89d8ca0ea1b2 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 22 Jan 2016 11:43:46 +0100 Subject: dvb: fix compilation with older Linux headers At least DTV_ENUM_DELSYS is not available in older versions. It's hard to tell when this identifier was introduced, but it appears it was probably API version 5.5. --- stream/dvbin.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'stream') diff --git a/stream/dvbin.h b/stream/dvbin.h index e0688aa79e..9c2eb35e26 100644 --- a/stream/dvbin.h +++ b/stream/dvbin.h @@ -28,9 +28,10 @@ * Version 5 is also called S2API, it adds support for tuning to S2 channels * and is extensible for future delivery systems. Old API is deprecated. * StreamID-implementation only supported since API >=5.2. + * At least DTV_ENUM_DELSYS requires 5.5. */ -#if (DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 2) +#if (DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 5) #define DVB_USE_S2API 1 // This had a different name until API 5.8. -- cgit v1.2.3 From 2df448b1f383ebb7d29bf64a1cfb827eb1fff70b Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 22 Jan 2016 11:55:47 +0100 Subject: dvb: remove trailing whitespace --- stream/dvb_tune.c | 20 ++++++++++---------- stream/stream_dvb.c | 16 ++++++++-------- 2 files changed, 18 insertions(+), 18 deletions(-) (limited to 'stream') diff --git a/stream/dvb_tune.c b/stream/dvb_tune.c index 7b19f2df39..b83da040d0 100644 --- a/stream/dvb_tune.c +++ b/stream/dvb_tune.c @@ -43,7 +43,7 @@ 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. + /* 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}; @@ -63,9 +63,9 @@ int dvb_get_tuner_types(int fe_fd, struct mp_log *log, int** 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, + /* 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: @@ -141,7 +141,7 @@ int dvb_open_devices(dvb_priv_t *priv, int n, int demux_cnt) char frontend_dev[32], dvr_dev[32], demux_dev[32]; dvb_state_t* state = priv->state; - + sprintf(frontend_dev, "/dev/dvb/adapter%d/frontend0", n); sprintf(dvr_dev, "/dev/dvb/adapter%d/dvr0", n); sprintf(demux_dev, "/dev/dvb/adapter%d/demux0", n); @@ -180,7 +180,7 @@ int dvb_fix_demuxes(dvb_priv_t *priv, int cnt) { int i; char demux_dev[32]; - + dvb_state_t* state = priv->state; sprintf(demux_dev, "/dev/dvb/adapter%d/demux0", state->card); @@ -435,7 +435,7 @@ static int do_diseqc(int secfd, int sat_no, int polv, int hi_lo) (sat_no / 4) % 2 ? SEC_MINI_B : SEC_MINI_A); } -static int tune_it(dvb_priv_t *priv, int fd_frontend, +static int tune_it(dvb_priv_t *priv, int fd_frontend, unsigned int freq, unsigned int srate, char pol, int tone, bool is_dvb_s2, int stream_id, fe_spectral_inversion_t specInv, unsigned int diseqc, @@ -454,7 +454,7 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend, struct dvb_frontend_parameters feparams; MP_VERBOSE(priv, "TUNE_IT, fd_frontend %d, freq %lu, srate %lu, " - "pol %c, tone %i, diseqc %u\n", fd_frontend, + "pol %c, tone %i, diseqc %u\n", fd_frontend, (long unsigned int)freq, (long unsigned int)srate, pol, tone, diseqc); @@ -574,8 +574,8 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend, case TUNER_CBL: { #ifdef DVB_USE_S2API /* S2API is the DVB API new since 2.6.28. - * It is also needed for devices supporting multiple delivery systems, - * commonly DVB-C + DVB-T are supported here. + * It is also needed for devices supporting multiple delivery systems, + * commonly DVB-C + DVB-T are supported here. */ fe_delivery_system_t delsys = SYS_DVBC_ANNEX_AC; struct dtv_property p[] = { diff --git a/stream/stream_dvb.c b/stream/stream_dvb.c index b5ac6ea17a..352759af15 100644 --- a/stream/stream_dvb.c +++ b/stream/stream_dvb.c @@ -857,14 +857,14 @@ static void dvbin_close(stream_t *stream) dvb_state_t* state = priv->state; if (state->switching_channel && state->is_on) { - // Prevent state destruction, reset channel-switch. + // Prevent state destruction, reset channel-switch. state->switching_channel = false; pthread_mutex_lock(&global_dvb_state_lock); global_dvb_state->stream_used = false; pthread_mutex_unlock(&global_dvb_state_lock); return; } - + for (int i = state->demux_fds_cnt - 1; i >= 0; i--) { state->demux_fds_cnt--; MP_VERBOSE(stream, "DVBIN_CLOSE, close(%d), fd=%d, COUNT=%d\n", i, @@ -877,7 +877,7 @@ static void dvbin_close(stream_t *stream) state->fe_fd = state->dvr_fd = -1; state->is_on = 0; - + pthread_mutex_lock(&global_dvb_state_lock); dvb_free_state(state); global_dvb_state = NULL; @@ -949,7 +949,7 @@ static int dvb_open(stream_t *stream) dvb_state_t* state = dvb_get_state(stream); state->stream_used = true; pthread_mutex_unlock(&global_dvb_state_lock); - + priv->state = state; if (state == NULL) { MP_ERR(stream, "DVB CONFIGURATION IS EMPTY, exit\n"); @@ -957,8 +957,8 @@ static int dvb_open(stream_t *stream) } if (state->is_on != 1) { - // State could be already initialized, for example, we just did a channel switch. - // The following setup only has to be done once. + // State could be already initialized, for example, we just did a channel switch. + // The following setup only has to be done once. state->card = -1; for (i = 0; i < state->count; i++) { @@ -1000,7 +1000,7 @@ static int dvb_open(stream_t *stream) if (!dvb_streaming_start(stream, tuner_type, progname)) return STREAM_ERROR; } - + stream->type = STREAMTYPE_DVB; stream->fill_buffer = dvb_streaming_read; stream->close = dvbin_close; @@ -1031,7 +1031,7 @@ dvb_state_t *dvb_get_state(stream_t *stream) state = malloc(sizeof(dvb_state_t)); if (state == NULL) return NULL; - + state->count = 0; state->switching_channel = false; state->stream_used = true; -- cgit v1.2.3 From 3c4f13c23a0363bcfd9e78650795f8352056f7f2 Mon Sep 17 00:00:00 2001 From: Oliver Freyermuth Date: Sun, 24 Jan 2016 20:20:08 +0100 Subject: dvb: fix segmentation fault in case no valid configuration is found. This was introduced in c55b242 . --- stream/stream_dvb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'stream') diff --git a/stream/stream_dvb.c b/stream/stream_dvb.c index 352759af15..4316adfb56 100644 --- a/stream/stream_dvb.c +++ b/stream/stream_dvb.c @@ -947,14 +947,15 @@ static int dvb_open(stream_t *stream) } dvb_state_t* state = dvb_get_state(stream); - state->stream_used = true; - pthread_mutex_unlock(&global_dvb_state_lock); priv->state = state; if (state == NULL) { MP_ERR(stream, "DVB CONFIGURATION IS EMPTY, exit\n"); + pthread_mutex_unlock(&global_dvb_state_lock); return STREAM_ERROR; } + state->stream_used = true; + pthread_mutex_unlock(&global_dvb_state_lock); if (state->is_on != 1) { // State could be already initialized, for example, we just did a channel switch. -- cgit v1.2.3 From 8e4eee9a9adc0b40b0ad7f182808c77bf24f7c47 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 12 Feb 2016 15:47:25 +0100 Subject: stream_dvb: remove dead code Fixes CID 1350063. --- stream/stream_dvb.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'stream') diff --git a/stream/stream_dvb.c b/stream/stream_dvb.c index 4316adfb56..d0e3cad8d8 100644 --- a/stream/stream_dvb.c +++ b/stream/stream_dvb.c @@ -758,11 +758,6 @@ int dvb_step_channel(stream_t *stream, int dir) MP_VERBOSE(stream, "DVB_STEP_CHANNEL dir %d\n", dir); - if (priv == NULL) { - MP_ERR(stream, "dvb_step_channel: NULL priv_ptr, quit\n"); - return 0; - } - list = state->list; if (list == NULL) { MP_ERR(stream, "dvb_step_channel: NULL list_ptr, quit\n"); -- cgit v1.2.3 From 337ad4fef400df103c8256152ca35512303fba66 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 12 Feb 2016 15:49:44 +0100 Subject: stream_dvb: fix minor resource leaks Fixes CID 1350062 and 1350061. Just for the sake of shutting up Coverity. --- stream/stream_dvb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'stream') diff --git a/stream/stream_dvb.c b/stream/stream_dvb.c index d0e3cad8d8..43ca8ac2b9 100644 --- a/stream/stream_dvb.c +++ b/stream/stream_dvb.c @@ -1101,6 +1101,7 @@ dvb_state_t *dvb_get_state(stream_t *stream) if (tmp == NULL) { mp_err(log, "DVB_CONFIG, can't realloc %d bytes, skipping\n", size); + free(list); continue; } cards = tmp; @@ -1108,6 +1109,8 @@ dvb_state_t *dvb_get_state(stream_t *stream) name = malloc(20); if (name == NULL) { mp_err(log, "DVB_CONFIG, can't realloc 20 bytes, skipping\n"); + free(list); + free(tmp); continue; } -- cgit v1.2.3 From 92ba63079617f6579c276dd3ec54197b56378913 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 28 Feb 2016 19:14:23 +0100 Subject: demux: remove relative seeking Ever since a change in mplayer2 or so, relative seeks were translated to absolute seeks before sending them to the demuxer in most cases. The only exception in current mpv is DVD seeking. Remove the SEEK_ABSOLUTE flag; it's not the implied default. SEEK_FACTOR is kept, because it's sometimes slightly useful for seeking in things like transport streams. (And maybe mkv files without duration set?) DVD seeking is terrible because DVD and libdvdnav are terrible, but mostly because libdvdnav is terrible. libdvdnav does not expose seeking with seek tables. (Although I know xbmc/kodi use an undocumented API that is not declared in the headers by dladdr()ing it - I think the function is dvdnav_jump_to_sector_by_time().) With the current mpv policy if not giving a shit about DVD, just revert our half-working seek hacks and always use dvdnav_time_search(). Relative seeking might get stuck sometimes; in this case --hr-seek=always is recommended. --- stream/stream_dvdnav.c | 37 ++++--------------------------------- 1 file changed, 4 insertions(+), 33 deletions(-) (limited to 'stream') diff --git a/stream/stream_dvdnav.c b/stream/stream_dvdnav.c index e2562dbcbc..d61ca5c937 100644 --- a/stream/stream_dvdnav.c +++ b/stream/stream_dvdnav.c @@ -332,8 +332,7 @@ static int control(stream_t *stream, int cmd, void *arg) case STREAM_CTRL_SEEK_TO_TIME: { double *args = arg; double d = args[0]; // absolute target timestamp - double r = args[1]; // if not SEEK_ABSOLUTE, the base time for d - int flags = args[2]; // from SEEK_* flags (demux.h) + int flags = args[1]; // from SEEK_* flags (demux.h) if (flags & SEEK_HR) d -= 10; // fudge offset; it's a hack, because fuck libdvd* int64_t tm = (int64_t)(d * 90000); @@ -344,37 +343,9 @@ static int control(stream_t *stream, int cmd, void *arg) uint32_t pos, len; if (dvdnav_get_position(dvdnav, &pos, &len) != DVDNAV_STATUS_OK) break; - // The following is convoluted, because we have to translate between - // dvdnav's block/CBR-based seeking bullshit, and the player's - // timestamp-based high-level machinery. - if (!(flags & SEEK_ABSOLUTE) && !(flags & SEEK_HR) && priv->duration > 0) - { - int dir = (flags & SEEK_BACKWARD) ? -1 : 1; - // The user is making a relative seek (translated to absolute), - // and we try not to get the user stuck on "boundaries". So try - // to do block based seeks, which should workaround libdvdnav's - // terrible CBR-based seeking. - d -= r; // relative seek amount in seconds - d = d / (priv->duration / 1000.0) * len; // d is now in blocks - d += pos; // absolute target in blocks - if (dir > 0) - d = MPMAX(d, pos + 1.0); - if (dir < 0) - d = MPMIN(d, pos - 1.0); - d += 0.5; // round - uint32_t target = MPCLAMP(d, 0, len); - MP_VERBOSE(stream, "seek from block %lu to %lu, dir=%d\n", - (unsigned long)pos, (unsigned long)target, dir); - if (dvdnav_sector_search(dvdnav, target, SEEK_SET) != DVDNAV_STATUS_OK) - break; - } else { - // "old" method, should be good enough for large seeks. Used for - // hr-seeks (with fudge offset), because I fear that block-based - // seeking might be off too far for large jumps. - MP_VERBOSE(stream, "seek to PTS %f (%"PRId64")\n", d, tm); - if (dvdnav_time_search(dvdnav, tm) != DVDNAV_STATUS_OK) - break; - } + MP_VERBOSE(stream, "seek to PTS %f (%"PRId64")\n", d, tm); + if (dvdnav_time_search(dvdnav, tm) != DVDNAV_STATUS_OK) + break; stream_drop_buffers(stream); d = dvdnav_get_current_time(dvdnav) / 90000.0f; MP_VERBOSE(stream, "landed at: %f\n", d); -- cgit v1.2.3