sub: align ytdl-hook secondary subs to the top

29e15e6248 prefixed youtube-dl's subs url with an edl prefix to not
download them until they're selected, which is useful when there are
many sub languages. But this prefix broke the alignment of secondary
subs, which would overlap the primary subs instead of always being
placed at the top. This can be tested with
--sub-file='edl://!no_clip;!delay_open,media_type=sub;secondary_sub.srt'

When a sub is added, sub.c:reinit_sub() is called. This calls in
init_subdec() -> dec_sub.c:sub_create() -> init_decoder() ->
sd_ass:init(). Then reinit_sub() calls
sub_control(track->d_sub, SD_CTRL_SET_TOP, &(bool){!!order}) which sets
sd_ass_priv.on_top = true for secondary subs.

But for EDL subs the real sub is initialized again when in
dec_sub.c:sub_read_packets() is_new_segment() returns true and
update_segment() is called, or when sub_get_bitmaps() calls
update_segment(). update_segment() then calls init_decoder(), which
calls sd_ass:init(), so sd_ass_priv is reinitialized, and its on_top
property is left false. This commit sets it to true again.

For URLs that need to be downloaded it seems that the update_segment()
call that reinitializes sd_ass_priv is always the one in
sub_read_packets(), but with local subs sub_get_bitmaps() is usually
called earlier (though there shouldn't be a reason to use the EDL URL
for local subs), so I added the order parameter to sub_create(), rather
than adding it to all of update_segment(), sub_read_packets() and
sub_get_bitmaps().

Also removes the cast to bool in the other sub_control call, since
sub/sd_ass.c:control already casts arg to bool when cmd is
SD_CTRL_SET_TOP.
This commit is contained in:
Guido Cella 2021-08-10 22:11:53 +02:00 committed by Dudemanguy
parent f25d446b03
commit b6ebd1a15e
3 changed files with 8 additions and 4 deletions

View File

@ -171,7 +171,8 @@ static bool init_subdec(struct MPContext *mpctx, struct track *track)
return false;
track->d_sub = sub_create(mpctx->global, track->stream,
get_all_attachments(mpctx));
get_all_attachments(mpctx),
get_order(mpctx, track));
if (!track->d_sub)
return false;
@ -199,7 +200,7 @@ void reinit_sub(struct MPContext *mpctx, struct track *track)
sub_select(track->d_sub, true);
int order = get_order(mpctx, track);
osd_set_sub(mpctx->osd, order, track->d_sub);
sub_control(track->d_sub, SD_CTRL_SET_TOP, &(bool){!!order});
sub_control(track->d_sub, SD_CTRL_SET_TOP, &order);
if (mpctx->playback_initialized)
update_subtitles(mpctx, mpctx->playback_pts);

View File

@ -57,6 +57,7 @@ struct dec_sub {
struct sh_stream *sh;
int play_dir;
int order;
double last_pkt_pts;
bool preload_attempted;
double video_fps;
@ -161,7 +162,7 @@ static struct sd *init_decoder(struct dec_sub *sub)
// Ownership of attachments goes to the callee, and is released with
// talloc_free() (even on failure).
struct dec_sub *sub_create(struct mpv_global *global, struct sh_stream *sh,
struct attachment_list *attachments)
struct attachment_list *attachments, int order)
{
assert(sh && sh->type == STREAM_SUB);
@ -174,6 +175,7 @@ struct dec_sub *sub_create(struct mpv_global *global, struct sh_stream *sh,
.codec = sh->codec,
.attachments = talloc_steal(sub, attachments),
.play_dir = 1,
.order = order,
.last_pkt_pts = MP_NOPTS_VALUE,
.last_vo_pts = MP_NOPTS_VALUE,
.start = MP_NOPTS_VALUE,
@ -210,6 +212,7 @@ static void update_segment(struct dec_sub *sub)
talloc_free(sub->sd);
sub->sd = new;
update_subtitle_speed(sub);
sub_control(sub, SD_CTRL_SET_TOP, &sub->order);
} else {
// We'll just keep the current decoder, and feed it possibly
// invalid data (not our fault if it crashes or something).

View File

@ -37,7 +37,7 @@ struct attachment_list {
};
struct dec_sub *sub_create(struct mpv_global *global, struct sh_stream *sh,
struct attachment_list *attachments);
struct attachment_list *attachments, int order);
void sub_destroy(struct dec_sub *sub);
bool sub_can_preload(struct dec_sub *sub);