0
0
mirror of https://github.com/mpv-player/mpv.git synced 2024-09-20 12:02:23 +02:00

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
This commit is contained in:
reimar 2010-07-10 20:48:50 +00:00 committed by Uoti Urpala
parent 0eb5662a05
commit 1663d97a11
3 changed files with 138 additions and 93 deletions

153
command.c
View File

@ -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 source = -1;
int top = -1;
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)
@ -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;
}
}

View File

@ -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];

View File

@ -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;