subs: always use sub decoder framework for libass rendering

Remove subtitle selection code setting osd->ass_track directly and
vf_ass/vf_vo code rendering the track directly with libass. Instead,
do track selection and rendering with dec_sub.c functions.

Before, mpctx->set_of_ass_tracks[] contained bare libass tracks
generated from external subtitle files. For use with dec_sub.c, it now
contains struct sh_sub instances with decoder already initialized.

This commit breaks the sub_step command ('g' and 'y' keys) for
libass-rendered subtitles. It could be fixed, but it's so useless -
especially as with the existing implementation there's no practical
way to get subtitle delay back to normal after using it - that I
didn't bother.

Conflicts:
	command.c
	mp_core.h
	mplayer.c
This commit is contained in:
Uoti Urpala 2012-08-25 21:22:39 +03:00 committed by wm4
parent 9bb03b7db4
commit 89a5714893
16 changed files with 164 additions and 105 deletions

View File

@ -1487,6 +1487,8 @@ static int mp_property_sub_alignment(m_option_t *prop, int action,
static int mp_property_sub_visibility(m_option_t *prop, int action,
void *arg, MPContext *mpctx)
{
struct MPOpts *opts = &mpctx->opts;
if (!mpctx->sh_video)
return M_PROPERTY_UNAVAILABLE;
@ -1500,7 +1502,7 @@ static int mp_property_sub_visibility(m_option_t *prop, int action,
if (vo_spudec)
vo_osd_changed(OSDTYPE_SPU);
default:
return m_property_flag(prop, action, arg, &sub_visibility);
return m_property_flag(prop, action, arg, &opts->sub_visibility);
}
}
@ -1579,34 +1581,28 @@ static int mp_property_sub_scale(m_option_t *prop, int action, void *arg,
if (!arg)
return M_PROPERTY_ERROR;
M_PROPERTY_CLAMP(prop, *(float *) arg);
#ifdef CONFIG_ASS
if (opts->ass_enabled)
opts->ass_font_scale = *(float *) arg;
#endif
text_font_scale_factor = *(float *) arg;
vo_osd_resized();
return M_PROPERTY_OK;
case M_PROPERTY_STEP_UP:
case M_PROPERTY_STEP_DOWN:
#ifdef CONFIG_ASS
if (opts->ass_enabled) {
opts->ass_font_scale += (arg ? *(float *) arg : 0.1) *
(action == M_PROPERTY_STEP_UP ? 1.0 : -1.0);
M_PROPERTY_CLAMP(prop, opts->ass_font_scale);
}
#endif
text_font_scale_factor += (arg ? *(float *) arg : 0.1) *
(action == M_PROPERTY_STEP_UP ? 1.0 : -1.0);
M_PROPERTY_CLAMP(prop, text_font_scale_factor);
vo_osd_resized();
return M_PROPERTY_OK;
default:
#ifdef CONFIG_ASS
if (opts->ass_enabled)
return m_property_float_ro(prop, action, arg, opts->ass_font_scale);
else
#endif
return m_property_float_ro(prop, action, arg, text_font_scale_factor);
return m_property_float_ro(prop, action, arg, text_font_scale_factor);
}
}
@ -2371,7 +2367,8 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
struct track *track = mpctx->current_track[STREAM_SUB];
if (track && track->subdata)
step_sub(track->subdata, mpctx->video_pts, movement);
#ifdef CONFIG_ASS
#if 0
// currently not implemented with libass
if (mpctx->osd->ass_track)
sub_delay +=
ass_step_sub(mpctx->osd->ass_track,
@ -2677,7 +2674,7 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
case MP_CMD_GET_SUB_VISIBILITY:
if (sh_video) {
mp_msg(MSGT_GLOBAL, MSGL_INFO,
"ANS_SUB_VISIBILITY=%d\n", sub_visibility);
"ANS_SUB_VISIBILITY=%d\n", opts->sub_visibility);
}
break;

View File

@ -39,6 +39,7 @@ void set_default_mplayer_options(struct MPOpts *opts)
.audio_id = -1,
.video_id = -1,
.sub_id = -1,
.sub_visibility = 1,
.extension_parsing = 1,
.audio_output_channels = 2,
.audio_output_format = -1, // AF_FORMAT_UNKNOWN

View File

@ -352,19 +352,21 @@ static int render_frame(struct vf_instance *vf, mp_image_t *mpi,
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
{
struct osd_state *osd = vf->priv->osd;
struct vf_priv_s *priv = vf->priv;
struct MPOpts *opts = vf->opts;
struct osd_state *osd = priv->osd;
ASS_Image *images = 0;
ASS_Renderer *renderer = osd->ass_renderer;
bool vs = osd->vsfilter_aspect && vf->opts->ass_vsfilter_aspect_compat;
if (sub_visibility && osd->ass_track && (pts != MP_NOPTS_VALUE)) {
struct mp_eosd_res dim = { .w = vf->priv->outw, .h = vf->priv->outh,
.mt = vf->opts->ass_top_margin,
.mb = vf->opts->ass_bottom_margin };
mp_ass_configure(renderer, vf->opts, &dim, 0);
ass_set_aspect_ratio(renderer,
vs ? 1. : vf->priv->aspect_correction, 1);
images = ass_render_frame(renderer, osd->ass_track,
(pts - osd->sub_offset + sub_delay) * 1000 + .5, NULL);
if (pts != MP_NOPTS_VALUE) {
osd->dim = (struct mp_eosd_res){ .w = vf->priv->outw,
.h = vf->priv->outh,
.mt = opts->ass_top_margin,
.mb = opts->ass_bottom_margin };
osd->normal_scale = vf->priv->aspect_correction;
osd->vsfilter_scale = 1;
osd->sub_pts = pts - osd->sub_offset;
struct sub_bitmaps b;
sub_get_bitmaps(osd, &b);
images = b.imgs;
}
prepare_image(vf, mpi);

View File

@ -30,7 +30,6 @@
#include "libvo/video_out.h"
#include "sub/ass_mp.h"
#include "sub/sub.h"
struct vf_priv_s {
@ -122,40 +121,29 @@ static int control(struct vf_instance *vf, int request, void *data)
};
return vo_control(video_out, VOCTRL_GET_EQUALIZER, &param) == VO_TRUE;
}
#ifdef CONFIG_ASS
case VFCTRL_INIT_EOSD: {
vf->priv->prev_visibility = false;
return CONTROL_TRUE;
}
case VFCTRL_DRAW_EOSD: {
struct mp_eosd_res dim = { 0 };
struct osd_state *osd = data;
osd->dim = (struct mp_eosd_res){0};
if (!video_out->config_ok ||
vo_control(video_out, VOCTRL_GET_EOSD_RES, &dim) != true) {
vo_control(video_out, VOCTRL_GET_EOSD_RES, &osd->dim) != true) {
vf->priv->prev_visibility = false;
return CONTROL_FALSE;
}
struct osd_state *osd = data;
mp_eosd_images_t images = { NULL, 2 };
ASS_Renderer *renderer = osd->ass_renderer;
double scale = 1;
if (osd->vsfilter_aspect && vf->opts->ass_vsfilter_aspect_compat)
scale = vf->priv->scale_ratio;
if (sub_visibility && osd->ass_track && (osd->pts != MP_NOPTS_VALUE)) {
mp_ass_configure(renderer, vf->opts, &dim,
vf->default_caps & VFCAP_EOSD_UNSCALED);
ass_set_aspect_ratio(renderer, scale, 1);
images.imgs = ass_render_frame(renderer, osd->ass_track,
(osd->pts + sub_delay) * 1000 + .5,
&images.changed);
if (!vf->priv->prev_visibility)
images.changed = 2;
vf->priv->prev_visibility = true;
} else
vf->priv->prev_visibility = false;
osd->normal_scale = 1;
osd->vsfilter_scale = vf->priv->scale_ratio;
osd->unscaled = vf->default_caps & VFCAP_EOSD_UNSCALED;
struct sub_bitmaps images;
sub_get_bitmaps(osd, &images);
if (!vf->priv->prev_visibility)
images.changed = 2;
vf->priv->prev_visibility = true;
return vo_control(video_out, VOCTRL_DRAW_EOSD, &images) == VO_TRUE;
}
#endif
}
return CONTROL_UNKNOWN;
}

View File

@ -23,6 +23,7 @@
#include <stdbool.h>
#include "sub/ass_mp.h"
#include "sub/dec_sub.h"
// Pool of surfaces
struct eosd_surface {

View File

@ -107,8 +107,8 @@ struct track {
// fields. The data is stored in stream->sub this case.
// External text subtitle using libass subtitle renderer.
struct ass_track *ass_track;
bool native_ass_track;
// The sh_sub is a dummy and doesn't belong to a demuxer.
struct sh_sub *sh_sub;
// External text subtitle using non-libass subtitle renderer.
struct sub_data *subdata;

View File

@ -605,8 +605,13 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask)
if (mask & INITIALIZED_SUB) {
mpctx->initialized_flags &= ~INITIALIZED_SUB;
struct track *track = mpctx->current_track[STREAM_SUB];
// One of these was active; they can't be both active.
assert(!(mpctx->sh_sub && (track && track->sh_sub)));
if (mpctx->sh_sub)
sub_switchoff(mpctx->sh_sub, mpctx->osd);
if (track && track->sh_sub)
sub_switchoff(track->sh_sub, mpctx->osd);
cleanup_demux_stream(mpctx, STREAM_SUB);
reset_subtitles(mpctx);
}
@ -623,10 +628,7 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask)
for (int i = 0; i < mpctx->num_tracks; i++) {
struct track *track = mpctx->tracks[i];
sub_free(track->subdata);
#ifdef CONFIG_ASS
if (track->ass_track)
ass_free_track(track->ass_track);
#endif
talloc_free(track->sh_sub);
talloc_free(track);
}
mpctx->num_tracks = 0;
@ -1040,16 +1042,16 @@ void add_subtitles(struct MPContext *mpctx, char *filename, float fps,
{
struct MPOpts *opts = &mpctx->opts;
sub_data *subd = NULL;
struct ass_track *asst = NULL;
bool is_native_ass = false;
struct sh_sub *sh = NULL;
if (filename == NULL)
return;
#ifdef CONFIG_ASS
if (opts->ass_enabled) {
asst = mp_ass_read_stream(mpctx->ass_library, filename, sub_cp);
is_native_ass = asst;
#ifdef CONFIG_ASS
struct ass_track *asst = mp_ass_read_stream(mpctx->ass_library,
filename, sub_cp);
bool is_native_ass = asst;
if (!asst) {
subd = sub_read_file(filename, fps, &mpctx->opts);
if (subd) {
@ -1058,12 +1060,14 @@ void add_subtitles(struct MPContext *mpctx, char *filename, float fps,
subd = NULL;
}
}
} else
if (asst)
sh = sd_ass_create_from_track(asst, is_native_ass, opts);
#endif
subd = sub_read_file(filename, fps, &mpctx->opts);
} else
subd = sub_read_file(filename, fps, &mpctx->opts);
if (!asst && !subd) {
if (!sh && !subd) {
mp_tmsg(MSGT_CPLAYER, noerr ? MSGL_WARN : MSGL_ERR,
"Cannot load subtitles: %s\n", filename);
return;
@ -1072,11 +1076,11 @@ void add_subtitles(struct MPContext *mpctx, char *filename, float fps,
struct track *track = talloc_ptrtype(NULL, track);
*track = (struct track) {
.type = STREAM_SUB,
.title = talloc_strdup(track, filename),
.user_tid = find_new_tid(mpctx, STREAM_SUB),
.demuxer_id = -1,
.is_external = true,
.ass_track = asst,
.native_ass_track = is_native_ass,
.sh_sub = sh,
.subdata = subd,
};
MP_TARRAY_APPEND(mpctx, mpctx->tracks, mpctx->num_tracks, track);
@ -1743,10 +1747,6 @@ double playing_audio_pts(struct MPContext *mpctx)
static void reset_subtitles(struct MPContext *mpctx)
{
struct sh_sub *sh_sub = mpctx->sh_sub;
if (sh_sub)
sub_reset(sh_sub, mpctx->osd);
sub_clear_text(&mpctx->subs, MP_NOPTS_VALUE);
if (vo_sub)
set_osd_subtitle(mpctx, NULL);
@ -1941,7 +1941,6 @@ static void reinit_subs(struct MPContext *mpctx)
init_demux_stream(mpctx, STREAM_SUB);
mpctx->osd->ass_track = NULL;
vobsub_id = -1;
if (!track)
@ -1967,20 +1966,17 @@ static void reinit_subs(struct MPContext *mpctx)
if (track->vobsub_id_plus_one) {
vobsub_id = track->vobsub_id_plus_one - 1;
} else if (track->subdata || track->ass_track) {
} else if (track->subdata || track->sh_sub) {
#ifdef CONFIG_ASS
if (opts->ass_enabled && track->ass_track) {
mpctx->osd->ass_track = track->ass_track;
mpctx->osd->vsfilter_aspect = track->native_ass_track;
}
if (opts->ass_enabled && track->sh_sub)
sub_init(track->sh_sub, mpctx->osd);
#endif
vo_osd_changed(OSDTYPE_SUBTITLE);
} else if (track->stream) {
if (mpctx->sh_sub->type == 'v')
init_vo_spudec(mpctx);
else {
else
sub_init(mpctx->sh_sub, mpctx->osd);
}
}
}
@ -2365,11 +2361,9 @@ int reinit_video_chain(struct MPContext *mpctx)
sh_video->vfilter = append_filters(sh_video->vfilter, opts->vf_settings);
#ifdef CONFIG_ASS
if (opts->ass_enabled)
sh_video->vfilter->control(sh_video->vfilter, VFCTRL_INIT_EOSD,
mpctx->ass_library);
#endif
init_best_video_codec(sh_video, video_codec_list, video_fm_list);
@ -2616,7 +2610,10 @@ static int redraw_osd(struct MPContext *mpctx)
return -1;
if (vo_redraw_frame(mpctx->video_out) < 0)
return -1;
mpctx->osd->pts = mpctx->video_pts - mpctx->osd->sub_offset;
mpctx->osd->sub_pts = mpctx->video_pts;
if (mpctx->osd->sub_pts != MP_NOPTS_VALUE)
mpctx->osd->sub_pts += sub_delay - mpctx->osd->sub_offset;
if (!(sh_video->output_flags & VFCAP_EOSD_FILTER))
vf->control(vf, VFCTRL_DRAW_EOSD, mpctx->osd);
vf->control(vf, VFCTRL_DRAW_OSD, mpctx->osd);
@ -3215,7 +3212,9 @@ static void run_playloop(struct MPContext *mpctx)
update_subtitles(mpctx, sh_video->pts);
update_osd_msg(mpctx);
struct vf_instance *vf = sh_video->vfilter;
mpctx->osd->pts = mpctx->video_pts - mpctx->osd->sub_offset;
mpctx->osd->sub_pts = mpctx->video_pts;
if (mpctx->osd->sub_pts != MP_NOPTS_VALUE)
mpctx->osd->sub_pts += sub_delay - mpctx->osd->sub_offset;
vf->control(vf, VFCTRL_DRAW_EOSD, mpctx->osd);
vf->control(vf, VFCTRL_DRAW_OSD, mpctx->osd);
vo_osd_reset_changed();
@ -4048,7 +4047,6 @@ terminate_playback: // don't jump here after ao/vo/getch initialization!
vo_sub = NULL;
#ifdef CONFIG_ASS
mpctx->osd->ass_track = NULL;
if (mpctx->osd->ass_renderer)
ass_renderer_done(mpctx->osd->ass_renderer);
mpctx->osd->ass_renderer = NULL;

View File

@ -74,6 +74,7 @@ typedef struct MPOpts {
int sub_id;
char **audio_lang;
char **sub_lang;
int sub_visibility;
int hr_mp3_seek;
char *quvi_format;

View File

@ -61,10 +61,4 @@ typedef struct ass_image {
#endif
typedef struct {
ASS_Image *imgs;
int changed;
} mp_eosd_images_t;
#endif /* MPLAYER_ASS_MP_H */

View File

@ -22,8 +22,9 @@
#include "config.h"
#include "libmpdemux/stheader.h"
#include "sd.h"
#include "dec_sub.h"
#include "sub/sd.h"
#include "sub/sub.h"
#include "sub/dec_sub.h"
#include "options.h"
extern const struct sd_functions sd_ass;
@ -33,6 +34,7 @@ void sub_init(struct sh_sub *sh, struct osd_state *osd)
{
struct MPOpts *opts = sh->opts;
assert(!osd->sh_sub);
#ifdef CONFIG_ASS
if (opts->ass_enabled && is_text_sub(sh->type))
sh->sd_driver = &sd_ass;
@ -42,6 +44,8 @@ void sub_init(struct sh_sub *sh, struct osd_state *osd)
if (sh->sd_driver) {
if (sh->sd_driver->init(sh, osd) < 0)
return;
osd->sh_sub = sh;
osd->changed_outside_sd = true;
sh->initialized = true;
sh->active = true;
}
@ -54,6 +58,22 @@ void sub_decode(struct sh_sub *sh, struct osd_state *osd, void *data,
sh->sd_driver->decode(sh, osd, data, data_len, pts, duration);
}
void sub_get_bitmaps(struct osd_state *osd, struct sub_bitmaps *res)
{
struct MPOpts *opts = osd->opts;
*res = (struct sub_bitmaps){.imgs = NULL, .changed = 2};
if (!opts->sub_visibility || !osd->sh_sub || !osd->sh_sub->active) {
osd->changed_outside_sd = true;
return;
}
if (osd->sh_sub->sd_driver->get_bitmaps)
osd->sh_sub->sd_driver->get_bitmaps(osd->sh_sub, osd, res);
if (osd->changed_outside_sd)
res->changed = 2;
osd->changed_outside_sd = false;
}
void sub_reset(struct sh_sub *sh, struct osd_state *osd)
{
if (sh->active && sh->sd_driver->reset)
@ -62,8 +82,11 @@ void sub_reset(struct sh_sub *sh, struct osd_state *osd)
void sub_switchoff(struct sh_sub *sh, struct osd_state *osd)
{
if (sh->active && sh->sd_driver->switch_off)
if (sh->active && sh->sd_driver->switch_off) {
assert(osd->sh_sub == sh);
sh->sd_driver->switch_off(sh, osd);
osd->sh_sub = NULL;
}
sh->active = false;
}

View File

@ -3,12 +3,18 @@
struct sh_sub;
struct osd_state;
struct ass_track;
typedef struct mp_eosd_res {
int w, h; // screen dimensions, including black borders
int mt, mb, ml, mr; // borders (top, bottom, left, right)
} mp_eosd_res_t;
typedef struct sub_bitmaps {
struct ass_image *imgs;
int changed;
} mp_eosd_images_t;
static inline bool is_text_sub(int type)
{
return type == 't' || type == 'm' || type == 'a';
@ -16,9 +22,14 @@ static inline bool is_text_sub(int type)
void sub_decode(struct sh_sub *sh, struct osd_state *osd, void *data,
int data_len, double pts, double duration);
void sub_get_bitmaps(struct osd_state *osd, struct sub_bitmaps *res);
void sub_init(struct sh_sub *sh, struct osd_state *osd);
void sub_reset(struct sh_sub *sh, struct osd_state *osd);
void sub_switchoff(struct sh_sub *sh, struct osd_state *osd);
void sub_uninit(struct sh_sub *sh);
struct sh_sub *sd_ass_create_from_track(struct ass_track *track,
bool vsfilter_aspect,
struct MPOpts *opts);
#endif

View File

@ -331,9 +331,11 @@ void vo_update_text_progbar(struct osd_state *osd, mp_osd_obj_t* obj)
void vo_update_text_sub(struct osd_state *osd, mp_osd_obj_t* obj)
{
struct MPOpts *opts = osd->opts;
obj->flags |= OSDFLAG_CHANGED | OSDFLAG_VISIBLE;
if (!vo_sub || !sub_visibility) {
if (!vo_sub || !opts->sub_visibility) {
obj->flags &= ~OSDFLAG_VISIBLE;
return;
}

View File

@ -3,11 +3,14 @@
struct osd_state;
struct sh_sub;
struct sub_bitmaps;
struct sd_functions {
int (*init)(struct sh_sub *sh, struct osd_state *osd);
void (*decode)(struct sh_sub *sh, struct osd_state *osd,
void *data, int data_len, double pts, double duration);
void (*get_bitmaps)(struct sh_sub *sh, struct osd_state *osd,
struct sub_bitmaps *res);
void (*reset)(struct sh_sub *sh, struct osd_state *osd);
void (*switch_off)(struct sh_sub *sh, struct osd_state *osd);
void (*uninit)(struct sh_sub *sh);

View File

@ -23,6 +23,7 @@
#include "talloc.h"
#include "options.h"
#include "mpcommon.h"
#include "mp_msg.h"
#include "libmpdemux/stheader.h"
@ -33,6 +34,7 @@
struct sd_ass_priv {
struct ass_track *ass_track;
bool vsfilter_aspect;
bool incomplete_event;
};
@ -61,9 +63,7 @@ static int init(struct sh_sub *sh, struct osd_state *osd)
ctx->ass_track = mp_ass_default_track(osd->ass_library, sh->opts);
}
assert(osd->ass_track == NULL);
osd->ass_track = ctx->ass_track;
osd->vsfilter_aspect = sh->type == 'a';
ctx->vsfilter_aspect = sh->type == 'a';
return 0;
}
@ -125,6 +125,25 @@ static void decode(struct sh_sub *sh, struct osd_state *osd, void *data,
event->Text = strdup(buf);
}
static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd,
struct sub_bitmaps *res)
{
struct sd_ass_priv *ctx = sh->context;
struct MPOpts *opts = osd->opts;
if (osd->sub_pts == MP_NOPTS_VALUE)
return;
double scale = osd->normal_scale;
if (ctx->vsfilter_aspect && opts->ass_vsfilter_aspect_compat)
scale = osd->vsfilter_scale;
ASS_Renderer *renderer = osd->ass_renderer;
mp_ass_configure(renderer, opts, &osd->dim, osd->unscaled);
ass_set_aspect_ratio(renderer, scale, 1);
res->imgs = ass_render_frame(renderer, ctx->ass_track,
osd->sub_pts * 1000 + .5, &res->changed);
}
static void reset(struct sh_sub *sh, struct osd_state *osd)
{
struct sd_ass_priv *ctx = sh->context;
@ -133,12 +152,6 @@ static void reset(struct sh_sub *sh, struct osd_state *osd)
ctx->incomplete_event = false;
}
static void switch_off(struct sh_sub *sh, struct osd_state *osd)
{
reset(sh, osd);
osd->ass_track = NULL;
}
static void uninit(struct sh_sub *sh)
{
struct sd_ass_priv *ctx = sh->context;
@ -150,7 +163,27 @@ static void uninit(struct sh_sub *sh)
const struct sd_functions sd_ass = {
.init = init,
.decode = decode,
.get_bitmaps = get_bitmaps,
.reset = reset,
.switch_off = switch_off,
.switch_off = reset,
.uninit = uninit,
};
struct sh_sub *sd_ass_create_from_track(struct ass_track *track,
bool vsfilter_aspect,
struct MPOpts *opts)
{
struct sh_sub *sh = talloc(NULL, struct sh_sub);
*sh = (struct sh_sub) {
.opts = opts,
.type = 'a',
.sd_driver = &sd_ass,
.context = talloc_struct(sh, struct sd_ass_priv, {
.ass_track = track,
.vsfilter_aspect = vsfilter_aspect,
}),
.initialized = true,
};
return sh;
}

View File

@ -30,6 +30,7 @@
#include "osdep/timer.h"
#include "talloc.h"
#include "options.h"
#include "mplayer.h"
#include "mp_msg.h"
#include "libvo/video_out.h"
@ -170,6 +171,7 @@ static int osd_update_ext(struct osd_state *osd, int dxs, int dys,
int left_border, int top_border, int right_border,
int bottom_border, int orig_w, int orig_h)
{
struct MPOpts *opts = osd->opts;
mp_osd_obj_t* obj=vo_osd_list;
int chg=0;
@ -190,7 +192,7 @@ static int osd_update_ext(struct osd_state *osd, int dxs, int dys,
vo_update_text_progbar(osd, obj);
break;
case OSDTYPE_SPU:
if(sub_visibility && vo_spudec && spudec_visible(vo_spudec)){
if (opts->sub_visibility && vo_spudec && spudec_visible(vo_spudec)){
vo_update_spudec_sub(osd, obj);
obj->flags|=OSDFLAG_VISIBLE|OSDFLAG_CHANGED;
}

View File

@ -62,15 +62,19 @@ typedef struct mp_osd_obj_s {
struct osd_state {
struct ass_library *ass_library;
struct ass_renderer *ass_renderer;
int w, h;
char *osd_text;
struct ass_track *ass_track;
double pts;
struct sh_sub *sh_sub;
bool changed_outside_sd;
double sub_pts;
double sub_offset;
bool vsfilter_aspect;
struct mp_eosd_res dim;
double normal_scale;
double vsfilter_scale;
bool unscaled;
struct ass_renderer *osd_render;
struct ass_library *osd_ass_library;
char *osd_text;
int w, h;
struct MPOpts *opts;
};
@ -113,7 +117,6 @@ extern char *sub_cp;
extern int sub_pos;
extern int sub_width_p;
extern int sub_alignment;
extern int sub_visibility;
extern int sub_bg_color; /* subtitles background color */
extern int sub_bg_alpha;
extern int spu_alignment;