diff options
Diffstat (limited to 'stream')
-rw-r--r-- | stream/cache.c | 8 | ||||
-rw-r--r-- | stream/dvb_tune.c | 60 | ||||
-rw-r--r-- | stream/dvbin.h | 21 | ||||
-rw-r--r-- | stream/rar.c | 2 | ||||
-rw-r--r-- | stream/stream.c | 6 | ||||
-rw-r--r-- | stream/stream.h | 2 | ||||
-rw-r--r-- | stream/stream_bluray.c | 2 | ||||
-rw-r--r-- | stream/stream_cdda.c | 2 | ||||
-rw-r--r-- | stream/stream_dvb.c | 323 | ||||
-rw-r--r-- | stream/stream_dvd.c | 2 | ||||
-rw-r--r-- | stream/stream_file.c | 7 | ||||
-rw-r--r-- | stream/stream_lavf.c | 6 |
12 files changed, 275 insertions, 166 deletions
diff --git a/stream/cache.c b/stream/cache.c index c4eaa6e261..ff5dd9fca6 100644 --- a/stream/cache.c +++ b/stream/cache.c @@ -184,8 +184,7 @@ static size_t read_buffer(struct priv *s, unsigned char *dst, } // Runs in the cache thread. -// Returns true if reading was attempted, and the mutex was shortly unlocked. -static bool cache_fill(struct priv *s) +static void cache_fill(struct priv *s) { int64_t read = s->read_filepos; int len = 0; @@ -236,7 +235,7 @@ static bool cache_fill(struct priv *s) if (space < FILL_LIMIT) { s->idle = true; s->reads++; // don't stuck main thread - return false; + return; } // limit to end of buffer (without wrapping) @@ -278,8 +277,6 @@ done: } pthread_cond_signal(&s->wakeup); - - return true; } // This is called both during init and at runtime. @@ -421,6 +418,7 @@ static bool control_needs_flush(int stream_ctrl) case STREAM_CTRL_SET_CURRENT_TITLE: case STREAM_CTRL_RECONNECT: case STREAM_CTRL_DVB_SET_CHANNEL: + case STREAM_CTRL_DVB_SET_CHANNEL_NAME: case STREAM_CTRL_DVB_STEP_CHANNEL: return true; } diff --git a/stream/dvb_tune.c b/stream/dvb_tune.c index fa65156d3c..7ec4bcd9e8 100644 --- a/stream/dvb_tune.c +++ b/stream/dvb_tune.c @@ -79,32 +79,34 @@ int dvb_open_devices(dvb_priv_t *priv, int n, int demux_cnt) int i; 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); - priv->fe_fd = open(frontend_dev, O_RDWR | O_NONBLOCK | O_CLOEXEC); - if (priv->fe_fd < 0) { + 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", frontend_dev, errno); return 0; } - priv->demux_fds_cnt = 0; + state->demux_fds_cnt = 0; MP_VERBOSE(priv, "DVB_OPEN_DEVICES(%d)\n", demux_cnt); for (i = 0; i < demux_cnt; i++) { - priv->demux_fds[i] = open(demux_dev, O_RDWR | O_NONBLOCK | O_CLOEXEC); - if (priv->demux_fds[i] < 0) { + state->demux_fds[i] = open(demux_dev, O_RDWR | O_NONBLOCK | O_CLOEXEC); + if (state->demux_fds[i] < 0) { MP_ERR(priv, "ERROR OPENING DEMUX 0: %d\n", errno); return 0; } else { MP_VERBOSE(priv, "OPEN(%d), file %s: FD=%d, CNT=%d\n", i, demux_dev, - priv->demux_fds[i], priv->demux_fds_cnt); - priv->demux_fds_cnt++; + state->demux_fds[i], state->demux_fds_cnt); + state->demux_fds_cnt++; } } - priv->dvr_fd = open(dvr_dev, O_RDONLY | O_NONBLOCK | O_CLOEXEC); - if (priv->dvr_fd < 0) { + state->dvr_fd = open(dvr_dev, O_RDONLY | O_NONBLOCK | O_CLOEXEC); + if (state->dvr_fd < 0) { MP_ERR(priv, "ERROR OPENING DVR DEVICE %s: %d\n", dvr_dev, errno); return 0; } @@ -117,25 +119,27 @@ int dvb_fix_demuxes(dvb_priv_t *priv, int cnt) { int i; char demux_dev[32]; - - sprintf(demux_dev, "/dev/dvb/adapter%d/demux0", priv->card); - MP_VERBOSE(priv, "FIX %d -> %d\n", priv->demux_fds_cnt, cnt); - if (priv->demux_fds_cnt >= cnt) { - for (i = priv->demux_fds_cnt - 1; i >= cnt; i--) { - MP_VERBOSE(priv, "FIX, CLOSE fd(%d): %d\n", i, priv->demux_fds[i]); - close(priv->demux_fds[i]); + + dvb_state_t* state = priv->state; + + sprintf(demux_dev, "/dev/dvb/adapter%d/demux0", state->card); + MP_VERBOSE(priv, "FIX %d -> %d\n", state->demux_fds_cnt, cnt); + if (state->demux_fds_cnt >= cnt) { + for (i = state->demux_fds_cnt - 1; i >= cnt; i--) { + MP_VERBOSE(priv, "FIX, CLOSE fd(%d): %d\n", i, state->demux_fds[i]); + close(state->demux_fds[i]); } - priv->demux_fds_cnt = cnt; - } else if (priv->demux_fds_cnt < cnt) { - for (i = priv->demux_fds_cnt; i < cnt; i++) { - priv->demux_fds[i] = open(demux_dev, + state->demux_fds_cnt = cnt; + } else if (state->demux_fds_cnt < cnt) { + for (i = state->demux_fds_cnt; i < cnt; i++) { + state->demux_fds[i] = open(demux_dev, O_RDWR | O_NONBLOCK | O_CLOEXEC); - MP_VERBOSE(priv, "FIX, OPEN fd(%d): %d\n", i, priv->demux_fds[i]); - if (priv->demux_fds[i] < 0) { + MP_VERBOSE(priv, "FIX, OPEN fd(%d): %d\n", i, state->demux_fds[i]); + if (state->demux_fds[i] < 0) { MP_ERR(priv, "ERROR OPENING DEMUX 0: %d\n", errno); return 0; } else - priv->demux_fds_cnt++; + state->demux_fds_cnt++; } } @@ -370,7 +374,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, int fd_sec, +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, @@ -386,8 +390,8 @@ static int tune_it(dvb_priv_t *priv, int fd_frontend, int fd_sec, struct dvb_frontend_parameters feparams; struct dvb_frontend_info fe_info; - MP_VERBOSE(priv, "TUNE_IT, fd_frontend %d, fd_sec %d\nfreq %lu, srate %lu, " - "pol %c, tone %i, diseqc %u\n", fd_frontend, fd_sec, + MP_VERBOSE(priv, "TUNE_IT, fd_frontend %d, freq %lu, srate %lu, " + "pol %c, tone %i, diseqc %u\n", fd_frontend, (long unsigned int)freq, (long unsigned int)srate, pol, tone, diseqc); @@ -548,7 +552,9 @@ int dvb_tune(dvb_priv_t *priv, int freq, char pol, int srate, int diseqc, { MP_INFO(priv, "dvb_tune Freq: %lu\n", (long unsigned int) freq); - int ris = tune_it(priv, priv->fe_fd, priv->sec_fd, freq, srate, pol, tone, + dvb_state_t* state = priv->state; + + int ris = tune_it(priv, state->fe_fd, freq, srate, pol, tone, is_dvb_s2, stream_id, specInv, diseqc, modulation, HP_CodeRate, TransmissionMode, guardInterval, bandWidth, LP_CodeRate, hier, timeout); diff --git a/stream/dvbin.h b/stream/dvbin.h index baa7ba4e13..e0688aa79e 100644 --- a/stream/dvbin.h +++ b/stream/dvbin.h @@ -90,25 +90,26 @@ typedef struct { typedef struct { int count; dvb_card_config_t *cards; - void *priv; -} dvb_config_t; -typedef struct dvb_params { - struct mp_log *log; - int fd; int card; int fe_fd; - int sec_fd; - int demux_fd[3], demux_fds[DMX_FILTER_SIZE], demux_fds_cnt; int dvr_fd; + int demux_fd[3], demux_fds[DMX_FILTER_SIZE], demux_fds_cnt; - dvb_config_t *config; dvb_channels_list *list; int tuner_type; int is_on; int retry; int timeout; int last_freq; + bool switching_channel; + bool stream_used; +} dvb_state_t; + +typedef struct dvb_params { + struct mp_log *log; + + dvb_state_t *state; char *cfg_prog; int cfg_card; @@ -125,7 +126,7 @@ typedef struct dvb_params { int dvb_step_channel(stream_t *, int); int dvb_set_channel(stream_t *, int, int); -dvb_config_t *dvb_get_config(stream_t *); -void dvb_free_config(dvb_config_t *config); +dvb_state_t *dvb_get_state(stream_t *); +void dvb_free_state(dvb_state_t *); #endif /* MPLAYER_DVBIN_H */ diff --git a/stream/rar.c b/stream/rar.c index d0dbc8d736..9a74097ce7 100644 --- a/stream/rar.c +++ b/stream/rar.c @@ -31,7 +31,7 @@ #include <libavutil/intreadwrite.h> -#include "talloc.h" +#include "mpv_talloc.h" #include "common/common.h" #include "stream.h" #include "rar.h" diff --git a/stream/stream.c b/stream/stream.c index 1ceb184c48..1048a8006d 100644 --- a/stream/stream.c +++ b/stream/stream.c @@ -29,7 +29,7 @@ #include "osdep/atomics.h" #include "osdep/io.h" -#include "talloc.h" +#include "mpv_talloc.h" #include "config.h" @@ -500,7 +500,7 @@ int stream_fill_buffer(stream_t *s) } // Read between 1..buf_size bytes of data, return how much data has been read. -// Return 0 on EOF, error, of if buf_size was 0. +// Return 0 on EOF, error, or if buf_size was 0. int stream_read_partial(stream_t *s, char *buf, int buf_size) { assert(s->buf_pos <= s->buf_len); @@ -914,7 +914,7 @@ struct bstr stream_read_complete(struct stream *s, void *talloc_ctx, int total_read = 0; int padding = 1; char *buf = NULL; - int64_t size = stream_get_size(s); + int64_t size = stream_get_size(s) - stream_tell(s); if (size > max_size) return (struct bstr){NULL, 0}; if (size > 0) diff --git a/stream/stream.h b/stream/stream.h index 28a6ba6bc9..11e70bcb7d 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -98,6 +98,8 @@ enum stream_ctrl { STREAM_CTRL_TV_STEP_CHAN, STREAM_CTRL_TV_LAST_CHAN, STREAM_CTRL_DVB_SET_CHANNEL, + STREAM_CTRL_DVB_SET_CHANNEL_NAME, + STREAM_CTRL_DVB_GET_CHANNEL_NAME, STREAM_CTRL_DVB_STEP_CHANNEL, // Optical discs diff --git a/stream/stream_bluray.c b/stream/stream_bluray.c index b40c3275b3..7a58d888b9 100644 --- a/stream/stream_bluray.c +++ b/stream/stream_bluray.c @@ -38,7 +38,7 @@ #include <libavutil/common.h> #include "config.h" -#include "talloc.h" +#include "mpv_talloc.h" #include "common/common.h" #include "common/msg.h" #include "options/m_option.h" diff --git a/stream/stream_cdda.c b/stream/stream_cdda.c index 6781f4a0ad..8fadf3452a 100644 --- a/stream/stream_cdda.c +++ b/stream/stream_cdda.c @@ -37,7 +37,7 @@ #include <stdlib.h> #include <stdbool.h> -#include "talloc.h" +#include "mpv_talloc.h" #include "stream.h" #include "options/m_option.h" diff --git a/stream/stream_dvb.c b/stream/stream_dvb.c index 0510143b48..8bc6c4e200 100644 --- a/stream/stream_dvb.c +++ b/stream/stream_dvb.c @@ -40,6 +40,7 @@ #include <unistd.h> #include <fcntl.h> #include <errno.h> +#include <pthread.h> #include <libavutil/avstring.h> @@ -47,6 +48,7 @@ #include "misc/ctype.h" #include "stream.h" +#include "common/tags.h" #include "options/m_config.h" #include "options/m_option.h" #include "options/options.h" @@ -61,6 +63,9 @@ #define OPT_BASE_STRUCT struct dvb_params +static dvb_state_t* global_dvb_state = NULL; +static pthread_mutex_t global_dvb_state_lock = PTHREAD_MUTEX_INITIALIZER; + /// URL definition static const m_option_t stream_params[] = { OPT_STRING("prog", cfg_prog, 0), @@ -576,22 +581,22 @@ static dvb_channels_list *dvb_get_channels(struct mp_log *log, return list; } -void dvb_free_config(dvb_config_t *config) +void dvb_free_state(dvb_state_t *state) { int i, j; - for (i = 0; i < config->count; i++) { - free(config->cards[i].name); - if (!config->cards[i].list) + for (i = 0; i < state->count; i++) { + free(state->cards[i].name); + if (!state->cards[i].list) continue; - if (config->cards[i].list->channels) { - for (j = 0; j < config->cards[i].list->NUM_CHANNELS; j++) - free(config->cards[i].list->channels[j].name); - free(config->cards[i].list->channels); + if (state->cards[i].list->channels) { + for (j = 0; j < state->cards[i].list->NUM_CHANNELS; j++) + free(state->cards[i].list->channels[j].name); + free(state->cards[i].list->channels); } - free(config->cards[i].list); + free(state->cards[i].list); } - free(config); + free(state); } static int dvb_streaming_read(stream_t *stream, char *buffer, int size) @@ -599,12 +604,13 @@ static int dvb_streaming_read(stream_t *stream, char *buffer, int size) struct pollfd pfds[1]; int pos = 0, tries, rk, fd; dvb_priv_t *priv = (dvb_priv_t *) stream->priv; + dvb_state_t* state = priv->state; MP_TRACE(stream, "dvb_streaming_read(%d)\n", size); - tries = priv->retry + 1; + tries = state->retry + 1; - fd = priv->fd; + fd = state->dvr_fd; while (pos < size) { pfds[0].fd = fd; pfds[0].events = POLLIN | POLLPRI; @@ -642,18 +648,18 @@ int dvb_set_channel(stream_t *stream, int card, int n) dvb_channel_t *channel; dvb_priv_t *priv = stream->priv; char buf[4096]; - dvb_config_t *conf = (dvb_config_t *) priv->config; + dvb_state_t *state = (dvb_state_t *) priv->state; int devno; int i; - if ((card < 0) || (card > conf->count)) { + if ((card < 0) || (card > state->count)) { MP_ERR(stream, "dvb_set_channel: INVALID CARD NUMBER: %d vs %d, abort\n", - card, conf->count); + card, state->count); return 0; } - devno = conf->cards[card].devno; - new_list = conf->cards[card].list; + devno = state->cards[card].devno; + new_list = state->cards[card].list; if ((n > new_list->NUM_CHANNELS) || (n < 0)) { MP_ERR(stream, "dvb_set_channel: INVALID CHANNEL NUMBER: %d, for " "card %d, abort\n", n, card); @@ -661,14 +667,14 @@ int dvb_set_channel(stream_t *stream, int card, int n) } channel = &(new_list->channels[n]); - if (priv->is_on) { //the fds are already open and we have to stop the demuxers - for (i = 0; i < priv->demux_fds_cnt; i++) - dvb_demux_stop(priv->demux_fds[i]); + if (state->is_on) { //the fds are already open and we have to stop the demuxers + for (i = 0; i < state->demux_fds_cnt; i++) + dvb_demux_stop(state->demux_fds[i]); - priv->retry = 0; + state->retry = 0; //empty both the stream's and driver's buffer while (dvb_streaming_read(stream, buf, 4096) > 0) {} - if (priv->card != card) { + if (state->card != card) { dvbin_close(stream); if (!dvb_open_devices(priv, devno, channel->pids_cnt)) { MP_ERR(stream, "DVB_SET_CHANNEL, COULDN'T OPEN DEVICES OF " @@ -689,17 +695,16 @@ int dvb_set_channel(stream_t *stream, int card, int n) } } - priv->card = card; - priv->list = new_list; - priv->retry = 5; + state->card = card; + state->list = new_list; + state->retry = 5; new_list->current = n; - priv->fd = priv->dvr_fd; MP_VERBOSE(stream, "DVB_SET_CHANNEL: new channel name=%s, card: %d, " "channel %d\n", channel->name, card, n); stream_drop_buffers(stream); - if (channel->freq != priv->last_freq) { + if (channel->freq != state->last_freq) { if (!dvb_tune(priv, channel->freq, channel->pol, channel->srate, channel->diseqc, channel->tone, channel->is_dvb_s2, channel->stream_id, channel->inv, @@ -709,8 +714,8 @@ int dvb_set_channel(stream_t *stream, int card, int n) return 0; } - priv->last_freq = channel->freq; - priv->is_on = 1; + state->last_freq = channel->freq; + state->is_on = 1; if (channel->service_id != -1) { /* We need the PMT-PID in addition. @@ -735,7 +740,7 @@ int dvb_set_channel(stream_t *stream, int card, int n) MP_ERR(stream, "DVB_SET_CHANNEL: PMT-PID not found, " "teletext-decoding may fail.\n"); } else { - if (!dvb_set_ts_filt(priv, priv->demux_fds[i], channel->pids[i], + if (!dvb_set_ts_filt(priv, state->demux_fds[i], channel->pids[i], DMX_PES_OTHER)) return 0; } @@ -749,6 +754,7 @@ int dvb_step_channel(stream_t *stream, int dir) int new_current; dvb_channels_list *list; dvb_priv_t *priv = stream->priv; + dvb_state_t* state = priv->state; MP_VERBOSE(stream, "DVB_STEP_CHANNEL dir %d\n", dir); @@ -757,7 +763,7 @@ int dvb_step_channel(stream_t *stream, int dir) return 0; } - list = priv->list; + list = state->list; if (list == NULL) { MP_ERR(stream, "dvb_step_channel: NULL list_ptr, quit\n"); return 0; @@ -766,7 +772,7 @@ int dvb_step_channel(stream_t *stream, int dir) new_current = (list->NUM_CHANNELS + list->current + (dir >= 0 ? 1 : -1)) % list->NUM_CHANNELS; - return dvb_set_channel(stream, priv->card, new_current); + return dvb_set_channel(stream, state->card, new_current); } static int dvbin_stream_control(struct stream *s, int cmd, void *arg) @@ -776,33 +782,106 @@ static int dvbin_stream_control(struct stream *s, int cmd, void *arg) case STREAM_CTRL_DVB_SET_CHANNEL: { int *iarg = arg; r = dvb_set_channel(s, iarg[1], iarg[0]); - return r ? STREAM_OK : STREAM_ERROR; + if (r) { + // Stream will be pulled down after channel switch, + // persist state. + dvb_priv_t *priv = (dvb_priv_t *) s->priv; + dvb_state_t* state = priv->state; + state->switching_channel = true; + return STREAM_OK; + } + return STREAM_ERROR; + } + case STREAM_CTRL_DVB_SET_CHANNEL_NAME: { + char *progname = *((char**)arg); + dvb_priv_t *priv = (dvb_priv_t *) s->priv; + dvb_state_t* state = priv->state; + int new_channel = -1; + for (int i=0; i < state->list->NUM_CHANNELS; ++i) { + if (!strcmp(state->list->channels[i].name, progname)) { + new_channel = i; + break; + } + } + if (new_channel == -1) { + MP_ERR(s, "Program '%s' not found for card %d!\n", + progname, state->card); + return STREAM_ERROR; + } + r = dvb_set_channel(s, state->card, new_channel); + if (r) { + // Stream will be pulled down after channel switch, + // persist state. + state->switching_channel = true; + return STREAM_OK; + } + return STREAM_ERROR; } - case STREAM_CTRL_DVB_STEP_CHANNEL: + case STREAM_CTRL_DVB_STEP_CHANNEL: { r = dvb_step_channel(s, *(int *)arg); - return r ? STREAM_OK : STREAM_ERROR; + if (r) { + // Stream will be pulled down after channel switch, + // persist state. + dvb_priv_t *priv = (dvb_priv_t *) s->priv; + dvb_state_t* state = priv->state; + state->switching_channel = true; + return STREAM_OK; + } + return STREAM_ERROR; + } + case STREAM_CTRL_DVB_GET_CHANNEL_NAME: { + dvb_priv_t *priv = (dvb_priv_t *) s->priv; + dvb_state_t* state = priv->state; + int current_channel = state->list->current; + char* progname = state->list->channels[current_channel].name; + *(char **)arg = talloc_strdup(NULL, progname); + return STREAM_OK; + } + case STREAM_CTRL_GET_METADATA: { + struct mp_tags* metadata = talloc_zero(NULL, struct mp_tags); + dvb_priv_t *priv = (dvb_priv_t *) s->priv; + dvb_state_t* state = priv->state; + int current_channel = state->list->current; + char* progname = state->list->channels[current_channel].name; + mp_tags_set_str(metadata, "title", progname); + *(struct mp_tags **)arg = metadata; + return STREAM_OK; + } } return STREAM_UNSUPPORTED; } static void dvbin_close(stream_t *stream) { - int i; dvb_priv_t *priv = (dvb_priv_t *) stream->priv; - - for (i = priv->demux_fds_cnt - 1; i >= 0; i--) { - priv->demux_fds_cnt--; + dvb_state_t* state = priv->state; + + if (state->switching_channel && state->is_on) { + // 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, - priv->demux_fds[i], priv->demux_fds_cnt); - close(priv->demux_fds[i]); + state->demux_fds[i], state->demux_fds_cnt); + close(state->demux_fds[i]); } - close(priv->dvr_fd); + close(state->dvr_fd); - close(priv->fe_fd); - priv->fe_fd = priv->sec_fd = priv->dvr_fd = -1; + close(state->fe_fd); + state->fe_fd = state->dvr_fd = -1; - priv->is_on = 0; - dvb_free_config(priv->config); + state->is_on = 0; + + pthread_mutex_lock(&global_dvb_state_lock); + dvb_free_state(state); + global_dvb_state = NULL; + pthread_mutex_unlock(&global_dvb_state_lock); } static int dvb_streaming_start(stream_t *stream, int tuner_type, char *progname) @@ -810,23 +889,24 @@ static int dvb_streaming_start(stream_t *stream, int tuner_type, char *progname) int i; dvb_channel_t *channel = NULL; dvb_priv_t *priv = stream->priv; + dvb_state_t* state = priv->state; dvb_priv_t *opts = priv; MP_VERBOSE(stream, "\r\ndvb_streaming_start(PROG: %s, CARD: %d)\n", opts->cfg_prog, opts->cfg_card); - priv->is_on = 0; + state->is_on = 0; i = 0; - while ((channel == NULL) && i < priv->list->NUM_CHANNELS) { - if (!strcmp(priv->list->channels[i].name, progname)) - channel = &(priv->list->channels[i]); + while ((channel == NULL) && i < state->list->NUM_CHANNELS) { + if (!strcmp(state->list->channels[i].name, progname)) + channel = &(state->list->channels[i]); i++; } if (channel != NULL) { - priv->list->current = i - 1; + state->list->current = i - 1; MP_VERBOSE(stream, "PROGRAM NUMBER %d: name=%s, freq=%u\n", i - 1, channel->name, channel->freq); } else { @@ -835,8 +915,8 @@ static int dvb_streaming_start(stream_t *stream, int tuner_type, char *progname) } - if (!dvb_set_channel(stream, priv->card, priv->list->current)) { - MP_ERR(stream, "ERROR, COULDN'T SET CHANNEL %i: ", priv->list->current); + if (!dvb_set_channel(stream, state->card, state->list->current)) { + MP_ERR(stream, "ERROR, COULDN'T SET CHANNEL %i: ", state->list->current); dvbin_close(stream); return 0; } @@ -851,7 +931,7 @@ static int dvb_streaming_start(stream_t *stream, int tuner_type, char *progname) static int dvb_open(stream_t *stream) { - // I don't force the file format bacause, although it's almost always TS, + // I don't force the file format because, although it's almost always TS, // there are some providers that stream an IP multicast with M$ Mpeg4 inside dvb_priv_t *priv = stream->priv; priv->log = stream->log; @@ -859,53 +939,68 @@ static int dvb_open(stream_t *stream) char *progname; int tuner_type = 0, i; - priv->fe_fd = priv->sec_fd = priv->dvr_fd = -1; - priv->config = dvb_get_config(stream); - if (priv->config == NULL) { + pthread_mutex_lock(&global_dvb_state_lock); + if (global_dvb_state && global_dvb_state->stream_used) { + MP_ERR(stream, "DVB stream already in use, only one DVB stream can exist at a time!"); + pthread_mutex_unlock(&global_dvb_state_lock); + return STREAM_ERROR; + } + + 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"); return STREAM_ERROR; } - priv->card = -1; - for (i = 0; i < priv->config->count; i++) { - if (priv->config->cards[i].devno + 1 == p->cfg_card) { - priv->card = i; - break; - } - } + 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. - if (priv->card == -1) { - MP_ERR(stream, "NO CONFIGURATION FOUND FOR CARD N. %d, exit\n", - p->cfg_card); - return STREAM_ERROR; - } - priv->timeout = p->cfg_timeout; + state->card = -1; + for (i = 0; i < state->count; i++) { + if (state->cards[i].devno + 1 == p->cfg_card) { + state->card = i; + break; + } + } - tuner_type = priv->config->cards[priv->card].type; + if (state->card == -1) { + MP_ERR(stream, "NO CONFIGURATION FOUND FOR CARD N. %d, exit\n", + p->cfg_card); + return STREAM_ERROR; + } + state->timeout = p->cfg_timeout; - if (tuner_type == 0) { - MP_VERBOSE(stream, - "OPEN_DVB: UNKNOWN OR UNDETECTABLE TUNER TYPE, EXIT\n"); - return STREAM_ERROR; - } + tuner_type = state->cards[state->card].type; - priv->tuner_type = tuner_type; + if (tuner_type == 0) { + MP_VERBOSE(stream, + "OPEN_DVB: UNKNOWN OR UNDETECTABLE TUNER TYPE, EXIT\n"); + return STREAM_ERROR; + } - MP_VERBOSE(stream, "OPEN_DVB: prog=%s, card=%d, type=%d\n", - p->cfg_prog, priv->card + 1, priv->tuner_type); + state->tuner_type = tuner_type; - priv->list = priv->config->cards[priv->card].list; + MP_VERBOSE(stream, "OPEN_DVB: prog=%s, card=%d, type=%d\n", + p->cfg_prog, state->card + 1, state->tuner_type); - if ((!strcmp(p->cfg_prog, "")) && (priv->list != NULL)) { - progname = priv->list->channels[0].name; - } else { - progname = p->cfg_prog; - } + state->list = state->cards[state->card].list; + if ((!strcmp(p->cfg_prog, "")) && (state->list != NULL)) { + progname = state->list->channels[0].name; + } else { + progname = p->cfg_prog; + } - if (!dvb_streaming_start(stream, tuner_type, progname)) - return STREAM_ERROR; + 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; @@ -919,27 +1014,32 @@ static int dvb_open(stream_t *stream) } #define MAX_CARDS 4 -dvb_config_t *dvb_get_config(stream_t *stream) +dvb_state_t *dvb_get_state(stream_t *stream) { + if (global_dvb_state != NULL) { + return global_dvb_state; + } struct mp_log *log = stream->log; struct mpv_global *global = stream->global; dvb_priv_t *priv = stream->priv; - int i, fd, type, size; + int type, size; char filename[30], *name; dvb_channels_list *list; dvb_card_config_t *cards = NULL, *tmp; - dvb_config_t *conf = NULL; + dvb_state_t *state = NULL; - conf = malloc(sizeof(dvb_config_t)); - if (conf == NULL) + state = malloc(sizeof(dvb_state_t)); + if (state == NULL) return NULL; - - conf->priv = NULL; - conf->count = 0; - conf->cards = NULL; - for (i = 0; i < MAX_CARDS; i++) { + + state->count = 0; + state->switching_channel = false; + state->stream_used = true; + state->cards = NULL; + state->fe_fd = state->dvr_fd = -1; + for (int i = 0; i < MAX_CARDS; i++) { snprintf(filename, sizeof(filename), "/dev/dvb/adapter%d/frontend0", i); - fd = open(filename, O_RDONLY | O_NONBLOCK | O_CLOEXEC); + 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); @@ -993,8 +1093,8 @@ dvb_config_t *dvb_get_config(stream_t *stream) if (list == NULL) continue; - size = sizeof(dvb_card_config_t) * (conf->count + 1); - tmp = realloc(conf->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", @@ -1009,23 +1109,24 @@ dvb_config_t *dvb_get_config(stream_t *stream) continue; } - conf->cards = cards; - conf->cards[conf->count].devno = i; - conf->cards[conf->count].list = list; - conf->cards[conf->count].type = type; + 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'), - conf->count + 1); - conf->cards[conf->count].name = name; - conf->count++; + state->count + 1); + state->cards[state->count].name = name; + state->count++; } - if (conf->count == 0) { - free(conf); - conf = NULL; + if (state->count == 0) { + free(state); + state = NULL; } - return conf; + global_dvb_state = state; + return state; } static void *get_defaults(stream_t *st) diff --git a/stream/stream_dvd.c b/stream/stream_dvd.c index 641305e7a8..55cb6dfc7b 100644 --- a/stream/stream_dvd.c +++ b/stream/stream_dvd.c @@ -35,7 +35,7 @@ #include "osdep/io.h" #include "config.h" -#include "talloc.h" +#include "mpv_talloc.h" #include "common/common.h" #include "common/msg.h" diff --git a/stream/stream_file.c b/stream/stream_file.c index 527261edd7..ce9f9d9739 100644 --- a/stream/stream_file.c +++ b/stream/stream_file.c @@ -262,9 +262,6 @@ static int open_f(stream_t *stream) MP_INFO(stream, "Writing to stdout...\n"); p->fd = 1; } -#ifdef __MINGW32__ - setmode(p->fd, O_BINARY); -#endif p->close = false; } else { mode_t openmode = S_IRUSR | S_IWUSR; @@ -298,6 +295,10 @@ static int open_f(stream_t *stream) p->close = true; } +#ifdef __MINGW32__ + setmode(p->fd, O_BINARY); +#endif + off_t len = lseek(p->fd, 0, SEEK_END); lseek(p->fd, 0, SEEK_SET); if (len != (off_t)-1) { diff --git a/stream/stream_lavf.c b/stream/stream_lavf.c index a66ff94374..d899629571 100644 --- a/stream/stream_lavf. |