summaryrefslogtreecommitdiffstats
path: root/libmpdemux/demuxer.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-08-19 18:01:30 +0200
committerwm4 <wm4@nowhere>2012-09-18 21:04:45 +0200
commit0f155921b046c9e6cfed3fe601aa891c2d2a8b16 (patch)
treeced8b2b76d00f3461bf12d0b5063ce2cf6fb8fe8 /libmpdemux/demuxer.c
parent13482fb397ce6bbcec8a9342015f21d48fb7efe6 (diff)
downloadmpv-0f155921b046c9e6cfed3fe601aa891c2d2a8b16.tar.bz2
mpv-0f155921b046c9e6cfed3fe601aa891c2d2a8b16.tar.xz
core: manage tracks in the frontend
Introduce a general track struct for every audio/video/subtitle track known to the frontend. External files (subtitles) are now represented as tracks too. This mainly serves to clean up the subtitle selection code: now every subtitle is simply a track, instead of using a messy numbering that goes by subtitle type (as it was stored in the global_sub_pos field). The mplayer fontend will list external subtitle files as additional tracks. The timeline code now tries to match the exact demuxer IDs of all tracks. This may cause problems when Matroska files with different track numberings are used with EDL timelines. Change demux_lavf not to set demuxer IDs, since most time they are not set.
Diffstat (limited to 'libmpdemux/demuxer.c')
-rw-r--r--libmpdemux/demuxer.c179
1 files changed, 63 insertions, 116 deletions
diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c
index bc2e132c60..13f5fab268 100644
--- a/libmpdemux/demuxer.c
+++ b/libmpdemux/demuxer.c
@@ -189,10 +189,12 @@ static void free_demuxer_stream(struct demux_stream *ds)
free(ds);
}
-static struct demux_stream *new_demuxer_stream(struct demuxer *demuxer, int id)
+static struct demux_stream *new_demuxer_stream(struct demuxer *demuxer,
+ enum stream_type type, int id)
{
demux_stream_t *ds = malloc(sizeof(demux_stream_t));
- *ds = (demux_stream_t){
+ *ds = (demux_stream_t) {
+ .stream_type = type,
.id = id,
.demuxer = demuxer,
.asf_seq = -1,
@@ -200,6 +202,19 @@ static struct demux_stream *new_demuxer_stream(struct demuxer *demuxer, int id)
return ds;
}
+struct sh_stream *ds_gsh(struct demux_stream *ds)
+{
+ // Ideally ds would have a gsh field, but since all the old demuxers set
+ // ds->sh themselves and we don't want to change them, enjoy this hack.
+ if (!ds->sh)
+ return NULL;
+ switch (ds->stream_type) {
+ case STREAM_VIDEO: return ((struct sh_video *)ds->sh)->gsh;
+ case STREAM_AUDIO: return ((struct sh_audio *)ds->sh)->gsh;
+ case STREAM_SUB: return ((struct sh_sub *)ds->sh)->gsh;
+ }
+ assert(false);
+}
/**
* Get demuxer description structure for a given demuxer type
@@ -231,9 +246,12 @@ demuxer_t *new_demuxer(struct MPOpts *opts, stream_t *stream, int type,
d->seekable = 1;
d->synced = 0;
d->filepos = -1;
- d->audio = new_demuxer_stream(d, a_id);
- d->video = new_demuxer_stream(d, v_id);
- d->sub = new_demuxer_stream(d, s_id);
+ d->audio = new_demuxer_stream(d, STREAM_VIDEO, a_id);
+ d->video = new_demuxer_stream(d, STREAM_AUDIO, v_id);
+ d->sub = new_demuxer_stream(d, STREAM_SUB, s_id);
+ d->ds[STREAM_VIDEO] = d->video;
+ d->ds[STREAM_AUDIO] = d->audio;
+ d->ds[STREAM_SUB] = d->sub;
d->type = type;
d->opts = opts;
if (type)
@@ -269,8 +287,9 @@ static struct sh_stream *new_sh_stream(demuxer_t *demuxer,
{
struct sh_stream *sh = talloc_struct(demuxer, struct sh_stream, {
.type = type,
+ .demuxer = demuxer,
.index = demuxer->num_streams,
- .demuxer_id = demuxer->new_stream_id++, // possibly temporary value only
+ .demuxer_id = tid, // may be overwritten by demuxer
.tid = tid,
.stream_index = stream_index,
.opts = demuxer->opts,
@@ -308,7 +327,6 @@ static struct sh_stream *new_sh_stream(demuxer_t *demuxer,
}
default: assert(false);
}
- sh->common_header->id = sh->tid;
sh->common_header->opts = sh->opts;
sh->common_header->gsh = sh;
return sh;
@@ -1235,37 +1253,42 @@ int demux_control(demuxer_t *demuxer, int cmd, void *arg)
return DEMUXER_CTRL_NOTIMPL;
}
-int demuxer_switch_audio(demuxer_t *demuxer, int index)
+struct sh_stream *demuxer_stream_by_demuxer_id(struct demuxer *d,
+ enum stream_type t, int id)
{
- int res = demux_control(demuxer, DEMUXER_CTRL_SWITCH_AUDIO, &index);
- if (res == DEMUXER_CTRL_NOTIMPL) {
- struct sh_audio *sh_audio = demuxer->audio->sh;
- return sh_audio ? sh_audio->aid : -2;
+ for (int n = 0; n < d->num_streams; n++) {
+ struct sh_stream *s = d->streams[n];
+ if (s->type == t && s->demuxer_id == id)
+ return d->streams[n];
}
- if (demuxer->audio->id >= 0) {
- struct sh_audio *sh_audio = demuxer->a_streams[demuxer->audio->id];
- demuxer->audio->sh = sh_audio;
- index = sh_audio->aid; // internal MPEG demuxers don't set it right
- }
- else
- demuxer->audio->sh = NULL;
- return index;
+ return NULL;
}
-int demuxer_switch_video(demuxer_t *demuxer, int index)
-{
- int res = demux_control(demuxer, DEMUXER_CTRL_SWITCH_VIDEO, &index);
- if (res == DEMUXER_CTRL_NOTIMPL) {
- struct sh_video *sh_video = demuxer->video->sh;
- return sh_video ? sh_video->vid : -2;
+void demuxer_switch_track(struct demuxer *demuxer, enum stream_type type,
+ struct sh_stream *stream)
+{
+ assert(!stream || stream->type == type);
+ int index = stream ? stream->tid : -2;
+ if (type == STREAM_AUDIO) {
+ demux_control(demuxer, DEMUXER_CTRL_SWITCH_AUDIO, &index);
+ } else if (type == STREAM_VIDEO) {
+ demux_control(demuxer, DEMUXER_CTRL_SWITCH_VIDEO, &index);
+ } else if (type == STREAM_SUB) {
+ int index2 = stream ? stream->stream_index : -2;
+ if (demuxer->ds[type]->id != index2)
+ ds_free_packs(demuxer->ds[type]);
+ demuxer->ds[type]->id = index2;
}
- if (demuxer->video->id >= 0) {
- struct sh_video *sh_video = demuxer->v_streams[demuxer->video->id];
- demuxer->video->sh = sh_video;
- index = sh_video->vid; // internal MPEG demuxers don't set it right
- } else
- demuxer->video->sh = NULL;
- return index;
+ int new_id = demuxer->ds[type]->id;
+ void *new = NULL;
+ if (new_id >= 0) {
+ switch (type) {
+ case STREAM_VIDEO: new = demuxer->v_streams[new_id]; break;
+ case STREAM_AUDIO: new = demuxer->a_streams[new_id]; break;
+ case STREAM_SUB: new = demuxer->s_streams[new_id]; break;
+ }
+ }
+ demuxer->ds[type]->sh = new;
}
int demuxer_add_attachment(demuxer_t *demuxer, struct bstr name,
@@ -1456,91 +1479,15 @@ int demuxer_set_angle(demuxer_t *demuxer, int angle)
return angle;
}
-static char *demuxer_audio_lang(demuxer_t *d, int id)
-{
- struct stream_lang_req req;
- sh_audio_t *sh;
- if (id < 0 || id >= MAX_A_STREAMS)
- return NULL;
- sh = d->a_streams[id];
- if (!sh)
- return NULL;
- if (sh->lang)
- return talloc_strdup(NULL, sh->lang);
- req.type = stream_ctrl_audio;
- req.id = sh->aid;
- if (stream_control(d->stream, STREAM_CTRL_GET_LANG, &req) == STREAM_OK)
- return req.name;
- return NULL;
-}
-
-static char *demuxer_sub_lang(demuxer_t *d, int id)
+char *demuxer_stream_lang(demuxer_t *d, struct sh_stream *sh)
{
- struct stream_lang_req req;
- sh_sub_t *sh;
- if (id < 0 || id >= MAX_S_STREAMS)
- return NULL;
- sh = d->s_streams[id];
- if (sh && sh->lang)
- return talloc_strdup(NULL, sh->lang);
- req.type = stream_ctrl_sub;
- // assume 1:1 mapping so we can show the language of
- // DVD subs even when we have not yet created the stream.
- req.id = sh ? sh->sid : id;
+ struct stream_lang_req req = { .id = sh->tid }; // assume 1:1 mapping
+ switch (sh->type) {
+ case STREAM_AUDIO: req.type = stream_ctrl_audio; break;
+ case STREAM_SUB: req.type = stream_ctrl_sub; break;
+ default: return NULL;
+ }
if (stream_control(d->stream, STREAM_CTRL_GET_LANG, &req) == STREAM_OK)
return req.name;
return NULL;
}
-
-char *demuxer_stream_lang(demuxer_t *d, struct sh_stream *s)
-{
- switch (s->type) {
- case STREAM_AUDIO: return demuxer_audio_lang(d, s->stream_index);
- case STREAM_SUB: return demuxer_sub_lang(d, s->stream_index);
- default: return NULL;
- }
-}
-
-int demuxer_audio_track_by_lang_and_default(struct demuxer *d, char **langt)
-{
- int n = 0;
- while (1) {
- char *lang = langt ? langt[n++] : NULL;
- int id = -1;
- for (int i = 0; i < MAX_A_STREAMS; i++) {
- struct sh_audio *sh = d->a_streams[i];
- if (sh && (!lang || sh->lang && !strcmp(lang, sh->lang))) {
- if (sh->gsh->default_track)
- return sh->aid;
- if (id < 0)
- id = sh->aid;
- }
- }
- if (id >= 0)
- return id;
- if (!lang)
- return -1;
- }
-}
-
-int demuxer_sub_track_by_lang_and_default(struct demuxer *d, char **langt)
-{
- int n = 0;
- while (1) {
- char *lang = langt ? langt[n++] : NULL;
- int id = -1;
- for (int i = 0; i < MAX_S_STREAMS; i++) {
- struct sh_sub *sh = d->s_streams[i];
- if (sh && (!lang || sh->lang && !strcmp(lang, sh->lang))) {
- if (sh->gsh->default_track)
- return sh->sid;
- if (id < 0)
- id = sh->sid;
- }
- }
- if (!lang)
- return -1;
- if (id >= 0)
- return id;
- }
-}