diff options
-rw-r--r-- | command.c | 650 | ||||
-rw-r--r-- | input/input.c | 4 | ||||
-rw-r--r-- | input/input.h | 4 | ||||
-rw-r--r-- | libmpdemux/demux_lavf.c | 3 | ||||
-rw-r--r-- | libmpdemux/demuxer.c | 179 | ||||
-rw-r--r-- | libmpdemux/demuxer.h | 28 | ||||
-rw-r--r-- | libmpdemux/stheader.h | 7 | ||||
-rw-r--r-- | mp_core.h | 76 | ||||
-rw-r--r-- | mplayer.c | 751 | ||||
-rw-r--r-- | sub/av_sub.c | 5 | ||||
-rw-r--r-- | sub/av_sub.h | 1 | ||||
-rw-r--r-- | sub/sub.c | 3 |
12 files changed, 694 insertions, 1017 deletions
@@ -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-> |