mirror of https://github.com/mpv-player/mpv
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:
parent
9bb03b7db4
commit
89a5714893
15
command.c
15
command.c
|
@ -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,33 +1581,27 @@ 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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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, ¶m) == 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);
|
||||
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;
|
||||
} else
|
||||
vf->priv->prev_visibility = false;
|
||||
return vo_control(video_out, VOCTRL_DRAW_EOSD, &images) == VO_TRUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return CONTROL_UNKNOWN;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#include "sub/ass_mp.h"
|
||||
#include "sub/dec_sub.h"
|
||||
|
||||
// Pool of surfaces
|
||||
struct eosd_surface {
|
||||
|
|
|
@ -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;
|
||||
|
|
58
mplayer.c
58
mplayer.c
|
@ -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
|
||||
} 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,22 +1966,19 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mp_switch_track(struct MPContext *mpctx, enum stream_type type,
|
||||
struct track *track)
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
3
sub/sd.h
3
sub/sd.h
|
@ -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);
|
||||
|
|
53
sub/sd_ass.c
53
sub/sd_ass.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
15
sub/sub.h
15
sub/sub.h
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue