summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--command.c650
-rw-r--r--input/input.c4
-rw-r--r--input/input.h4
-rw-r--r--libmpdemux/demux_lavf.c3
-rw-r--r--libmpdemux/demuxer.c179
-rw-r--r--libmpdemux/demuxer.h28
-rw-r--r--libmpdemux/stheader.h7
-rw-r--r--mp_core.h76
-rw-r--r--mplayer.c751
-rw-r--r--sub/av_sub.c5
-rw-r--r--sub/av_sub.h1
-rw-r--r--sub/sub.c3
12 files changed, 694 insertions, 1017 deletions
diff --git a/command.c b/command.c
index edb0e5a77a..065802b6d0 100644
--- a/command.c
+++ b/command.c
@@ -105,86 +105,6 @@ static void rescale_input_coordinates(struct MPContext *mpctx, int ix, int iy,
vo->dheight, vo_fs);
}
-static int sub_pos_by_source(MPContext *mpctx, int src)
-{
- int i, cnt = 0;
- if (src >= SUB_SOURCES || mpctx->sub_counts[src] == 0)
- return -1;
- for (i = 0; i < src; i++)
- cnt += mpctx->sub_counts[i];
- return cnt;
-}
-
-static int sub_source_and_index_by_pos(MPContext *mpctx, int *pos)
-{
- int start = 0;
- int i;
- for (i = 0; i < SUB_SOURCES; i++) {
- int cnt = mpctx->sub_counts[i];
- if (*pos >= start && *pos < start + cnt) {
- *pos -= start;
- return i;
- }
- start += cnt;
- }
- *pos = -1;
- return -1;
-}
-
-static int sub_source_by_pos(MPContext *mpctx, int pos)
-{
- return sub_source_and_index_by_pos(mpctx, &pos);
-}
-
-static int sub_source_pos(MPContext *mpctx)
-{
- int pos = mpctx->global_sub_pos;
- sub_source_and_index_by_pos(mpctx, &pos);
- return pos;
-}
-
-static int sub_source(MPContext *mpctx)
-{
- return sub_source_by_pos(mpctx, mpctx->global_sub_pos);
-}
-
-static void update_global_sub_size(MPContext *mpctx)
-{
- struct MPOpts *opts = &mpctx->opts;
- int i;
- int cnt = 0;
-
- if (!mpctx->demuxer) {
- mpctx->global_sub_size = -1;
- mpctx->global_sub_pos = -1;
- return;
- }
-
- // update number of demuxer sub streams
- for (i = 0; i < MAX_S_STREAMS; i++)
- if (mpctx->d_sub->demuxer->s_streams[i])
- cnt++;
- if (cnt > mpctx->sub_counts[SUB_SOURCE_DEMUX])
- mpctx->sub_counts[SUB_SOURCE_DEMUX] = cnt;
-
- // update global size
- mpctx->global_sub_size = 0;
- for (i = 0; i < SUB_SOURCES; i++)
- mpctx->global_sub_size += mpctx->sub_counts[i];
-
- // update global_sub_pos if we auto-detected a demuxer sub
- if (mpctx->global_sub_pos == -1) {
- int sub_id = -1;
- if (mpctx->demuxer->sub)
- sub_id = mpctx->demuxer->sub->id;
- if (sub_id < 0)
- sub_id = opts->sub_id;
- if (sub_id >= 0 && sub_id < mpctx->sub_counts[SUB_SOURCE_DEMUX])
- mpctx->global_sub_pos = sub_pos_by_source(mpctx, SUB_SOURCE_DEMUX) +
- sub_id;
- }
-}
-
static int mp_property_generic_option(struct m_option *prop, int action,
void *arg, MPContext *mpctx)
{
@@ -893,120 +813,91 @@ static int mp_property_balance(m_option_t *prop, int action, void *arg,
return M_PROPERTY_NOT_IMPLEMENTED;
}
-/// Selected audio id (RW)
-static int mp_property_audio(m_option_t *prop, int action, void *arg,
- MPContext *mpctx)
+static struct track* track_next(struct MPContext *mpctx, enum stream_type type,
+ int direction, struct track *track)
+{
+ assert(direction == -1 || direction == +1);
+ struct track *prev = NULL, *next = NULL;
+ bool seen = track == NULL;
+ for (int n = 0; n < mpctx->num_tracks; n++) {
+ struct track *cur = mpctx->tracks[n];
+ if (cur->type == type) {
+ if (cur == track) {
+ seen = true;
+ } else {
+ if (seen && !next) {
+ next = cur;
+ } else if (!seen || !track) {
+ prev = cur;
+ }
+ }
+ }
+ }
+ return direction > 0 ? next : prev;
+}
+
+static int property_switch_track(m_option_t *prop, int action, void *arg,
+ MPContext *mpctx, enum stream_type type)
{
- int current_id, tmp;
if (!mpctx->num_sources)
return M_PROPERTY_UNAVAILABLE;
- struct sh_audio *sh = mpctx->sh_audio;
- current_id = sh ? sh->aid : -2;
+ struct track *track = mpctx->current_track[type];
switch (action) {
case M_PROPERTY_GET:
if (!arg)
return M_PROPERTY_ERROR;
- *(int *) arg = current_id;
+ *(int *) arg = track ? track->user_tid : -1;
return M_PROPERTY_OK;
case M_PROPERTY_PRINT:
if (!arg)
return M_PROPERTY_ERROR;
- if (!sh || current_id < 0)
+ if (!track)
*(char **) arg = talloc_strdup(NULL, mp_gtext("disabled"));
else {
- char *lang = demuxer_stream_lang(sh->ds->demuxer, sh->gsh);
+ char *lang = track->lang;
if (!lang)
- lang = talloc_strdup(NULL, mp_gtext("unknown"));
+ lang = mp_gtext("unknown");
- if (sh->gsh->title)
+ if (track->title)
*(char **)arg = talloc_asprintf(NULL, "(%d) %s (\"%s\")",
- current_id, lang, sh->gsh->title);
+ track->user_tid, lang, track->title);
else
- *(char **)arg = talloc_asprintf(NULL, "(%d) %s", current_id,
- lang);
-
- talloc_free(lang);
+ *(char **)arg = talloc_asprintf(NULL, "(%d) %s",
+ track->user_tid, lang);
}
return M_PROPERTY_OK;
case M_PROPERTY_STEP_UP:
- case M_PROPERTY_SET:
+ case M_PROPERTY_STEP_DOWN:
+ case M_PROPERTY_SET: {
+ int i = (arg ? *((int *) arg) : +1) *
+ (action == M_PROPERTY_STEP_DOWN ? -1 : +1);
if (action == M_PROPERTY_SET && arg)
- tmp = *((int *) arg);
+ track = mp_track_by_tid(mpctx, type, i);
else
- tmp = -1;
- int new_id = demuxer_switch_audio(mpctx->d_audio->demuxer, tmp);
- if (new_id != current_id)
- uninit_player(mpctx, INITIALIZED_AO | INITIALIZED_ACODEC);
- if (new_id != current_id && new_id >= 0) {
- mpctx->opts.audio_id = new_id;
- sh_audio_t *sh2;
- sh2 = mpctx->d_audio->demuxer->a_streams[mpctx->d_audio->id];
- sh2->ds = mpctx->d_audio;
- mpctx->sh_audio = sh2;
- reinit_audio_chain(mpctx);
- }
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_TRACK=%d\n", new_id);
+ track = track_next(mpctx, type, i > 0 ? +1 : -1, track);
+ mp_switch_track(mpctx, type, track);
return M_PROPERTY_OK;
+ }
default:
return M_PROPERTY_NOT_IMPLEMENTED;
}
+}
+/// Selected audio id (RW)
+static int mp_property_audio(m_option_t *prop, int action, void *arg,
+ MPContext *mpctx)
+{
+ return property_switch_track(prop, action, arg, mpctx, STREAM_AUDIO);
}
/// Selected video id (RW)
static int mp_property_video(m_option_t *prop, int action, void *arg,
MPContext *mpctx)
{
- struct MPOpts *opts = &mpctx->opts;
- int current_id, tmp;
- if (!mpctx->num_sources)
- return M_PROPERTY_UNAVAILABLE;
- current_id = mpctx->sh_video ? mpctx->sh_video->vid : -2;
-
- switch (action) {
- case M_PROPERTY_GET:
- if (!arg)
- return M_PROPERTY_ERROR;
- *(int *) arg = current_id;
- return M_PROPERTY_OK;
- case M_PROPERTY_PRINT:
- if (!arg)
- return M_PROPERTY_ERROR;
-
- if (current_id < 0)
- *(char **) arg = talloc_strdup(NULL, mp_gtext("disabled"));
- else {
- *(char **) arg = talloc_asprintf(NULL, "(%d) %s", current_id,
- mp_gtext("unknown"));
- }
- return M_PROPERTY_OK;
-
- case M_PROPERTY_STEP_UP:
- case M_PROPERTY_SET:
- if (action == M_PROPERTY_SET && arg)
- tmp = *((int *) arg);
- else
- tmp = -1;
- int new_id = demuxer_switch_video(mpctx->d_video->demuxer, tmp);
- if (new_id != current_id)
- uninit_player(mpctx, INITIALIZED_VCODEC |
- (opts->fixed_vo && new_id >= 0 ? 0 : INITIALIZED_VO));
- if (new_id != current_id && new_id >= 0) {
- sh_video_t *sh2;
- sh2 = mpctx->d_video->demuxer->v_streams[mpctx->d_video->id];
- sh2->ds = mpctx->d_video;
- mpctx->sh_video = sh2;
- reinit_video_chain(mpctx);
- }
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_TRACK=%d\n", new_id);
- return M_PROPERTY_OK;
-
- default:
- return M_PROPERTY_NOT_IMPLEMENTED;
- }
+ return property_switch_track(prop, action, arg, mpctx, STREAM_VIDEO);
}
static int mp_property_program(m_option_t *prop, int action, void *arg,
@@ -1364,7 +1255,7 @@ static int mp_property_gamma(m_option_t *prop, int action, void *arg,
}
#ifdef CONFIG_TV
- if (mpctx->sh_video->ds->demuxer->type == DEMUXER_TYPE_TV) {
+ if (mpctx->sh_video->gsh->demuxer->type == DEMUXER_TYPE_TV) {
int l = strlen(prop->name);
char tv_prop[3 + l + 1];
sprintf(tv_prop, "tv_%s", prop->name);
@@ -1496,350 +1387,7 @@ static int mp_property_sub_pos(m_option_t *prop, int action, void *arg,
static int mp_property_sub(m_option_t *prop, int action, void *arg,
MPContext *mpctx)
{
- struct MPOpts *opts = &mpctx->opts;
- demux_stream_t *const d_sub = mpctx->d_sub;
- int source = -1, reset_spu av_unused = 0; // used under CONFIG_DVDREAD
- int source_pos = -1;
-
- update_global_sub_size(mpctx);
- const int global_sub_size = mpctx->global_sub_size;
-
- if (global_sub_size <= 0)
- return M_PROPERTY_UNAVAILABLE;
-
- switch (action) {
- case M_PROPERTY_GET:
- if (!arg)
- return M_PROPERTY_ERROR;
- *(int *) arg = mpctx->global_sub_pos;
- return M_PROPERTY_OK;
- case M_PROPERTY_PRINT:
- if (!arg)
- return M_PROPERTY_ERROR;
- char *sub_name = NULL;
- if (mpctx->subdata)
- sub_name = mpctx->subdata->filename;
-#ifdef CONFIG_ASS
- if (mpctx->osd->ass_track)
- sub_name = mpctx->osd->ass_track->name;
-#endif
- if (!sub_name && mpctx->subdata)
- sub_name = mpctx->subdata->filename;
- if (sub_name) {
- const char *tmp = mp_basename(sub_name);
-
- *(char **) arg = talloc_asprintf(NULL, "(%d) %s%s",
- mpctx->set_of_sub_pos + 1,
- strlen(tmp) < 20 ? "" : "...",
- strlen(tmp) < 20 ? tmp : tmp + strlen(tmp) - 19);
- return M_PROPERTY_OK;
- }
-
- if (vo_vobsub && vobsub_id >= 0) {
- const char *language = mp_gtext("unknown");
- language = vobsub_get_id(vo_vobsub, (unsigned int) vobsub_id);
- *(char **) arg = talloc_asprintf(NULL, "(%d) %s",
- vobsub_id, language ? language : mp_gtext("unknown"));
- return M_PROPERTY_OK;
- }
- if (opts->sub_id >= 0 && mpctx->d_sub && mpctx->d_sub->sh) {
- struct sh_stream *sh = ((struct sh_sub *)mpctx->d_sub->sh)->gsh;
- char *lang = demuxer_stream_lang(sh->common_header->ds->demuxer, sh);
- if (!lang)
- lang = talloc_strdup(NULL, mp_gtext("unknown"));
- if (sh->title)
- *(char **)arg = talloc_asprintf(NULL, "(%d) %s (\"%s\")",
- opts->sub_id, lang, sh->title);
- else
- *(char **) arg = talloc_asprintf(NULL, "(%d) %s", opts->sub_id,
- lang);
- talloc_free(lang);
- return M_PROPERTY_OK;
- }
- *(char **) arg = talloc_strdup(NULL, mp_gtext("disabled"));
- return M_PROPERTY_OK;
-
- case M_PROPERTY_SET:
- if (!arg)
- return M_PROPERTY_ERROR;
- if (*(int *) arg < -1)
- *(int *) arg = -1;
- else if (*(int *) arg >= global_sub_size)
- *(int *) arg = global_sub_size - 1;
- mpctx->global_sub_pos = *(int *) arg;
- break;
- case M_PROPERTY_STEP_UP:
- mpctx->global_sub_pos += 2;
- mpctx->global_sub_pos =
- (mpctx->global_sub_pos % (global_sub_size + 1)) - 1;
- break;
- case M_PROPERTY_STEP_DOWN:
- mpctx->global_sub_pos += global_sub_size + 1;
- mpctx->global_sub_pos =
- (mpctx->global_sub_pos % (global_sub_size + 1)) - 1;
- break;
- default:
- return M_PROPERTY_NOT_IMPLEMENTED;
- }
-
- if (mpctx->global_sub_pos >= 0) {
- source = sub_source(mpctx);
- source_pos = sub_source_pos(mpctx);
- }
-
- mp_msg(MSGT_CPLAYER, MSGL_DBG3,
- "subtitles: %d subs, (v@%d s@%d d@%d), @%d, source @%d\n",
- global_sub_size,
- mpctx->sub_counts[SUB_SOURCE_VOBSUB],
- mpctx->sub_counts[SUB_SOURCE_SUBS],
- mpctx->sub_counts[SUB_SOURCE_DEMUX],
- mpctx->global_sub_pos, source);
-
- mpctx->set_of_sub_pos = -1;
- mpctx->subdata = NULL;
-
- vobsub_id = -1;
- opts->sub_id = -1;
- if (d_sub) {
- if (d_sub->id > -2)
- reset_spu = 1;
- d_sub->id = -2;
- }
- mpctx->osd->ass_track = NULL;
- uninit_player(mpctx, INITIALIZED_SUB);
-
- if (source == SUB_SOURCE_VOBSUB)
- vobsub_id = vobsub_get_id_by_index(vo_vobsub, source_pos);
- else if (source == SUB_SOURCE_SUBS) {
- mpctx->set_of_sub_pos = source_pos;
-#ifdef CONFIG_ASS
- if (opts->ass_enabled
- && mpctx->set_of_ass_tracks[mpctx->set_of_sub_pos]) {
- mpctx->osd->ass_track =
- mpctx->set_of_ass_tracks[mpctx->set_of_sub_pos];
- mpctx->osd->ass_track_changed = true;
- mpctx->osd->vsfilter_aspect =
- mpctx->track_was_native_ass[mpctx->set_of_sub_pos];
- } else
-#endif
- {
- mpctx->subdata = mpctx->set_of_subtitles[mpctx->set_of_sub_pos];
- vo_osd_changed(OSDTYPE_SUBTITLE);
- }
- } else if (source == SUB_SOURCE_DEMUX) {
- opts->sub_id = source_pos;
- if (d_sub && opts->sub_id < MAX_S_STREAMS) {
- int i = 0;
- // default: assume 1:1 mapping of sid and stream id
- d_sub->id = opts->sub_id;
- d_sub->sh = mpctx->d_sub->demuxer->s_streams[d_sub->id];
- ds_free_packs(d_sub);
- for (i = 0; i < MAX_S_STREAMS; i++) {
- sh_sub_t *sh = mpctx->d_sub->demuxer->s_streams[i];
- if (sh && sh->sid == opts->sub_id) {
- d_sub->id = i;
- d_sub->sh = sh;
- break;
- }
- }
- if (d_sub->sh && d_sub->id >= 0) {
- sh_sub_t *sh = d_sub->sh;
- if (sh->type == 'v')
- init_vo_spudec(mpctx);
- else {
- sub_init(sh, mpctx->osd);
- mpctx->initialized_flags |= INITIALIZED_SUB;
- }
- } else {
- d_sub->id = -2;
- d_sub->sh = NULL;
- }
- }
- }
-#ifdef CONFIG_DVDREAD
- if (vo_spudec && (mpctx->stream->type == STREAMTYPE_DVD)
- && opts->sub_id < 0 && reset_spu)
- {
- d_sub->id = -2;
- d_sub->sh = NULL;
- }
-#endif
-
- update_subtitles(mpctx, 0, true);
-
- return M_PROPERTY_OK;
-}
-
-/// Selected sub source (RW)
-static int mp_property_sub_source(m_option_t *prop, int action, void *arg,
- MPContext *mpctx)
-{
- int source;
- update_global_sub_size(mpctx);
- if (!mpctx->sh_video || mpctx->global_sub_size <= 0)
- return M_PROPERTY_UNAVAILABLE;
-
- switch (action) {
- case M_PROPERTY_GET:
- if (!arg)
- return M_PROPERTY_ERROR;
- *(int *) arg = sub_source(mpctx);
- return M_PROPERTY_OK;
- case M_PROPERTY_PRINT:
- if (!arg)
- return M_PROPERTY_ERROR;
- char *sourcename;
- switch (sub_source(mpctx)) {
- case SUB_SOURCE_SUBS:
- sourcename = mp_gtext("file");
- break;
- case SUB_SOURCE_VOBSUB:
- sourcename = mp_gtext("vobsub");
- break;
- case SUB_SOURCE_DEMUX:
- sourcename = mp_gtext("embedded");
- break;
- default:
- sourcename = mp_gtext("disabled");
- }
- *(char **)arg = talloc_strdup(NULL, sourcename);
- return M_PROPERTY_OK;
- case M_PROPERTY_SET:
- if (!arg)
- return M_PROPERTY_ERROR;
- M_PROPERTY_CLAMP(prop, *(int *)arg);
- if (*(int *) arg < 0)
- mpctx->global_sub_pos = -1;
- else if (*(int *) arg != sub_source(mpctx)) {
- int new_pos = sub_pos_by_source(mpctx, *(int *)arg);
- if (new_pos == -1)
- return M_PROPERTY_UNAVAILABLE;
- mpctx->global_sub_pos = new_pos;
- }
- break;
- case M_PROPERTY_STEP_UP:
- case M_PROPERTY_STEP_DOWN: {
- int step_all = (arg && *(int *)arg != 0 ? *(int *)arg : 1)
- * (action == M_PROPERTY_STEP_UP ? 1 : -1);
- int step = (step_all > 0) ? 1 : -1;
- int cur_source = sub_source(mpctx);
- source = cur_source;
- while (step_all) {
- source += step;
- if (source >= SUB_SOURCES)
- source = -1;
- else if (source < -1)
- source = SUB_SOURCES - 1;
- if (source == cur_source || source == -1 ||
- mpctx->sub_counts[source])
- step_all -= step;
- }
- if (source == cur_source)
- return M_PROPERTY_OK;
- if (source == -1)
- mpctx->global_sub_pos = -1;
- else
- mpctx->global_sub_pos = sub_pos_by_source(mpctx, source);
- break;
- }
- default:
- return M_PROPERTY_NOT_IMPLEMENTED;
- }
- --mpctx->global_sub_pos;
- return mp_property_sub(prop, M_PROPERTY_STEP_UP, NULL, mpctx);
-}
-
-/// Selected subtitles from specific source (RW)
-static int mp_property_sub_by_type(m_option_t *prop, int action, void *arg,
- MPContext *mpctx)
-{
- int source, is_cur_source, offset, new_pos;
- update_global_sub_size(mpctx);
- if (!mpctx->sh_video || mpctx->global_sub_size <= 0)
- return M_PROPERTY_UNAVAILABLE;
-
- if (!strcmp(prop->name, "sub_file"))
- source = SUB_SOURCE_SUBS;
- else if (!strcmp(prop->name, "sub_vob"))
- source = SUB_SOURCE_VOBSUB;
- else if (!strcmp(prop->name, "sub_demux"))
- source = SUB_SOURCE_DEMUX;
- else
- return M_PROPERTY_ERROR;
-
- offset = sub_pos_by_source(mpctx, source);
- if (offset < 0)
- return M_PROPERTY_UNAVAILABLE;
-
- is_cur_source = sub_source(mpctx) == source;
- new_pos = mpctx->global_sub_pos;
- switch (action) {
- case M_PROPERTY_GET:
- if (!arg)
- return M_PROPERTY_ERROR;
- if (is_cur_source) {
- *(int *) arg = sub_source_pos(mpctx);
- if (source == SUB_SOURCE_VOBSUB)
- *(int *) arg = vobsub_get_id_by_index(vo_vobsub, *(int *) arg);
- } else
- *(int *) arg = -1;
- return M_PROPERTY_OK;
- case M_PROPERTY_PRINT:
- if (!arg)
- return M_PROPERTY_ERROR;
- if (is_cur_source)
- return mp_property_sub(prop, M_PROPERTY_PRINT, arg, mpctx);
- *(char **) arg = talloc_strdup(NULL, mp_gtext("disabled"));
- return M_PROPERTY_OK;
- case M_PROPERTY_SET:
- if (!arg)
- return M_PROPERTY_ERROR;
- if (*(int *) arg >= 0) {
- int index = *(int *)arg;
- if (source == SUB_SOURCE_VOBSUB)
- index = vobsub_get_index_by_id(vo_vobsub, index);
- new_pos = offset + index;
- if (index < 0 || index > mpctx->sub_counts[source]) {
- new_pos = -1;
- *(int *) arg = -1;
- }
- } else
- new_pos = -1;
- break;
- case M_PROPERTY_STEP_UP:
- case M_PROPERTY_STEP_DOWN: {
- int step_all = (arg && *(int *)arg != 0 ? *(int *)arg : 1)
- * (action == M_PROPERTY_STEP_UP ? 1 : -1);
- int step = (step_all > 0) ? 1 : -1;
- int max_sub_pos_for_source = -1;
- if (!is_cur_source)
- new_pos = -1;
- while (step_all) {
- if (new_pos == -1) {
- if (step > 0)
- new_pos = offset;
- else if (max_sub_pos_for_source == -1) {
- // Find max pos for specific source
- new_pos = mpctx->global_sub_size - 1;
- while (new_pos >= 0 && sub_source(mpctx) != source)
- new_pos--;
- } else
- new_pos = max_sub_pos_for_source;
- } else {
- new_pos += step;
- if (new_pos < offset ||
- new_pos >= mpctx->global_sub_size ||
- sub_source(mpctx) != source)
- new_pos = -1;
- }
- step_all -= step;
- }
- break;
- }
- default:
- return M_PROPERTY_NOT_IMPLEMENTED;
- }
- return mp_property_sub(prop, M_PROPERTY_SET, &new_pos, mpctx);
+ return property_switch_track(prop, action, arg, mpctx, STREAM_SUB);
}
/// Subtitle delay (RW)
@@ -1859,8 +1407,7 @@ static int mp_property_sub_alignment(m_option_t *prop, int action,
_("top"), _("center"), _("bottom")
};
- if (!mpctx->sh_video || mpctx->global_sub_pos < 0
- || sub_source(mpctx) != SUB_SOURCE_SUBS)
+ if (!mpctx->current_track[STREAM_SUB])
return M_PROPERTY_UNAVAILABLE;
switch (action) {
@@ -2183,14 +1730,6 @@ static const m_option_t mp_properties[] = {
// Subs
{ "sub", mp_property_sub, CONF_TYPE_INT,
M_OPT_MIN, -1, 0, NULL },
- { "sub_source", mp_property_sub_source, CONF_TYPE_INT,
- M_OPT_RANGE, -1, SUB_SOURCES - 1, NULL },
- { "sub_vob", mp_property_sub_by_type, CONF_TYPE_INT,
- M_OPT_MIN, -1, 0, NULL },
- { "sub_demux", mp_property_sub_by_type, CONF_TYPE_INT,
- M_OPT_MIN, -1, 0, NULL },
- { "sub_file", mp_property_sub_by_type, CONF_TYPE_INT,
- M_OPT_MIN, -1, 0, NULL },
{ "sub_delay", mp_property_sub_delay, CONF_TYPE_FLOAT,
0, 0, 0, NULL },
{ "sub_pos", mp_property_sub_pos, CONF_TYPE_INT,
@@ -2299,10 +1838,6 @@ static struct property_osd_display {
{ "vsync", 0, -1, _("VSync: %s") },
// subs
{ "sub", 0, -1, _("Subtitles: %s") },
- { "sub_source", 0, -1, _("Sub source: %s") },
- { "sub_vob", 0, -1, _("Subtitles: %s") },
- { "sub_demux", 0, -1, _("Subtitles: %s") },
- { "sub_file", 0, -1, _("Subtitles: %s") },
{ "sub_pos", 0, -1, _("Sub position: %s/100") },
{ "sub_alignment", 0, -1, _("Sub alignment: %s") },
{ "sub_delay", 0, OSD_MSG_SUB_DELAY, _("Sub delay: %s") },
@@ -2423,10 +1958,6 @@ static struct {
{ "vsync", MP_CMD_SWITCH_VSYNC, 1},
// subs
{ "sub", MP_CMD_SUB_SELECT, 1},
- { "sub_source", MP_CMD_SUB_SOURCE, 1},
- { "sub_vob", MP_CMD_SUB_VOB, 1},
- { "sub_demux", MP_CMD_SUB_DEMUX, 1},
- { "sub_file", MP_CMD_SUB_FILE, 1},
{ "sub_pos", MP_CMD_SUB_POS, 0},
{ "sub_alignment", MP_CMD_SUB_ALIGNMENT, 1},
{ "sub_delay", MP_CMD_SUB_DELAY, 0},
@@ -2539,52 +2070,46 @@ static void show_chapters_on_osd(MPContext *mpctx)
talloc_free(res);
}
+static const char *track_type_name(enum stream_type t)
+{
+ switch (t) {
+ case STREAM_VIDEO: return "Video";
+ case STREAM_AUDIO: return "Audio";
+ case STREAM_SUB: return "Sub";
+ }
+ return NULL;
+}
+
static void show_tracks_on_osd(MPContext *mpctx)
{
struct MPOpts *opts = &mpctx->opts;
- demuxer_t *demuxer = mpctx->master_demuxer;
char *res = NULL;
- if (!demuxer)
- return;
-
- struct sh_stream *cur_a = mpctx->sh_audio ? mpctx->sh_audio->gsh : NULL;
- struct sh_stream *cur_s = NULL;
- if (opts->sub_id >= 0 && mpctx->d_sub && mpctx->d_sub->sh)
- cur_s = ((struct sh_sub *)mpctx->d_sub->sh)->gsh;
-
- int v_count = 0;
- enum stream_type t = STREAM_AUDIO;
-
- for (int n = 0; n < demuxer->num_streams; n++) {
- struct sh_stream *sh = demuxer->streams[n];
- if (sh->type == STREAM_VIDEO) {
- v_count++;
- continue;
- }
- if (t != sh->type)
+ for (int type = 0; type < STREAM_TYPE_COUNT; type++) {
+ for (int n = 0; n < mpctx->num_tracks; n++) {
+ struct track *track = mpctx->tracks[n];
+ if (track->type != type)
+ continue;
+
+ bool selected = mpctx->current_track[track->type] == track;
+ res = talloc_asprintf_append(res, "%s: ", track_type_name(track->type));
+ if (selected)
+ res = talloc_asprintf_append(res, "> ");
+ res = talloc_asprintf_append(res, "(%d) ", track->user_tid);
+ if (track->title)
+ res = talloc_asprintf_append(res, "'%s' ", track->title);
+ if (track->lang)
+ res = talloc_asprintf_append(res, "(%s) ", track->lang);
+ if (track->is_external)
+ res = talloc_asprintf_append(res, "(external) ");
+ if (selected)
+ res = talloc_asprintf_append(res, "<");
res = talloc_asprintf_append(res, "\n");
- bool selected = sh == cur_a || sh == cur_s;
- res = talloc_asprintf_append(res, "%s: ",
- sh->type == STREAM_AUDIO ? "Audio" : "Sub");
- if (selected)
- res = talloc_asprintf_append(res, "> ");
- res = talloc_asprintf_append(res, "(%d) ", sh->tid);
- if (sh->title)
- res = talloc_asprintf_append(res, "'%s' ", sh->title);
- char *lang = demuxer_stream_lang(sh->common_header->ds->demuxer, sh);
- if (lang)
- res = talloc_asprintf_append(res, "(%s) ", lang);
- talloc_free(lang);
- if (selected)
- res = talloc_asprintf_append(res, "<");
+ }
+
res = talloc_asprintf_append(res, "\n");
- t = sh->type;
}
- if (v_count > 1)
- res = talloc_asprintf_append(res, "\n(Warning: more than one video stream.)\n");
-
set_osd_msg(mpctx, OSD_MSG_TEXT, 1, opts->osd_duration, "%s", res);
talloc_free(res);
}
@@ -2783,7 +2308,9 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
case MP_CMD_SUB_STEP:
if (sh_video) {
int movement = cmd->args[0].v.i;
- step_sub(mpctx->subdata, mpctx->video_pts, movement);
+ struct track *track = mpctx->current_track[STREAM_SUB];
+ if (track && track->subdata)
+ step_sub(track->subdata, mpctx->video_pts, movement);
#ifdef CONFIG_ASS
if (mpctx->osd->ass_track)
sub_delay +=
@@ -3083,12 +2610,7 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
case MP_CMD_SUB_LOAD:
if (sh_video) {
- int n = mpctx->set_of_sub_size;
add_subtitles(mpctx, cmd->args[0].v.s, sh_video->fps, 0);
- if (n != mpctx->set_of_sub_size) {
- mpctx->sub_counts[SUB_SOURCE_SUBS]++;
- ++mpctx->global_sub_size;
- }
}
break;
diff --git a/input/input.c b/input/input.c
index 4ea9e0c531..d1136532ed 100644
--- a/input/input.c
+++ b/input/input.c
@@ -134,10 +134,6 @@ static const mp_cmd_t mp_cmds[] = {
{ MP_CMD_SUB_LOAD, "sub_load", { ARG_STRING } },
{ MP_CMD_SUB_SELECT, "vobsub_lang", { OARG_INT(-2) } }, // for compatibility
{ MP_CMD_SUB_SELECT, "sub_select", { OARG_INT(-2) } },
- { MP_CMD_SUB_SOURCE, "sub_source", { OARG_INT(-2) } },
- { MP_CMD_SUB_VOB, "sub_vob", { OARG_INT(-2) } },
- { MP_CMD_SUB_DEMUX, "sub_demux", { OARG_INT(-2) } },
- { MP_CMD_SUB_FILE, "sub_file", { OARG_INT(-2) } },
{ MP_CMD_SUB_SCALE, "sub_scale", { ARG_FLOAT, OARG_INT(0) } },
#ifdef CONFIG_ASS
{ MP_CMD_ASS_USE_MARGINS, "ass_use_margins", { OARG_INT(-1) } },
diff --git a/input/input.h b/input/input.h
index e1e333c486..a055b59138 100644
--- a/input/input.h
+++ b/input/input.h
@@ -118,10 +118,6 @@ enum mp_command_type {
MP_CMD_BALANCE,
MP_CMD_SUB_SCALE,
MP_CMD_TV_START_SCAN,
- MP_CMD_SUB_SOURCE,
- MP_CMD_SUB_FILE,
- MP_CMD_SUB_VOB,
- MP_CMD_SUB_DEMUX,
MP_CMD_SWITCH_ANGLE,
MP_CMD_ASS_USE_MARGINS,
MP_CMD_SWITCH_TITLE,
diff --git a/libmpdemux/demux_lavf.c b/libmpdemux/demux_lavf.c
index baf013a8ef..4dd9938d07 100644
--- a/libmpdemux/demux_lavf.c
+++ b/libmpdemux/demux_lavf.c
@@ -309,7 +309,6 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i)
sh_audio = new_sh_audio_aid(demuxer, i, priv->audio_streams);
if (!sh_audio)
break;
- sh_audio->gsh->demuxer_id = i;
sh_audio->demuxer_codecname = codec_name;
stream_type = "audio";
priv->astreams[priv->audio_streams] = i;
@@ -391,7 +390,6 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i)
sh_video = new_sh_video_vid(demuxer, i, priv->video_streams);
if (!sh_video)
break;
- sh_video->gsh->demuxer_id = i;
sh_video->demuxer_codecname = codec_name;
stream_type = "video";
priv->vstreams[priv->video_streams] = i;
@@ -504,7 +502,6 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i)
sh_sub = new_sh_sub_sid(demuxer, i, priv->sub_streams);
if (!sh_sub)
break;
- sh_sub->gsh->demuxer_id = i;
sh_sub->demuxer_codecname = codec_name;
stream_type = "subtitle";
priv->sstreams[priv->sub_streams] = i;
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 DEMUX