# HG changeset patch # User reimar # Date 1278794930 0 # Node ID 7fc1f051a19f9d9d499f37ce30948f9663c014d1 # Parent d8408f8f996b3ee7286e838a732bf2522f320db9 Change global subtitle numbering scheme so that demuxers can "asynchronously" add subtitles during playback. diff -r d8408f8f996b -r 7fc1f051a19f command.c --- a/command.c Sat Jul 10 18:53:08 2010 +0000 +++ b/command.c Sat Jul 10 20:48:50 2010 +0000 @@ -98,19 +98,62 @@ vo_dheight, vo_fs); } -static int sub_source_by_pos(MPContext *mpctx, int pos) +static void update_global_sub_size(MPContext *mpctx) { - int source = -1; - int top = -1; + 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 = i + 1; + if (cnt > mpctx->sub_counts[SUB_SOURCE_DEMUX]) + mpctx->sub_counts[SUB_SOURCE_DEMUX] = cnt; + + // TODO: possibly adjust global_sub_pos + + // update global size + mpctx->global_sub_size = 0; + for (i = 0; i < SUB_SOURCES; i++) + mpctx->global_sub_size = mpctx->sub_counts[i]; +} + +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 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) @@ -1323,11 +1366,14 @@ MPContext *mpctx) { demux_stream_t *const d_sub = mpctx->d_sub; - const int global_sub_size = mpctx->global_sub_size; + int global_sub_size; int source = -1, reset_spu = 0; + int source_pos = -1; double pts = 0; char *sub_name; + update_global_sub_size(mpctx); + global_sub_size = mpctx->global_sub_size; if (global_sub_size <= 0) return M_PROPERTY_UNAVAILABLE; @@ -1433,15 +1479,17 @@ 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; @@ -1459,10 +1507,9 @@ #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 = 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 (ass_enabled && mpctx->set_of_ass_tracks[mpctx->set_of_sub_pos]) ass_track = mpctx->set_of_ass_tracks[mpctx->set_of_sub_pos]; @@ -1473,8 +1520,7 @@ vo_osd_changed(OSDTYPE_SUBTITLE); } } else if (source == SUB_SOURCE_DEMUX) { - dvdsub_id = - mpctx->global_sub_pos - mpctx->global_sub_indices[SUB_SOURCE_DEMUX]; + dvdsub_id = source_pos; if (d_sub && dvdsub_id < MAX_S_STREAMS) { int i = 0; // default: assume 1:1 mapping of sid and stream id @@ -1526,6 +1572,7 @@ MPContext *mpctx) { int source; + update_global_sub_size(mpctx); if (!mpctx->sh_video || mpctx->global_sub_size <= 0) return M_PROPERTY_UNAVAILABLE; @@ -1562,9 +1609,10 @@ 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: @@ -1581,7 +1629,7 @@ 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) @@ -1589,7 +1637,7 @@ 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: @@ -1604,6 +1652,7 @@ MPContext *mpctx) { int source, is_cur_source, offset; + update_global_sub_size(mpctx); if (!mpctx->sh_video || mpctx->global_sub_size <= 0) return M_PROPERTY_UNAVAILABLE; @@ -1616,8 +1665,8 @@ 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; @@ -1626,7 +1675,7 @@ 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); } @@ -1650,8 +1699,7 @@ 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) { + if (index < 0 || index > mpctx->sub_counts[source]) { mpctx->global_sub_pos = -1; *(int *) arg = -1; } @@ -2385,7 +2433,7 @@ 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)); @@ -2980,9 +3028,7 @@ int n = mpctx->set_of_sub_size; add_subtitles(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 -r d8408f8f996b -r 7fc1f051a19f mp_core.h --- a/mp_core.h Sat Jul 10 18:53:08 2010 +0000 +++ b/mp_core.h Sat Jul 10 20:48:50 2010 +0000 @@ -110,7 +110,7 @@ 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]; #ifdef CONFIG_ASS // set_of_ass_tracks[i] contains subtitles from set_of_subtitles[i] // parsed by libass or NULL if format unsupported diff -r d8408f8f996b -r 7fc1f051a19f mplayer.c --- a/mplayer.c Sat Jul 10 18:53:08 2010 +0000 +++ b/mplayer.c Sat Jul 10 20:48:50 2010 +0000 @@ -1875,32 +1875,42 @@ return time_frame; } -static void select_subtitle(MPContext *mpctx) +static int select_subtitle(MPContext *mpctx) { // 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 (dvdsub_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 && dvdsub_id >= 0) { // if user asks for a dvd sub id, use that next. - mpctx->global_sub_pos = mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + dvdsub_id; - } else if (mpctx->global_sub_indices[SUB_SOURCE_SUBS] >= 0) { + id = dvdsub_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 (dvdsub_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 && dvdsub_id == -1) { // finally select subs by language and container hints if (dvdsub_id == -1 && dvdsub_lang) dvdsub_id = demuxer_sub_track_by_lang(mpctx->demuxer, dvdsub_lang); if (dvdsub_id == -1) dvdsub_id = demuxer_default_sub_track(mpctx->demuxer); - if (dvdsub_id >= 0) - mpctx->global_sub_pos = mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + dvdsub_id; + if (dvdsub_id >= 0) { + id = dvdsub_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 @@ -1959,7 +1969,7 @@ } audio_delay = 0.0f; - mpctx->global_sub_size = mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + mp_dvdnav_number_of_subs(mpctx->stream); + mpctx->sub_counts[SUB_SOURCE_DEMUX] = mp_dvdnav_number_of_subs(mpctx->stream); if (dvdsub_lang && dvdsub_id == dvdsub_lang_id) { dvdsub_lang_id = mp_dvdnav_sid_from_lang(ctx->stream, dvdsub_lang); if (dvdsub_lang_id != dvdsub_id) { @@ -3050,7 +3060,7 @@ // 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 (filename) { load_per_protocol_config (mconfig, filename); @@ -3237,8 +3247,7 @@ 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 ==================== @@ -3325,8 +3334,7 @@ if(audio_id==-1) audio_id=dvd_aid_from_lang(mpctx->stream,audio_lang); if(dvdsub_lang && dvdsub_id==-1) dvdsub_id=dvd_sid_from_lang(mpctx->stream,dvdsub_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 @@ -3339,8 +3347,7 @@ if(dvdsub_lang && dvdsub_id==-1) dvdsub_lang_id=dvdsub_id=mp_dvdnav_sid_from_lang(mpctx->stream,dvdsub_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 @@ -3433,20 +3440,6 @@ 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, ((sh_sub_t *)mpctx->demuxer->s_streams[i])->sid); - mpctx->global_sub_size += maxid + 1; -} -// Make dvdsub_id always selectable if set. -if (mpctx->global_sub_size <= mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + dvdsub_id) - mpctx->global_sub_size = mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + dvdsub_id + 1; - #ifdef CONFIG_ASS if (ass_enabled && ass_library) { for (i = 0; i < mpctx->demuxer->num_attachments; ++i) { @@ -3596,15 +3589,11 @@ } 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;