summaryrefslogtreecommitdiffstats
path: root/player
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-10-21 13:16:48 +0200
committerwm4 <wm4@nowhere>2014-10-21 13:19:20 +0200
commitf0f83ff36600abc8715f3a11c31b2eeeda6c8c92 (patch)
tree38c6faba94976b08052fed67615d6680c748022e /player
parentbcc3d72995e926f899c0baa215599c50e23b9523 (diff)
downloadmpv-f0f83ff36600abc8715f3a11c31b2eeeda6c8c92.tar.bz2
mpv-f0f83ff36600abc8715f3a11c31b2eeeda6c8c92.tar.xz
player: add stream selection by ffmpeg index
Apparently using the stream index is the best way to refer to the same streams across multiple FFmpeg-using programs, even if the stream index itself is rarely meaningful in any way. For Matroska, there are some possible problems, depending how FFmpeg actually adds streams. Normally they seem to match though.
Diffstat (limited to 'player')
-rw-r--r--player/command.c36
-rw-r--r--player/core.h4
-rw-r--r--player/loadfile.c26
3 files changed, 55 insertions, 11 deletions
diff --git a/player/command.c b/player/command.c
index 4e74b690c9..d3d8fecbe6 100644
--- a/player/command.c
+++ b/player/command.c
@@ -1661,6 +1661,35 @@ static int property_switch_track(struct m_property *prop, int action, void *arg,
return mp_property_generic_option(mpctx, prop, action, arg);
}
+// Similar, less featured, for selecting by ff-index.
+static int property_switch_track_ff(void *ctx, struct m_property *prop,
+ int action, void *arg)
+{
+ MPContext *mpctx = ctx;
+ enum stream_type type = (intptr_t)prop->priv;
+ if (!mpctx->num_sources)
+ return M_PROPERTY_UNAVAILABLE;
+ struct track *track = mpctx->current_track[0][type];
+
+ switch (action) {
+ case M_PROPERTY_GET:
+ *(int *) arg = track ? track->ff_index : -2;
+ return M_PROPERTY_OK;
+ case M_PROPERTY_SET: {
+ track = NULL;
+ for (int n = 0; n < mpctx->num_tracks; n++) {
+ if (mpctx->tracks[n]->ff_index == *(int *)arg) {
+ track = mpctx->tracks[n];
+ break;
+ }
+ }
+ mp_switch_track_n(mpctx, 0, type, track);
+ return M_PROPERTY_OK;
+ }
+ }
+ return mp_property_generic_option(mpctx, prop, action, arg);
+}
+
static int get_track_entry(int item, int action, void *arg, void *ctx)
{
struct MPContext *mpctx = ctx;
@@ -1686,6 +1715,7 @@ static int get_track_entry(int item, int action, void *arg, void *ctx)
.unavailable = !track->external_filename},
{"codec", SUB_PROP_STR(codec),
.unavailable = !codec},
+ {"ff-index", SUB_PROP_INT(track->ff_index)},
{0}
};
@@ -3030,6 +3060,12 @@ static const struct m_property mp_properties[] = {
{"tv-channel", mp_property_tv_channel},
{"dvb-channel", mp_property_dvb_channel},
+#define TRACK_FF(name, type) \
+ {name, property_switch_track_ff, (void *)(intptr_t)type}
+ TRACK_FF("ff-vid", STREAM_VIDEO),
+ TRACK_FF("ff-aid", STREAM_AUDIO),
+ TRACK_FF("ff-sid", STREAM_SUB),
+
M_PROPERTY_ALIAS("video", "vid"),
M_PROPERTY_ALIAS("audio", "aid"),
M_PROPERTY_ALIAS("sub", "sid"),
diff --git a/player/core.h b/player/core.h
index 4d4142000c..f883ae2882 100644
--- a/player/core.h
+++ b/player/core.h
@@ -96,8 +96,8 @@ struct track {
// IDs coming from demuxers or container files.
int user_tid;
- // Same as stream->demuxer_id. -1 if not set.
- int demuxer_id;
+ int demuxer_id; // same as stream->demuxer_id. -1 if not set.
+ int ff_index; // same as stream->ff_index, or 0.
char *title;
bool default_track;
diff --git a/player/loadfile.c b/player/loadfile.c
index 470e0d24eb..b7dab134c7 100644
--- a/player/loadfile.c
+++ b/player/loadfile.c
@@ -340,6 +340,7 @@ static struct track *add_stream_track(struct MPContext *mpctx,
.type = stream->type,
.user_tid = find_new_tid(mpctx, stream->type),
.demuxer_id = stream->demuxer_id,
+ .ff_index = stream->ff_index,
.title = stream->title,
.default_track = stream->default_track,
.attached_picture = stream->attached_picture != NULL,
@@ -378,7 +379,8 @@ static int match_lang(char **langs, char *lang)
* tid is the track ID requested by the user (-2: deselect, -1: default)
* lang is a string list, NULL is same as empty list
* Sort tracks based on the following criteria, and pick the first:
- * 0) track matches tid (always wins)
+ * 0a) track matches ff-index (always wins)
+ * 0b) track matches tid (almost always wins)
* 1) track is external (no_default cancels this)
* 1b) track was passed explicitly (is not an auto-loaded subtitle)
* 2) earlier match in lang list
@@ -414,9 +416,12 @@ static bool compare_track(struct track *t1, struct track *t2, char **langs,
return t1->user_tid <= t2->user_tid;
}
static struct track *select_track(struct MPContext *mpctx,
- enum stream_type type, int tid, char **langs)
+ enum stream_type type, int tid, int ffid,
+ char **langs)
{
- if (tid == -2)
+ if (ffid != -1)
+ tid = -1; // prefer selecting ffid
+ if (tid == -2 || ffid == -2)
return NULL;
bool select_fallback = type == STREAM_VIDEO || type == STREAM_AUDIO;
struct track *pick = NULL;
@@ -426,6 +431,8 @@ static struct track *select_track(struct MPContext *mpctx,
continue;
if (track->user_tid == tid)
return track;
+ if (track->ff_index == ffid)
+ return track;
if (!pick || compare_track(track, pick, langs, mpctx->opts))
pick = track;
}
@@ -1094,15 +1101,16 @@ goto_reopen_demuxer: ;
check_previous_track_selection(mpctx);
mpctx->current_track[0][STREAM_VIDEO] =
- select_track(mpctx, STREAM_VIDEO, mpctx->opts->video_id, NULL);
+ select_track(mpctx, STREAM_VIDEO, opts->video_id, opts->video_id_ff,
+ NULL);
mpctx->current_track[0][STREAM_AUDIO] =
- select_track(mpctx, STREAM_AUDIO, mpctx->opts->audio_id,
- mpctx->opts->audio_lang);
+ select_track(mpctx, STREAM_AUDIO, opts->audio_id, opts->audio_id_ff,
+ opts->audio_lang);
mpctx->current_track[0][STREAM_SUB] =
- select_track(mpctx, STREAM_SUB, mpctx->opts->sub_id,
- mpctx->opts->sub_lang);
+ select_track(mpctx, STREAM_SUB, opts->sub_id, opts->sub_id_ff,
+ opts->sub_lang);
mpctx->current_track[1][STREAM_SUB] =
- select_track(mpctx, STREAM_SUB, mpctx->opts->sub2_id, NULL);
+ select_track(mpctx, STREAM_SUB, opts->sub2_id, -2, NULL);
for (int t = 0; t < STREAM_TYPE_COUNT; t++) {
for (int i = 0; i < NUM_PTRACKS; i++) {
struct track *track = mpctx->current_track[i][t];