From 1663d97a112261c10f989b70547545048f9e31c3 Mon Sep 17 00:00:00 2001 From: reimar Date: Sat, 10 Jul 2010 20:48:50 +0000 Subject: [PATCH] subs: Change global subtitle numbering scheme Change numbering so that demuxers can "asynchronously" add subtitles during playback. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@31678 b3059339-0415-0410-9bf9-f77b7e298cf2 Fix calculation of global_sub_size. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@31711 b3059339-0415-0410-9bf9-f77b7e298cf2 Update global_sub_pos if we auto-selected a subtitle. This avoid strange behaviour with subtitle selection in that case, because the subtitle selection code thinks no subtitle was displayed while we actually did display one. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@31863 b3059339-0415-0410-9bf9-f77b7e298cf2 Move function to avoid a forward declaration. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@31864 b3059339-0415-0410-9bf9-f77b7e298cf2 Fix subtitle selection: make selecting -sid 0 work again by replacing the M_PROPERTY_STEP_UP hack by M_PROPERTY_SET and set the global sub pos also when we do not yet have a subtitle stream but do know the number of subs from out-of-band as e.g. for DVD. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@31882 b3059339-0415-0410-9bf9-f77b7e298cf2 100l, re-add vobsub_get_id_by_index call accidentally removed in r31678. Patch by ubitux [ubitux gmail com]. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@31985 b3059339-0415-0410-9bf9-f77b7e298cf2 --- command.c | 153 ++++++++++++++++++++++++++++++++++++++++++-------------------- mp_core.h | 2 +- mplayer.c | 76 +++++++++++++------------------ 3 files changed, 138 insertions(+), 93 deletions(-) diff --git a/command.c b/command.c index 8c3ad5d778..3a9c3aa179 100644 --- a/command.c +++ b/command.c @@ -103,19 +103,42 @@ static void rescale_input_coordinates(struct MPContext *mpctx, int ix, int iy, vo->dheight, vo_fs); } -static int sub_source_by_pos(MPContext *mpctx, int pos) +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 source = -1; - int top = -1; + int start = 0; int i; for (i = 0; i < SUB_SOURCES; i++) { - int j = mpctx->global_sub_indices[i]; - if ((j >= 0) && (j > top) && (pos >= j)) { - source = i; - top = j; + int cnt = mpctx->sub_counts[i]; + if (*pos >= start && *pos < start + cnt) { + *pos -= start; + return i; } + start += cnt; } - return source; + *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) @@ -123,6 +146,37 @@ 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; + + // update number of demuxer sub streams + for (i = 0; i < MAX_S_STREAMS; i++) + if (mpctx->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; + } +} + /** * \brief Log the currently displayed subtitle to a file * @@ -1400,10 +1454,13 @@ static int mp_property_sub(m_option_t *prop, int action, void *arg, { struct MPOpts *opts = &mpctx->opts; demux_stream_t *const d_sub = mpctx->d_sub; - const int global_sub_size = mpctx->global_sub_size; int source = -1, reset_spu = 0; + int source_pos = -1; char *sub_name; + update_global_sub_size(mpctx); + const int global_sub_size = mpctx->global_sub_size; + if (global_sub_size <= 0) return M_PROPERTY_UNAVAILABLE; @@ -1510,15 +1567,17 @@ static int mp_property_sub(m_option_t *prop, int action, void *arg, return M_PROPERTY_NOT_IMPLEMENTED; } - if (mpctx->global_sub_pos >= 0) + 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->global_sub_indices[SUB_SOURCE_VOBSUB], - mpctx->global_sub_indices[SUB_SOURCE_SUBS], - mpctx->global_sub_indices[SUB_SOURCE_DEMUX], + 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; @@ -1536,10 +1595,9 @@ static int mp_property_sub(m_option_t *prop, int action, void *arg, #endif if (source == SUB_SOURCE_VOBSUB) { - vobsub_id = vobsub_get_id_by_index(vo_vobsub, mpctx->global_sub_pos - mpctx->global_sub_indices[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 = - mpctx->global_sub_pos - mpctx->global_sub_indices[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]) ass_track = mpctx->set_of_ass_tracks[mpctx->set_of_sub_pos]; @@ -1550,8 +1608,7 @@ static int mp_property_sub(m_option_t *prop, int action, void *arg, vo_osd_changed(OSDTYPE_SUBTITLE); } } else if (source == SUB_SOURCE_DEMUX) { - opts->sub_id = - mpctx->global_sub_pos - mpctx->global_sub_indices[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 @@ -1600,6 +1657,7 @@ 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; @@ -1636,9 +1694,10 @@ static int mp_property_sub_source(m_option_t *prop, int action, void *arg, if (*(int *) arg < 0) mpctx->global_sub_pos = -1; else if (*(int *) arg != sub_source(mpctx)) { - if (*(int *) arg != sub_source_by_pos(mpctx, mpctx->global_sub_indices[*(int *) arg])) + int new_pos = sub_pos_by_source(mpctx, *(int *)arg); + if (new_pos == -1) return M_PROPERTY_UNAVAILABLE; - mpctx->global_sub_pos = mpctx->global_sub_indices[*(int *) arg]; + mpctx->global_sub_pos = new_pos; } break; case M_PROPERTY_STEP_UP: @@ -1655,7 +1714,7 @@ static int mp_property_sub_source(m_option_t *prop, int action, void *arg, else if (source < -1) source = SUB_SOURCES - 1; if (source == cur_source || source == -1 || - source == sub_source_by_pos(mpctx, mpctx->global_sub_indices[source])) + mpctx->sub_counts[source]) step_all -= step; } if (source == cur_source) @@ -1663,7 +1722,7 @@ static int mp_property_sub_source(m_option_t *prop, int action, void *arg, if (source == -1) mpctx->global_sub_pos = -1; else - mpctx->global_sub_pos = mpctx->global_sub_indices[source]; + mpctx->global_sub_pos = sub_pos_by_source(mpctx, source); break; } default: @@ -1677,7 +1736,8 @@ static int mp_property_sub_source(m_option_t *prop, int action, void *arg, static int mp_property_sub_by_type(m_option_t *prop, int action, void *arg, MPContext *mpctx) { - int source, is_cur_source, offset; + 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; @@ -1690,17 +1750,18 @@ static int mp_property_sub_by_type(m_option_t *prop, int action, void *arg, else return M_PROPERTY_ERROR; - offset = mpctx->global_sub_indices[source]; - if (offset < 0 || source != sub_source_by_pos(mpctx, offset)) + 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 = mpctx->global_sub_pos - offset; + *(int *) arg = sub_source_pos(mpctx); if (source == SUB_SOURCE_VOBSUB) *(int *) arg = vobsub_get_id_by_index(vo_vobsub, *(int *) arg); } @@ -1723,15 +1784,14 @@ static int mp_property_sub_by_type(m_option_t *prop, int action, void *arg, int index = *(int *)arg; if (source == SUB_SOURCE_VOBSUB) index = vobsub_get_index_by_id(vo_vobsub, index); - mpctx->global_sub_pos = offset + index; - if (index < 0 || mpctx->global_sub_pos >= mpctx->global_sub_size - || sub_source(mpctx) != source) { - mpctx->global_sub_pos = -1; + new_pos = offset + index; + if (index < 0 || index > mpctx->sub_counts[source]) { + new_pos = -1; *(int *) arg = -1; } } else - mpctx->global_sub_pos = -1; + new_pos = -1; break; case M_PROPERTY_STEP_UP: case M_PROPERTY_STEP_DOWN: { @@ -1740,27 +1800,27 @@ static int mp_property_sub_by_type(m_option_t *prop, int action, void *arg, int step = (step_all > 0) ? 1 : -1; int max_sub_pos_for_source = -1; if (!is_cur_source) - mpctx->global_sub_pos = -1; + new_pos = -1; while (step_all) { - if (mpctx->global_sub_pos == -1) { + if (new_pos == -1) { if (step > 0) - mpctx->global_sub_pos = offset; + new_pos = offset; else if (max_sub_pos_for_source == -1) { // Find max pos for specific source - mpctx->global_sub_pos = mpctx->global_sub_size - 1; - while (mpctx->global_sub_pos >= 0 + new_pos = mpctx->global_sub_size - 1; + while (new_pos >= 0 && sub_source(mpctx) != source) - --mpctx->global_sub_pos; + new_pos--; } else - mpctx->global_sub_pos = max_sub_pos_for_source; + new_pos = max_sub_pos_for_source; } else { - mpctx->global_sub_pos += step; - if (mpctx->global_sub_pos < offset || - mpctx->global_sub_pos >= mpctx->global_sub_size || + new_pos += step; + if (new_pos < offset || + new_pos >= mpctx->global_sub_size || sub_source(mpctx) != source) - mpctx->global_sub_pos = -1; + new_pos = -1; } step_all -= step; } @@ -1769,8 +1829,7 @@ static int mp_property_sub_by_type(m_option_t *prop, int action, void *arg, default: return M_PROPERTY_NOT_IMPLEMENTED; } - --mpctx->global_sub_pos; - return mp_property_sub(prop, M_PROPERTY_STEP_UP, NULL, mpctx); + return mp_property_sub(prop, M_PROPERTY_SET, &new_pos, mpctx); } /// Subtitle delay (RW) @@ -2545,7 +2604,7 @@ static void remove_subtitle_range(MPContext *mpctx, int start, int count) mpctx->global_sub_size -= count; mpctx->set_of_sub_size -= count; if (mpctx->set_of_sub_size <= 0) - mpctx->global_sub_indices[SUB_SOURCE_SUBS] = -1; + mpctx->sub_counts[SUB_SOURCE_SUBS] = 0; memmove(subs + start, subs + end, after * sizeof(*subs)); memset(subs + start + after, 0, count * sizeof(*subs)); @@ -3133,9 +3192,7 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) 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) { - if (mpctx->global_sub_indices[SUB_SOURCE_SUBS] < 0) - mpctx->global_sub_indices[SUB_SOURCE_SUBS] = - mpctx->global_sub_size; + mpctx->sub_counts[SUB_SOURCE_SUBS]++; ++mpctx->global_sub_size; } } diff --git a/mp_core.h b/mp_core.h index 1a01109307..9ef9e6c972 100644 --- a/mp_core.h +++ b/mp_core.h @@ -169,7 +169,7 @@ typedef struct MPContext { int global_sub_pos; // this encompasses all subtitle sources int set_of_sub_pos; int set_of_sub_size; - int global_sub_indices[SUB_SOURCES]; + int sub_counts[SUB_SOURCES]; // set_of_ass_tracks[i] contains subtitles from set_of_subtitles[i] // parsed by libass or NULL if format unsupported struct ass_track *set_of_ass_tracks[MAX_SUBTITLE_FILES]; diff --git a/mplayer.c b/mplayer.c index ad25bd9cbd..f29edd7021 100644 --- a/mplayer.c +++ b/mplayer.c @@ -1949,33 +1949,43 @@ static float timing_sleep(struct MPContext *mpctx, float time_frame) return time_frame; } -static void select_subtitle(MPContext *mpctx) +static int select_subtitle(MPContext *mpctx) { struct MPOpts *opts = &mpctx->opts; // find the best sub to use - int vobsub_index_id = vobsub_get_index_by_id(vo_vobsub, vobsub_id); + int id; + int found = 0; mpctx->global_sub_pos = -1; // no subs by default - if (vobsub_index_id >= 0) { + if (vobsub_id >= 0) { // if user asks for a vobsub id, use that first. - mpctx->global_sub_pos = mpctx->global_sub_indices[SUB_SOURCE_VOBSUB] + vobsub_index_id; - } else if (opts->sub_id >= 0 && mpctx->global_sub_indices[SUB_SOURCE_DEMUX] >= 0) { + id = vobsub_id; + found = mp_property_do("sub_vob", M_PROPERTY_SET, &id, mpctx) == M_PROPERTY_OK; + } + + if (!found && opts->sub_id >= 0) { // if user asks for a dvd sub id, use that next. - mpctx->global_sub_pos = mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + opts->sub_id; - } else if (mpctx->global_sub_indices[SUB_SOURCE_SUBS] >= 0) { + id = opts->sub_id; + found = mp_property_do("sub_demux", M_PROPERTY_SET, &id, mpctx) == M_PROPERTY_OK; + } + + if (!found) { // if there are text subs to use, use those. (autosubs come last here) - mpctx->global_sub_pos = mpctx->global_sub_indices[SUB_SOURCE_SUBS]; - } else if (opts->sub_id == -1 && mpctx->global_sub_indices[SUB_SOURCE_DEMUX] >= 0) { + id = 0; + found = mp_property_do("sub_file", M_PROPERTY_SET, &id, mpctx) == M_PROPERTY_OK; + } + + if (!found && opts->sub_id == -1) { // finally select subs by language and container hints if (opts->sub_id == -1 && opts->sub_lang) opts->sub_id = demuxer_sub_track_by_lang(mpctx->demuxer, opts->sub_lang); if (opts->sub_id == -1) opts->sub_id = demuxer_default_sub_track(mpctx->demuxer); - if (opts->sub_id >= 0) - mpctx->global_sub_pos = mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + opts->sub_id; + if (opts->sub_id >= 0) { + id = opts->sub_id; + found = mp_property_do("sub_demux", M_PROPERTY_SET, &id, mpctx) == M_PROPERTY_OK; + } } - // rather than duplicate code, use the SUB_SELECT handler to init the right one. - mpctx->global_sub_pos--; - mp_property_do("sub",M_PROPERTY_STEP_UP,NULL, mpctx); + return found; } #ifdef CONFIG_DVDNAV @@ -2035,7 +2045,7 @@ static void mp_dvdnav_reset_stream (MPContext *ctx) { } audio_delay = 0.0f; - ctx->global_sub_size = ctx->global_sub_indices[SUB_SOURCE_DEMUX] + mp_dvdnav_number_of_subs(ctx->stream); + ctx->sub_counts[SUB_SOURCE_DEMUX] = mp_dvdnav_number_of_subs(ctx->stream); if (opts->sub_lang && opts->sub_id == dvdsub_lang_id) { dvdsub_lang_id = mp_dvdnav_sid_from_lang(ctx->stream, opts->sub_lang); if (dvdsub_lang_id != opts->sub_id) { @@ -3438,7 +3448,7 @@ play_next_file: // init global sub numbers mpctx->global_sub_size = 0; - { int i; for (i = 0; i < SUB_SOURCES; i++) mpctx->global_sub_indices[i] = -1; } + memset(mpctx->sub_counts, 0, sizeof(mpctx->sub_counts)); if (mpctx->filename) { load_per_protocol_config (mpctx->mconfig, mpctx->filename); @@ -3586,8 +3596,7 @@ if (edl_output_filename) { mp_property_do("sub_forced_only", M_PROPERTY_SET, &forced_subs_only, mpctx); // setup global sub numbering - mpctx->global_sub_indices[SUB_SOURCE_VOBSUB] = mpctx->global_sub_size; // the global # of the first vobsub. - mpctx->global_sub_size += vobsub_get_indexes_count(vo_vobsub); + mpctx->sub_counts[SUB_SOURCE_VOBSUB] = vobsub_get_indexes_count(vo_vobsub); } //============ Open & Sync STREAM --- fork cache2 ==================== @@ -3677,8 +3686,7 @@ if(mpctx->stream->type==STREAMTYPE_DVD){ if(opts->audio_id==-1) opts->audio_id=dvd_aid_from_lang(mpctx->stream,opts->audio_lang); if(opts->sub_lang && opts->sub_id==-1) opts->sub_id=dvd_sid_from_lang(mpctx->stream,opts->sub_lang); // setup global sub numbering - mpctx->global_sub_indices[SUB_SOURCE_DEMUX] = mpctx->global_sub_size; // the global # of the first demux-specific sub. - mpctx->global_sub_size += dvd_number_of_subs(mpctx->stream); + mpctx->sub_counts[SUB_SOURCE_DEMUX] = dvd_number_of_subs(mpctx->stream); current_module=NULL; } #endif @@ -3691,8 +3699,7 @@ if(mpctx->stream->type==STREAMTYPE_DVDNAV){ if(opts->sub_lang && opts->sub_id==-1) dvdsub_lang_id = opts->sub_id = mp_dvdnav_sid_from_lang(mpctx->stream,opts->sub_lang); // setup global sub numbering - mpctx->global_sub_indices[SUB_SOURCE_DEMUX] = mpctx->global_sub_size; // the global # of the first demux-specific sub. - mpctx->global_sub_size += mp_dvdnav_number_of_subs(mpctx->stream); + mpctx->sub_counts[SUB_SOURCE_DEMUX] = mp_dvdnav_number_of_subs(mpctx->stream); current_module=NULL; } #endif @@ -3790,20 +3797,6 @@ if(!mpctx->demuxer) mpctx->initialized_flags|=INITIALIZED_DEMUXER; -if (mpctx->stream->type != STREAMTYPE_DVD && mpctx->stream->type != STREAMTYPE_DVDNAV) { - int i; - int maxid = -1; - // setup global sub numbering - mpctx->global_sub_indices[SUB_SOURCE_DEMUX] = mpctx->global_sub_size; // the global # of the first demux-specific sub. - for (i = 0; i < MAX_S_STREAMS; i++) - if (mpctx->demuxer->s_streams[i]) - maxid = FFMAX(maxid, mpctx->demuxer->s_streams[i]->sid); - mpctx->global_sub_size += maxid + 1; -} -// Make opts->sub_id always selectable if set. -if (mpctx->global_sub_size <= mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + opts->sub_id) - mpctx->global_sub_size = mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + opts->sub_id + 1; - #ifdef CONFIG_ASS if (opts->ass_enabled && ass_library) { for (int j = 0; j < mpctx->num_sources; j++) { @@ -3959,15 +3952,10 @@ if(vo_spudec==NULL && } free(tmp); } - if (mpctx->set_of_sub_size > 0) { - // setup global sub numbering - mpctx->global_sub_indices[SUB_SOURCE_SUBS] = mpctx->global_sub_size; // the global # of the first sub. - mpctx->global_sub_size += mpctx->set_of_sub_size; - } - + if (mpctx->set_of_sub_size > 0) + mpctx->sub_counts[SUB_SOURCE_SUBS] = mpctx->set_of_sub_size; -if (mpctx->global_sub_size) { - select_subtitle(mpctx); +if (select_subtitle(mpctx)) { if(subdata) switch (stream_dump_type) { case 3: list_sub_file(subdata); break; -- 2.11.4.GIT