summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demux/demux.c185
-rw-r--r--demux/demux.h11
-rw-r--r--demux/demux_disc.c20
-rw-r--r--demux/demux_lavf.c21
-rw-r--r--demux/demux_mf.c4
-rw-r--r--demux/demux_mkv.c29
-rw-r--r--demux/demux_mkv_timeline.c10
-rw-r--r--demux/demux_raw.c20
-rw-r--r--demux/demux_tv.c13
-rw-r--r--input/input.c6
-rw-r--r--player/loadfile.c18
-rw-r--r--player/misc.c4
-rw-r--r--player/sub.c4
13 files changed, 199 insertions, 146 deletions
diff --git a/demux/demux.c b/demux/demux.c
index 972bf31bae..8eb274647d 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -103,6 +103,11 @@ struct demux_internal {
void (*wakeup_cb)(void *ctx);
void *wakeup_cb_ctx;
+ struct sh_stream **streams;
+ int num_streams;
+
+ int events;
+
bool warned_queue_overflow;
bool last_eof; // last actual global EOF status
bool eof; // whether we're in EOF state (reset for retry)
@@ -198,42 +203,85 @@ void demux_set_ts_offset(struct demuxer *demuxer, double offset)
pthread_mutex_unlock(&in->lock);
}
-struct sh_stream *new_sh_stream(demuxer_t *demuxer, enum stream_type type)
+// Allocate a new sh_stream of the given type. It either has to be released
+// with talloc_free(), or added to a demuxer with demux_add_sh_stream(). You
+// cannot add or read packets from the stream before it has been added.
+struct sh_stream *demux_alloc_sh_stream(enum stream_type type)
{
- assert(demuxer == demuxer->in->d_thread);
-
- if (demuxer->num_streams > MAX_SH_STREAMS) {
- MP_WARN(demuxer, "Too many streams.\n");
- return NULL;
- }
-
- int demuxer_id = 0;
- for (int n = 0; n < demuxer->num_streams; n++) {
- if (demuxer->streams[n]->type == type)
- demuxer_id++;
- }
-
- struct sh_stream *sh = talloc_ptrtype(demuxer, sh);
+ struct sh_stream *sh = talloc_ptrtype(NULL, sh);
*sh = (struct sh_stream) {
.type = type,
- .index = demuxer->num_streams,
- .ff_index = demuxer->num_streams,
- .demuxer_id = demuxer_id, // may be overwritten by demuxer
- .ds = talloc(sh, struct demux_stream),
+ .index = -1,
+ .ff_index = -1, // may be overwritten by demuxer
+ .demuxer_id = -1, // ... same
};
+ switch (sh->type) {
+ case STREAM_VIDEO: sh->video = talloc_zero(sh, struct sh_video); break;
+ case STREAM_AUDIO: sh->audio = talloc_zero(sh, struct sh_audio); break;
+ case STREAM_SUB: sh->sub = talloc_zero(sh, struct sh_sub); break;
+ }
+
+ return sh;
+}
+
+// Add a new sh_stream to the demuxer. Note that as soon as the stream has been
+// added, it must be immutable, and must not be released (this will happen when
+// the demuxer is destroyed).
+void demux_add_sh_stream(struct demuxer *demuxer, struct sh_stream *sh)
+{
+ struct demux_internal *in = demuxer->in;
+ pthread_mutex_lock(&in->lock);
+
+ assert(!sh->ds); // must not be added yet
+
+ sh->ds = talloc(sh, struct demux_stream);
*sh->ds = (struct demux_stream) {
- .in = demuxer->in,
+ .in = in,
.type = sh->type,
- .selected = demuxer->in->autoselect,
+ .selected = in->autoselect,
};
- MP_TARRAY_APPEND(demuxer, demuxer->streams, demuxer->num_streams, sh);
- switch (sh->type) {
- case STREAM_VIDEO: sh->video = talloc_zero(demuxer, struct sh_video); break;
- case STREAM_AUDIO: sh->audio = talloc_zero(demuxer, struct sh_audio); break;
- case STREAM_SUB: sh->sub = talloc_zero(demuxer, struct sh_sub); break;
+
+ sh->index = in->num_streams;
+ if (sh->ff_index < 0)
+ sh->ff_index = sh->index;
+ if (sh->demuxer_id < 0) {
+ sh->demuxer_id = 0;
+ for (int n = 0; n < in->num_streams; n++) {
+ if (in->streams[n]->type == sh->type)
+ sh->demuxer_id += 1;
+ }
}
- return sh;
+ MP_TARRAY_APPEND(in, in->streams, in->num_streams, sh);
+
+ in->events |= DEMUX_EVENT_STREAMS;
+ if (in->wakeup_cb)
+ in->wakeup_cb(in->wakeup_cb_ctx);
+ pthread_mutex_unlock(&in->lock);
+}
+
+// Return a stream with the given index. Since streams can only be added during
+// the lifetime of the demuxer, it is guaranteed that an index within the valid
+// range [0, demux_get_num_stream()) always returns a valid sh_stream pointer,
+// which will be valid until the demuxer is destroyed.
+struct sh_stream *demux_get_stream(struct demuxer *demuxer, int index)
+{
+ struct demux_internal *in = demuxer->in;
+ pthread_mutex_lock(&in->lock);
+ assert(index >= 0 && index < in->num_streams);
+ struct sh_stream *r = in->streams[index];
+ pthread_mutex_unlock(&in->lock);
+ return r;
+}
+
+// See demux_get_stream().
+int demux_get_num_stream(struct demuxer *demuxer)
+{
+ struct demux_internal *in = demuxer->in;
+ pthread_mutex_lock(&in->lock);
+ int r = in->num_streams;
+ pthread_mutex_unlock(&in->lock);
+ return r;
}
void free_demuxer(demuxer_t *demuxer)
@@ -247,8 +295,10 @@ void free_demuxer(demuxer_t *demuxer)
if (demuxer->desc->close)
demuxer->desc->close(in->d_thread);
- for (int n = 0; n < demuxer->num_streams; n++)
- ds_flush(demuxer->streams[n]->ds);
+ for (int n = in->num_streams - 1; n >= 0; n--) {
+ ds_flush(in->streams[n]->ds);
+ talloc_free(in->streams[n]);
+ }
pthread_mutex_destroy(&in->lock);
pthread_cond_destroy(&in->wakeup);
talloc_free(demuxer);
@@ -388,8 +438,8 @@ static bool read_packet(struct demux_internal *in)
// safe-guards against packet queue overflow.
bool active = false, read_more = false;
size_t packs = 0, bytes = 0;
- for (int n = 0; n < in->d_buffer->num_streams; n++) {
- struct demux_stream *ds = in->d_buffer->streams[n]->ds;
+ for (int n = 0; n < in->num_streams; n++) {
+ struct demux_stream *ds = in->streams[n]->ds;
active |= ds->active;
read_more |= ds->active && !ds->head;
packs += ds->packs;
@@ -404,16 +454,16 @@ static bool read_packet(struct demux_internal *in)
if (!in->warned_queue_overflow) {
in->warned_queue_overflow = true;
MP_ERR(in, "Too many packets in the demuxer packet queues:\n");
- for (int n = 0; n < in->d_buffer->num_streams; n++) {
- struct demux_stream *ds = in->d_buffer->streams[n]->ds;
+ for (int n = 0; n < in->num_streams; n++) {
+ struct demux_stream *ds = in->streams[n]->ds;
if (ds->selected) {
MP_ERR(in, " %s/%d: %zd packets, %zd bytes\n",
stream_type_name(ds->type), n, ds->packs, ds->bytes);
}
}
}
- for (int n = 0; n < in->d_buffer->num_streams; n++) {
- struct demux_stream *ds = in->d_buffer->streams[n]->ds;
+ for (int n = 0; n < in->num_streams; n++) {
+ struct demux_stream *ds = in->streams[n]->ds;
ds->eof |= !ds->head;
}
pthread_cond_signal(&in->wakeup);
@@ -433,8 +483,8 @@ static bool read_packet(struct demux_internal *in)
pthread_mutex_lock(&in->lock);
if (eof) {
- for (int n = 0; n < in->d_buffer->num_streams; n++)
- in->d_buffer->streams[n]->ds->eof = true;
+ for (int n = 0; n < in->num_streams; n++)
+ in->streams[n]->ds->eof = true;
// If we had EOF previously, then don't wakeup (avoids wakeup loop)
if (!in->last_eof) {
if (in->wakeup_cb)
@@ -478,8 +528,8 @@ static void start_refreshing(struct demux_internal *in)
in->start_refresh_seek = false;
double start_ts = MP_NOPTS_VALUE;
- for (int n = 0; n < demux->num_streams; n++) {
- struct demux_stream *ds = demux->streams[n]->ds;
+ for (int n = 0; n < in->num_streams; n++) {
+ struct demux_stream *ds = in->streams[n]->ds;
if (ds->type == STREAM_VIDEO || ds->type == STREAM_AUDIO)
start_ts = MP_PTS_MIN(start_ts, ds->base_ts);
}
@@ -488,8 +538,8 @@ static void start_refreshing(struct demux_internal *in)
demux->partially_seekable || !demux->allow_refresh_seeks)
return;
- for (int n = 0; n < demux->num_streams; n++) {
- struct demux_stream *ds = demux->streams[n]->ds;
+ for (int n = 0; n < in->num_streams; n++) {
+ struct demux_stream *ds = in->streams[n]->ds;
// Streams which didn't read any packets yet can return all packets,
// or they'd be stuck forever; affects newly selected streams too.
if (ds->last_pos != -1)
@@ -697,21 +747,22 @@ bool demux_has_packet(struct sh_stream *sh)
// Read and return any packet we find.
struct demux_packet *demux_read_any_packet(struct demuxer *demuxer)
{
- assert(!demuxer->in->threading); // doesn't work with threading
+ struct demux_internal *in = demuxer->in;
+ assert(!in->threading); // doesn't work with threading
bool read_more = true;
while (read_more) {
- for (int n = 0; n < demuxer->num_streams; n++) {
- struct sh_stream *sh = demuxer->streams[n];
+ for (int n = 0; n < in->num_streams; n++) {
+ struct sh_stream *sh = in->streams[n];
sh->ds->active = sh->ds->selected; // force read_packet() to read
struct demux_packet *pkt = dequeue_packet(sh->ds);
if (pkt)
return pkt;
}
// retry after calling this
- pthread_mutex_lock(&demuxer->in->lock);
- read_more = read_packet(demuxer->in);
- read_more &= !demuxer->in->eof;
- pthread_mutex_unlock(&demuxer->in->lock);
+ pthread_mutex_lock(&in->lock); // lock only because read_packet unlocks
+ read_more = read_packet(in);
+ read_more &= !in->eof;
+ pthread_mutex_unlock(&in->lock);
}
return NULL;
}
@@ -795,13 +846,14 @@ static int decode_peak(demuxer_t *demuxer, const char *tag, float *out)
static void apply_replaygain(demuxer_t *demuxer, struct replaygain_data *rg)
{
- for (int n = 0; n < demuxer->num_streams; n++) {
- struct sh_stream *sh = demuxer->streams[n];
+ struct demux_internal *in = demuxer->in;
+ for (int n = 0; n < in->num_streams; n++) {
+ struct sh_stream *sh = in->streams[n];
if (sh->audio && !sh->audio->replaygain_data) {
MP_VERBOSE(demuxer, "Replaygain: Track=%f/%f Album=%f/%f\n",
rg->track_gain, rg->track_peak,
rg->album_gain, rg->album_peak);
- sh->audio->replaygain_data = talloc_memdup(demuxer, rg, sizeof(*rg));
+ sh->audio->replaygain_data = talloc_memdup(in, rg, sizeof(*rg));
}
}
}
@@ -853,11 +905,6 @@ static void demux_copy(struct demuxer *dst, struct demuxer *src)
dst->start_time = src->start_time;
dst->priv = src->priv;
}
- if (src->events & DEMUX_EVENT_STREAMS) {
- // The stream structs themselves are immutable.
- for (int n = dst->num_streams; n < src->num_streams; n++)
- MP_TARRAY_APPEND(dst, dst->streams, dst->num_streams, src->streams[n]);
- }
if (src->events & DEMUX_EVENT_METADATA) {
talloc_free(dst->metadata);
dst->metadata = mp_tags_dup(dst, src->metadata);
@@ -905,6 +952,8 @@ void demux_update(demuxer_t *demuxer)
pthread_mutex_lock(&in->lock);
demux_copy(demuxer, in->d_buffer);
+ demuxer->events |= in->events;
+ in->events = 0;
if (in->stream_metadata && (demuxer->events & DEMUX_EVENT_METADATA))
mp_tags_merge(demuxer->metadata, in->stream_metadata);
pthread_mutex_unlock(&in->lock);
@@ -1113,8 +1162,8 @@ struct demuxer *demux_open_url(const char *url,
static void flush_locked(demuxer_t *demuxer)
{
- for (int n = 0; n < demuxer->num_streams; n++)
- ds_flush(demuxer->streams[n]->ds);
+ for (int n = 0; n < demuxer->in->num_streams; n++)
+ ds_flush(demuxer->in->streams[n]->ds);
demuxer->in->warned_queue_overflow = false;
demuxer->in->eof = false;
demuxer->in->last_eof = false;
@@ -1192,10 +1241,11 @@ void demux_set_enable_refresh_seeks(struct demuxer *demuxer, bool enabled)
struct sh_stream *demuxer_stream_by_demuxer_id(struct demuxer *d,
enum stream_type t, int id)
{
- for (int n = 0; n < d->num_streams; n++) {
- struct sh_stream *s = d->streams[n];
+ int num = demux_get_num_stream(d);
+ for (int n = 0; n < num; n++) {
+ struct sh_stream *s = demux_get_stream(d, n);
if (s->type == t && s->demuxer_id == id)
- return d->streams[n];
+ return s;
}
return NULL;
}
@@ -1205,8 +1255,9 @@ void demuxer_switch_track(struct demuxer *demuxer, enum stream_type type,
{
assert(!stream || stream->type == type);
- for (int n = 0; n < demuxer->num_streams; n++) {
- struct sh_stream *cur = demuxer->streams[n];
+ int num = demux_get_num_stream(demuxer);
+ for (int n = 0; n < num; n++) {
+ struct sh_stream *cur = demux_get_stream(demuxer, n);
if (cur->type == type)
demuxer_select_track(demuxer, cur, cur == stream);
}
@@ -1408,8 +1459,8 @@ static int cached_demux_control(struct demux_internal *in, int cmd, void *arg)
double *rates = arg;
for (int n = 0; n < STREAM_TYPE_COUNT; n++)
rates[n] = -1;
- for (int n = 0; n < in->d_user->num_streams; n++) {
- struct demux_stream *ds = in->d_user->streams[n]->ds;
+ for (int n = 0; n < in->num_streams; n++) {
+ struct demux_stream *ds = in->streams[n]->ds;
if (ds->selected && ds->bitrate >= 0)
rates[ds->type] = MPMAX(0, rates[ds->type]) + ds->bitrate;
}
@@ -1423,8 +1474,8 @@ static int cached_demux_control(struct demux_internal *in, int cmd, void *arg)
.ts_duration = -1,
};
int num_packets = 0;
- for (int n = 0; n < in->d_user->num_streams; n++) {
- struct demux_stream *ds = in->d_user->streams[n]->ds;
+ for (int n = 0; n < in->num_streams; n++) {
+ struct demux_stream *ds = in->streams[n]->ds;
if (ds->active) {
r->underrun |= !ds->head && !ds->eof;
r->ts_range[0] = MP_PTS_MAX(r->ts_range[0], ds->base_ts);
diff --git a/demux/demux.h b/demux/demux.h
index 96717d5eeb..db3b504c39 100644
--- a/demux/demux.h
+++ b/demux/demux.h
@@ -86,8 +86,6 @@ enum demux_event {
DEMUX_EVENT_ALL = 0xFFFF,
};
-#define MAX_SH_STREAMS 256
-
struct demuxer;
struct timeline;
@@ -199,9 +197,6 @@ typedef struct demuxer {
// Bitmask of DEMUX_EVENT_*
int events;
- struct sh_stream **streams;
- int num_streams;
-
struct demux_edition *editions;
int num_editions;
int edition;
@@ -251,7 +246,11 @@ double demux_get_next_pts(struct sh_stream *sh);
bool demux_has_packet(struct sh_stream *sh);
struct demux_packet *demux_read_any_packet(struct demuxer *demuxer);
-struct sh_stream *new_sh_stream(struct demuxer *demuxer, enum stream_type type);
+struct sh_stream *demux_get_stream(struct demuxer *demuxer, int index);
+int demux_get_num_stream(struct demuxer *demuxer);
+
+struct sh_stream *demux_alloc_sh_stream(enum stream_type type);
+void demux_add_sh_stream(struct demuxer *demuxer, struct sh_stream *sh);
struct demuxer *demux_open(struct stream *stream, struct demuxer_params *params,
struct mpv_global *global);
diff --git a/demux/demux_disc.c b/demux/demux_disc.c
index 1abae38d35..90c276b414 100644
--- a/demux/demux_disc.c
+++ b/demux/demux_disc.c
@@ -54,9 +54,10 @@ struct priv {
static void reselect_streams(demuxer_t *demuxer)
{
struct priv *p = demuxer->priv;
- for (int n = 0; n < MPMIN(p->slave->num_streams, p->num_streams); n++) {
+ int num_slave = demux_get_num_stream(p->slave);
+ for (int n = 0; n < MPMIN(num_slave, p->num_streams); n++) {
if (p->streams[n]) {
- demuxer_select_track(p->slave, p->slave->streams[n],
+ demuxer_select_track(p->slave, demux_get_stream(p->slave, n),
demux_stream_is_selected(p->streams[n]));
}
}
@@ -81,9 +82,7 @@ static void add_dvd_streams(demuxer_t *demuxer)
struct stream_dvd_info_req info;
if (stream_control(stream, STREAM_CTRL_GET_DVD_INFO, &info) > 0) {
for (int n = 0; n < MPMIN(32, info.num_subs); n++) {
- struct sh_stream *sh = new_sh_stream(demuxer, STREAM_SUB);
- if (!sh)
- break;
+ struct sh_stream *sh = demux_alloc_sh_stream(STREAM_SUB);
sh->demuxer_id = n + 0x20;
sh->codec = "dvd_subtitle";
get_disc_lang(stream, sh);
@@ -114,6 +113,8 @@ static void add_dvd_streams(demuxer_t *demuxer)
sh->extradata = s;
sh->extradata_size = strlen(s);
+
+ demux_add_sh_stream(demuxer, sh);
}
}
}
@@ -122,8 +123,8 @@ static void add_streams(demuxer_t *demuxer)
{
struct priv *p = demuxer->priv;
- for (int n = p->num_streams; n < p->slave->num_streams; n++) {
- struct sh_stream *src = p->slave->streams[n];
+ for (int n = p->num_streams; n < demux_get_num_stream(p->slave); n++) {
+ struct sh_stream *src = demux_get_stream(p->slave, n);
if (src->sub) {
struct sh_stream *sub = NULL;
if (src->demuxer_id >= 0x20 && src->demuxer_id <= 0x3F)
@@ -134,9 +135,7 @@ static void add_streams(demuxer_t *demuxer)
continue;
}
}
- struct sh_stream *sh = new_sh_stream(demuxer, src->type);
- if (!sh)
- break;
+ struct sh_stream *sh = demux_alloc_sh_stream(src->type);
assert(p->num_streams == n); // directly mapped
MP_TARRAY_APPEND(p, p->streams, p->num_streams, sh);
// Copy all stream fields that might be relevant
@@ -159,6 +158,7 @@ static void add_streams(demuxer_t *demuxer)
if (src->audio)
sh->audio = src->audio;
get_disc_lang(demuxer->stream, sh);
+ demux_add_sh_stream(demuxer, sh);
}
reselect_streams(demuxer);
}
diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c
index 7af41e6f09..5e7d8d8a9e 100644
--- a/demux/demux_lavf.c
+++ b/demux/demux_lavf.c
@@ -541,9 +541,7 @@ static void handle_new_stream(demuxer_t *demuxer, int i)
switch (codec->codec_type) {
case AVMEDIA_TYPE_AUDIO: {
- sh = new_sh_stream(demuxer, STREAM_AUDIO);
- if (!sh)
- break;
+ sh = demux_alloc_sh_stream(STREAM_AUDIO);
sh_audio_t *sh_audio = sh->audio;
// probably unneeded
@@ -558,9 +556,7 @@ static void handle_new_stream(demuxer_t *demuxer, int i)
break;
}
case AVMEDIA_TYPE_VIDEO: {
- sh = new_sh_stream(demuxer, STREAM_VIDEO);
- if (!sh)
- break;
+ sh = demux_alloc_sh_stream(STREAM_VIDEO);
sh_video_t *sh_video = sh->video;
if (st->disposition & AV_DISPOSITION_ATTACHED_PIC) {
@@ -609,9 +605,7 @@ static void handle_new_stream(demuxer_t *demuxer, int i)
}
case AVMEDIA_TYPE_SUBTITLE: {
sh_sub_t *sh_sub;
- sh = new_sh_stream(demuxer, STREAM_SUB);
- if (!sh)
- break;
+ sh = demux_alloc_sh_stream(STREAM_SUB);
sh_sub = sh->sub;
if (codec->extradata_size) {
@@ -660,9 +654,8 @@ static void handle_new_stream(demuxer_t *demuxer, int i)
sh->codec = mp_codec_from_av_codec_id(codec->codec_id);
sh->codec_tag = codec->codec_tag;
sh->lav_headers = avcodec_alloc_context3(NULL);
- if (!sh->lav_headers)
- return;
- mp_copy_lav_codec_headers(sh->lav_headers, codec);
+ if (sh->lav_headers)
+ mp_copy_lav_codec_headers(sh->lav_headers, codec);
if (st->disposition & AV_DISPOSITION_DEFAULT)
sh->default_track = true;
@@ -680,10 +673,10 @@ static void handle_new_stream(demuxer_t *demuxer, int i)
if (!sh->title && sh->hls_bitrate > 0)
sh->title = talloc_asprintf(sh, "bitrate %d", sh->hls_bitrate);
sh->missing_timestamps = !!(priv->avif_flags & AVFMT_NOTIMESTAMPS);
+ demux_add_sh_stream(demuxer, sh);
}
select_tracks(demuxer, i);
- demux_changed(demuxer, DEMUX_EVENT_STREAMS);
}
// Add any new streams that might have been added
@@ -844,7 +837,7 @@ static int demux_open_lavf(demuxer_t *demuxer, enum demux_check check)
// Often useful with OGG audio-only files, which have metadata in the audio
// track metadata instead of the main metadata.
- if (demuxer->num_streams == 1) {
+ if (demux_get_num_stream(demuxer) == 1) {
priv->merge_track_metadata = true;
for (int n = 0; n < priv->num_streams; n++) {
if (priv->streams[n])
diff --git a/demux/demux_mf.c b/demux/demux_mf.c
index ab703c0ced..c1cc5d79f3 100644
--- a/demux/demux_mf.c
+++ b/demux/demux_mf.c
@@ -201,7 +201,7 @@ static int demux_mf_fill_buffer(demuxer_t *demuxer)
memcpy(dp->buffer, data.start, data.len);
dp->pts = mf->curr_frame / mf->sh->fps;
dp->keyframe = true;
- demux_add_packet(demuxer->streams[0], dp);
+ demux_add_packet(mf->sh, dp);
}
}
talloc_free(data.start);
@@ -316,7 +316,7 @@ static int demux_open_mf(demuxer_t *demuxer, enum demux_check check)
mf->curr_frame = 0;
// create a new video stream header
- struct sh_stream *sh = new_sh_stream(demuxer, STREAM_VIDEO);
+ struct sh_stream *sh = demux_alloc_sh_stream(STREAM_VIDEO);
sh_video = sh->video;
sh->codec = codec;
diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c
index 562bddbfc6..af82dc8deb 100644
--- a/demux/demux_mkv.c
+++ b/demux/demux_mkv.c
@@ -1193,9 +1193,7 @@ static void add_coverart(struct demuxer *demuxer)
const char *codec = mp_map_mimetype_to_video_codec(att->type);
if (!codec)
continue;
- struct sh_stream *sh = new_sh_stream(demuxer, STREAM_VIDEO);
- if (!sh)
- break;
+ struct sh_stream *sh = demux_alloc_sh_stream(STREAM_VIDEO);
sh->demuxer_id = -1 - sh->index; // don't clash with mkv IDs
sh->codec = codec;
sh->attached_picture = new_demux_packet_from(att->data, att->data_size);
@@ -1205,6 +1203,7 @@ static void add_coverart(struct demuxer *demuxer)
sh->attached_picture->keyframe = true;
}
sh->title = att->name;
+ demux_add_sh_stream(demuxer, sh);
}
}
@@ -1266,9 +1265,7 @@ static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track)
{
unsigned char *extradata = NULL;
unsigned int extradata_size = 0;
- struct sh_stream *sh = new_sh_stream(demuxer, STREAM_VIDEO);
- if (!sh)
- return 1;
+ struct sh_stream *sh = demux_alloc_sh_stream(STREAM_VIDEO);
init_track(demuxer, track, sh);
sh_video_t *sh_v = sh->video;
@@ -1277,7 +1274,7 @@ static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track)
if (!strcmp(track->codec_id, "V_MS/VFW/FOURCC")) { /* AVI compatibility mode */
// The private_data contains a BITMAPINFOHEADER struct
if (track->private_data == NULL || track->private_size < 40)
- return 1;
+ goto done;
unsigned char *h = track->private_data;
if (track->v_width == 0)
@@ -1355,7 +1352,7 @@ static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track)
if (extradata_size > 0x1000000) {
MP_WARN(demuxer, "Invalid CodecPrivate\n");
- return 1;
+ goto done;
}
sh->extradata = talloc_memdup(sh_v, extradata, extradata_size);
@@ -1378,6 +1375,9 @@ static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track)
sh_v->stereo_mode = track->stereo_mode;
+done:
+ demux_add_sh_stream(demuxer, sh);
+
return 0;
}
@@ -1469,9 +1469,7 @@ static const char *const mkv_audio_tags[][2] = {
static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track)
{
- struct sh_stream *sh = new_sh_stream(demuxer, STREAM_AUDIO);
- if (!sh)
- return 1;
+ struct sh_stream *sh = demux_alloc_sh_stream(STREAM_AUDIO);
init_track(demuxer, track, sh);
sh_audio_t *sh_a = sh->audio;
@@ -1680,12 +1678,15 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track)
sh->extradata = extradata;
sh->extradata_size = extradata_len;
+ demux_add_sh_stream(demuxer, sh);
+
return 0;
error:
MP_WARN(demuxer, "Unknown/unsupported audio "
"codec ID '%s' for track %u or missing/faulty\n"
"private codec data.\n", track->codec_id, track->tnum);
+ demux_add_sh_stream(demuxer, sh); // add it anyway
return 1;
}
@@ -1717,9 +1718,7 @@ static int demux_mkv_open_sub(demuxer_t *demuxer, mkv_track_t *track)
if (track->private_size > 0x10000000)
return 1;
- struct sh_stream *sh = new_sh_stream(demuxer, STREAM_SUB);
- if (!sh)
- return 1;
+ struct sh_stream *sh = demux_alloc_sh_stream(STREAM_SUB);
init_track(demuxer, track, sh);
sh->codec = subtitle_type;
@@ -1734,6 +1733,8 @@ static int demux_mkv_open_sub(demuxer_t *demuxer, mkv_track_t *track)
sh->extradata = track->private_data;
sh->extradata_size = track->private_size;
+ demux_add_sh_stream(demuxer, sh);
+
if (!subtitle_type)
MP_ERR(demuxer, "Subtitle type '%s' is not supported.\n", track->codec_id);
diff --git a/demux/demux_mkv_timeline.c b/demux/demux_mkv_timeline.c
index a874f9c6a7..f784f2d010 100644
--- a/demux/demux_mkv_timeline.c
+++ b/demux/demux_mkv_timeline.c
@@ -458,8 +458,9 @@ static void check_track_compatibility(struct timeline *tl)
if (p->source == mainsrc)
continue;
- for (int i = 0; i < p->source->num_streams; i++) {
- struct sh_stream *s = p->source->streams[i];
+ int num_source_streams = demux_get_num_stream(p->source);
+ for (int i = 0; i < num_source_streams; i++) {
+ struct sh_stream *s = demux_get_stream(p->source, i);
if (s->attached_picture)
continue;
@@ -473,8 +474,9 @@ static void check_track_compatibility(struct timeline *tl)
}
}
- for (int i = 0; i < mainsrc->num_streams; i++) {
- struct sh_stream *m = mainsrc->streams[i];
+ int num_main_streams = demux_get_num_stream(mainsrc);
+ for (int i = 0; i < num_main_streams; i++) {
+ struct sh_stream *m = demux_get_stream(mainsrc, i);
if (m->attached_picture)
continue;
diff --git a/demux/demux_raw.c b/demux/demux_raw.c
index a67287792b..5e492334ae 100644
--- a/demux/demux_raw.c
+++ b/demux/demux_raw.c
@@ -117,6 +117,7 @@ const struct m_sub_options demux_rawvideo_conf = {
};
struct priv {
+ struct sh_stream *sh;
int frame_size;
int read_frames;
double frame_rate;
@@ -125,14 +126,12 @@ struct priv {
static int demux_rawaudio_open(demuxer_t *demuxer, enum demux_check check)
{
struct demux_rawaudio_opts *opts = demuxer->opts->demux_rawaudio;
- struct sh_stream *sh;
- sh_audio_t *sh_audio;
if (check != DEMUX_CHECK_REQUEST && check != DEMUX_CHECK_FORCE)
return -1;
- sh = new_sh_stream(demuxer, STREAM_AUDIO);
- sh_audio = sh->audio;
+ struct sh_stream *sh = demux_alloc_sh_stream(STREAM_AUDIO);
+ struct sh_audio *sh_audio = sh->audio;
sh_audio->channels = opts->channels;
sh_audio->force_channels = true;
sh_audio->samplerate = opts->samplerate;
@@ -142,9 +141,12 @@ static int demux_rawaudio_open(demuxer_t *demuxer, enum demux_check check)
mp_set_pcm_codec(sh, f & 1, f & 2, f >> 3, f & 4);
int samplesize = ((f >> 3) + 7) / 8;
+ demux_add_sh_stream(demuxer, sh);
+
struct priv *p = talloc_ptrtype(demuxer, p);
demuxer->priv = p;
*p = (struct priv) {
+ .sh = sh,
.frame_size = samplesize * sh_audio->channels.num,
.frame_rate = sh_audio->samplerate,
.read_frames = sh_audio->samplerate / 8,
@@ -156,8 +158,6 @@ static int demux_rawaudio_open(demuxer_t *demuxer, enum demux_check check)
static int demux_rawvideo_open(demuxer_t *demuxer, enum demux_check check)
{
struct demux_rawvideo_opts *opts = demuxer->opts->demux_rawvideo;
- struct sh_stream *sh;
- sh_video_t *sh_video;
if (check != DEMUX_CHECK_REQUEST && check != DEMUX_CHECK_FORCE)
return -1;
@@ -219,17 +219,19 @@ static int demux_rawvideo_open(demuxer_t *demuxer, enum demux_check check)
imgsize = width * height * bpp / 8;
}
- sh = new_sh_stream(demuxer, STREAM_VIDEO);
- sh_video = sh->video;
+ struct sh_stream *sh = demux_alloc_sh_stream(STREAM_VIDEO);
+ struct sh_video *sh_video = sh->video;
sh->codec = decoder;
sh->codec_tag = imgfmt;
sh_video->fps = opts->fps;
sh_video->disp_w = width;
sh_video->disp_h = height;
+ demux_add_sh_stream(demuxer, sh);
struct priv *p = talloc_ptrtype(demuxer, p);
demuxer->priv = p;
*p = (struct priv) {
+ .sh = sh,
.frame_size = imgsize,
.frame_rate = sh_video->fps,
.read_frames = 1,
@@ -256,7 +258,7 @@ static int raw_fill_buffer(demuxer_t *demuxer)
int len = stream_read(demuxer->stream, dp->buffer, dp->len);
demux_packet_shorten(dp, len);
- demux_add_packet(demuxer->streams[0], dp);
+ demux_add_packet(p->sh, dp);
return 1;
}
diff --git a/demux/demux_tv.c b/demux/demux_tv.c
index ab584874cb..a2d06591e0 100644
--- a/demux/demux_tv.c
+++ b/demux/demux_tv.c
@@ -50,7 +50,7 @@ static int demux_open_tv(demuxer_t *demuxer, enum demux_check check)
funcs = tvh->functions;
demuxer->priv=tvh;
- struct sh_stream *sh_v = new_sh_stream(demuxer, STREAM_VIDEO);
+ struct sh_stream *sh_v = demux_alloc_sh_stream(STREAM_VIDEO);
sh_video = sh_v->video;
/* get IMAGE FORMAT */
@@ -89,6 +89,8 @@ static int demux_open_tv(demuxer_t *demuxer, enum demux_check check)
/* set height */
funcs->control(tvh->priv, TVI_CONTROL_VID_GET_HEIGHT, &sh_video->disp_h);
+ demux_add_sh_stream(demuxer, sh_v);
+
demuxer->seekable = 0;
/* here comes audio init */
@@ -115,7 +117,7 @@ static int demux_open_tv(demuxer_t *demuxer, enum demux_check check)
goto no_audio;
}
- struct sh_stream *sh_a = new_sh_stream(demuxer, STREAM_AUDIO);
+ struct sh_stream *sh_a = demux_alloc_sh_stream(STREAM_AUDIO);
sh_audio = sh_a->audio;
funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLERATE,
@@ -128,6 +130,8 @@ static int demux_open_tv(demuxer_t *demuxer, enum demux_check check)
// s16ne
mp_set_pcm_codec(sh_a, true, false, 16, BYTE_ORDER == BIG_ENDIAN);
+ demux_add_sh_stream(demuxer, sh_a);
+
MP_VERBOSE(tvh, " TV audio: %d channels, %d bits, %d Hz\n",
nchannels, 16, sh_audio->samplerate);
}
@@ -168,8 +172,9 @@ static int demux_tv_fill_buffer(demuxer_t *demux)
unsigned int len=0;
struct sh_stream *want_audio = NULL, *want_video = NULL;
- for (int n = 0; n < demux->num_streams; n++) {
- struct sh_stream *sh = demux->streams[n];
+ int num_streams = demux_get_num_stream(demux);
+ for (int n = 0; n < num_streams; n++) {
+ struct sh_stream *sh = demux_get_stream(demux, n);
if (!demux_has_packet(sh) && demux_stream_is_selected(sh)) {
if (sh->type == STREAM_AUDIO)
want_audio = sh;
diff --git a/input/input.c b/input/input.c
index 24281fe99e..2e7d6d30ef 100644
--- a/input/input.c
+++ b/input/input.c
@@ -463,10 +463,8 @@ static mp_cmd_t *get_cmd_from_keys(struct input_ctx *ictx, char *force_section,
if (ret) {
ret->input_section = cmd->owner->section;
ret->key_name = talloc_steal(ret, mp_input_get_key_combo_name(&code, 1));
- if (mp_msg_test(ictx->log, MSGL_DEBUG)) {
- MP_DBG(ictx, "key '%s' -> '%s' in '%s'\n",
- ret->key_name, cmd->cmd, ret->input_section);
- }
+ MP_DBG(ictx, "key '%s' -> '%s' in '%s'\n",
+ ret->key_name, cmd->cmd, ret->input_section);
ret->is_mouse_button = code & MP_KEY_EMIT_ON_UP;
} else {
char *key_buf = mp_input_get_key_combo_name(&code, 1);
diff --git a/player/loadfile.c b/player/loadfile.c
index 07a32c307a..af60aed3e0 100644
--- a/player/loadfile.c
+++ b/player/loadfile.c
@@ -212,8 +212,8 @@ void update_demuxer_properties(struct MPContext *mpctx)
static bool need_init_seek(struct demuxer *demux)
{
- for (int n = 0; n < demux->num_streams; n++) {
- struct sh_stream *stream = demux->streams[n];
+ for (int n = 0; n < demux_get_num_stream(demux); n++) {
+ struct sh_stream *stream = demux_get_stream(demux, n);
// Subtitle streams are not properly interleaved -> force init. seek.
if (stream->type != STREAM_SUB && demux_stream_is_selected(stream))
return false;
@@ -250,8 +250,8 @@ static struct sh_stream *select_fallback_stream(struct demuxer *d,
int index)
{
struct sh_stream *best_stream = NULL;
- for (int n = 0; n < d->num_streams; n++) {
- struct sh_stream *s = d->streams[n];
+ for (int n = 0; n < demux_get_num_stream(d); n++) {
+ struct sh_stream *s = demux_get_stream(d, n);
if (s->type == type) {
best_stream = s;
if (index == 0)
@@ -396,8 +396,10 @@ static struct track *add_stream_track(struct MPContext *mpctx,
void add_demuxer_tracks(struct MPContext *mpctx, struct demuxer *demuxer)
{
- for (int n = 0; n < demuxer->num_streams; n++)
- add_stream_track(mpctx, demuxer, demuxer->streams[n], !!mpctx->timeline);
+ for (int n = 0; n < demux_get_num_stream(demuxer); n++) {
+ add_stream_track(mpctx, demuxer, demux_get_stream(demuxer, n),
+ !!mpctx->timeline);
+ }
}
// Result numerically higher => better match. 0 == no match.
@@ -708,8 +710,8 @@ struct track *mp_add_external_file(struct MPContext *mpctx, char *filename,
demux_set_ts_offset(demuxer, -demuxer->start_time);
struct track *first = NULL;
- for (int n = 0; n < demuxer->num_streams; n++) {
- struct sh_stream *sh = demuxer->streams[n];
+ for (int n = 0; n < demux_get_num_stream(demuxer); n++) {
+ struct sh_stream *sh = demux_get_stream(demuxer, n);
if (sh->type == filter) {
struct track *t = add_stream_track(mpctx, demuxer, sh, false);
t->is_external = true;
diff --git a/player/misc.c b/player/misc.c
index 0b2548b98b..fc98136e5c 100644
--- a/player/misc.c
+++ b/player/misc.c
@@ -106,8 +106,8 @@ double get_main_demux_pts(struct MPContext *mpctx)
{
double main_new_pos = MP_NOPTS_VALUE;
if (mpctx->demuxer) {
- for (int n = 0; n < mpctx->demuxer->num_streams; n++) {
- struct sh_stream *stream = mpctx->demuxer->streams[n];
+ for (int n = 0; n < demux_get_num_stream(mpctx->demuxer); n++) {
+ struct sh_stream *stream = demux_get_stream(mpctx->demuxer, n);
if (main_new_pos == MP_NOPTS_VALUE && stream->type != STREAM_SUB)
main_new_pos = demux_get_next_pts(stream);
}
diff --git a/player/sub.c b/player/sub.c
index 9ec7ba5e7b..df84e910af 100644
--- a/player/sub.c
+++ b/player/sub.c
@@ -146,8 +146,8 @@ void reset_subtitle_state(struct MPContext *mpctx)
void uninit_stream_sub_decoders(struct demuxer *demuxer)
{
- for (int i = 0; i < demuxer->num_streams; i++) {
- struct sh_stream *sh = demuxer->streams[i];
+ for (int i = 0; i < demux_get_num_stream(demuxer); i++) {
+ struct sh_stream *sh = demux_get_stream(demuxer, i);
if (sh->sub) {
sub_destroy(sh->sub->dec_sub);
sh->sub->dec_sub = NULL;