summaryrefslogtreecommitdiffstats
path: root/stream
diff options
context:
space:
mode:
Diffstat (limited to 'stream')
-rw-r--r--stream/cache.c8
-rw-r--r--stream/dvb_tune.c60
-rw-r--r--stream/dvbin.h21
-rw-r--r--stream/rar.c2
-rw-r--r--stream/stream.c6
-rw-r--r--stream/stream.h2
-rw-r--r--stream/stream_bluray.c2
-rw-r--r--stream/stream_cdda.c2
-rw-r--r--stream/stream_dvb.c323
-rw-r--r--stream/stream_dvd.c2
-rw-r--r--stream/stream_file.c7
-rw-r--r--stream/stream_lavf.c6
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.