From 02ce316ade9ba932ad405383278d6b01c54e5fc4 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 1 Jun 2013 19:44:12 +0200 Subject: sub: refactor Make the sub decoder stuff independent from sh_sub (except for initialization of course). Sub decoders now access a struct sd only, instead of getting access to sh_sub. The glue code in dec_sub.c is similarily independent from osd. Some simplifications are made. For example, the switch_id stuff is unneeded: the frontend code just has to make sure to call osd_changed() any time subtitles are switched. This is also preparation for introducing subtitle converters. It's much cleaner to completely separate demuxer header/renderer glue/decoders for this purpose, especially since sub converters might completely change how demuxer headers have to be interpreted. Also pass data as demux_packets. Currently, this doesn't help much, but libavcodec converters might need scary stuff like packet side data, so it's perhaps better to go with passing packets. --- core/command.c | 4 +- core/mplayer.c | 80 ++++++++++++++++----------- demux/stheader.h | 3 +- sub/dec_sub.c | 163 ++++++++++++++++++++++++++++++++++--------------------- sub/dec_sub.h | 36 ++++++++---- sub/sd.h | 40 +++++++++++--- sub/sd_ass.c | 80 +++++++++++++-------------- sub/sd_lavc.c | 37 ++++++------- sub/sd_spu.c | 36 ++++++------ sub/sub.c | 4 +- sub/sub.h | 9 +-- 11 files changed, 287 insertions(+), 205 deletions(-) diff --git a/core/command.c b/core/command.c index 7971180553..416fbcd06a 100644 --- a/core/command.c +++ b/core/command.c @@ -1951,9 +1951,9 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) case MP_CMD_SUB_STEP: #ifdef CONFIG_ASS - if (sh_video) { + if (mpctx->osd->dec_sub) { int movement = cmd->args[0].v.i; - struct ass_track *ass_track = sub_get_ass_track(mpctx->osd); + struct ass_track *ass_track = sub_get_ass_track(mpctx->osd->dec_sub); if (ass_track) { set_osd_tmsg(mpctx, OSD_MSG_SUB_DELAY, osdl, osd_duration, "Sub delay: %d ms", ROUND(opts->sub_delay * 1000)); diff --git a/core/mplayer.c b/core/mplayer.c index a19788df0b..92c0f717af 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -457,8 +457,10 @@ static void uninit_subs(struct demuxer *demuxer) { for (int i = 0; i < MAX_S_STREAMS; i++) { struct sh_sub *sh = demuxer->s_streams[i]; - if (sh && sh->initialized) - sub_uninit(sh); + if (sh) { + sub_destroy(sh->dec_sub); + sh->dec_sub = NULL; + } } } @@ -481,8 +483,9 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask) if (mask & INITIALIZED_SUB) { mpctx->initialized_flags &= ~INITIALIZED_SUB; if (mpctx->sh_sub) - sub_switchoff(mpctx->sh_sub, mpctx->osd); + sub_reset(mpctx->sh_sub->dec_sub); cleanup_demux_stream(mpctx, STREAM_SUB); + mpctx->osd->dec_sub = NULL; reset_subtitles(mpctx); } @@ -1077,7 +1080,7 @@ struct track *mp_add_subtitles(struct MPContext *mpctx, char *filename, s->sub->track = asst; s->codec = codec; - struct ass_track **pptr = talloc(s, struct ass_track*); + struct ass_track **pptr = talloc(d, struct ass_track*); *pptr = asst; talloc_set_destructor(pptr, free_ass_track); @@ -1830,18 +1833,21 @@ static bool is_non_interleaved(struct MPContext *mpctx, struct track *track) static void reset_subtitles(struct MPContext *mpctx) { if (mpctx->sh_sub) - sub_reset(mpctx->sh_sub, mpctx->osd); + sub_reset(mpctx->sh_sub->dec_sub); set_osd_subtitle(mpctx, NULL); + osd_changed(mpctx->osd, OSDTYPE_SUB); } static void update_subtitles(struct MPContext *mpctx, double refpts_tl) { struct MPOpts *opts = &mpctx->opts; - struct sh_sub *sh_sub = mpctx->sh_sub; + if (!(mpctx->initialized_flags & INITIALIZED_SUB)) + return; struct track *track = mpctx->current_track[STREAM_SUB]; - if (!track) - return; + struct sh_sub *sh_sub = mpctx->sh_sub; + assert(track && sh_sub); + struct dec_sub *dec_sub = sh_sub->dec_sub; double video_offset = track->under_timeline ? mpctx->video_offset : 0; @@ -1850,7 +1856,7 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl) double curpts_s = refpts_tl - mpctx->osd->sub_offset; double refpts_s = refpts_tl - video_offset; - if (sh_sub && sh_sub->active && !track->preloaded) { + if (!track->preloaded) { struct demux_stream *d_sub = sh_sub->ds; const char *type = sh_sub->gsh->codec; bool non_interleaved = is_non_interleaved(mpctx, track); @@ -1880,7 +1886,7 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl) "Sub early: c_pts=%5.3f s_pts=%5.3f\n", curpts_s, subpts_s); // Libass handled subs can be fed to it in advance - if (!sub_accept_packets_in_advance(sh_sub)) + if (!sub_accept_packets_in_advance(dec_sub)) break; // Try to avoid demuxing whole file at once if (non_interleaved && subpts_s > curpts_s + 1) @@ -1898,12 +1904,18 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl) len = FFMIN(len - 2, AV_RB16(packet)); packet += 2; } - sub_decode(sh_sub, mpctx->osd, packet, len, subpts_s, duration); + struct demux_packet pkt = { + .buffer = packet, + .len = len, + .pts = subpts_s, + .duration = duration, + }; + sub_decode(dec_sub, &pkt); } } if (!mpctx->osd->render_bitmap_subs) - set_osd_subtitle(mpctx, sub_get_text(mpctx->osd, curpts_s)); + set_osd_subtitle(mpctx, sub_get_text(dec_sub, curpts_s)); } static int check_framedrop(struct MPContext *mpctx, double frame_time) @@ -1946,7 +1958,7 @@ static double timing_sleep(struct MPContext *mpctx, double time_frame) return time_frame; } -static void set_dvdsub_fake_extradata(struct sh_sub *sh_sub, struct stream *st, +static void set_dvdsub_fake_extradata(struct dec_sub *dec_sub, struct stream *st, int width, int height) { #ifdef CONFIG_DVDREAD @@ -1981,9 +1993,7 @@ static void set_dvdsub_fake_extradata(struct sh_sub *sh_sub, struct stream *st, } s = talloc_asprintf_append(s, "\n"); - free(sh_sub->extradata); - sh_sub->extradata = strdup(s); - sh_sub->extradata_len = strlen(s); + sub_set_extradata(dec_sub, s, strlen(s)); talloc_free(s); #endif } @@ -1992,15 +2002,16 @@ static void reinit_subs(struct MPContext *mpctx) { struct MPOpts *opts = &mpctx->opts; struct track *track = mpctx->current_track[STREAM_SUB]; - struct osd_state *osd = mpctx->osd; assert(!(mpctx->initialized_flags & INITIALIZED_SUB)); init_demux_stream(mpctx, STREAM_SUB); - - if (!track) + if (!mpctx->sh_sub) return; + if (!mpctx->sh_sub->dec_sub) + mpctx->sh_sub->dec_sub = sub_create(opts); + if (track->demuxer && !track->stream) { // Lazily added DVD track - we must not miss the first subtitle packet, // which makes the demuxer create the sh_stream, and contains the first @@ -2016,25 +2027,32 @@ static void reinit_subs(struct MPContext *mpctx) return; } + assert(track->demuxer && track->stream); mpctx->initialized_flags |= INITIALIZED_SUB; - osd->sub_video_w = mpctx->sh_video ? mpctx->sh_video->disp_w : 0; - osd->sub_video_h = mpctx->sh_video ? mpctx->sh_video->disp_h : 0; + struct sh_sub *sh_sub = mpctx->sh_sub; + struct dec_sub *dec_sub = sh_sub->dec_sub; + assert(dec_sub); + + if (!sub_is_initialized(dec_sub)) { + int w = mpctx->sh_video ? mpctx->sh_video->disp_w : 0; + int h = mpctx->sh_video ? mpctx->sh_video->disp_h : 0; - if (track->stream) { - if (track->demuxer && track->demuxer->stream) { - set_dvdsub_fake_extradata(mpctx->sh_sub, track->demuxer->stream, - osd->sub_video_w, osd->sub_video_h); - } - sub_init(mpctx->sh_sub, osd); + set_dvdsub_fake_extradata(dec_sub, track->demuxer->stream, w, h); + sub_set_video_res(dec_sub, w, h); + sub_set_ass_renderer(dec_sub, mpctx->osd->ass_library, + mpctx->osd->ass_renderer); + sub_init_from_sh(dec_sub, sh_sub); } + mpctx->osd->dec_sub = dec_sub; + // Decides whether to use OSD path or normal subtitle rendering path. - mpctx->osd->render_bitmap_subs = true; - struct sh_sub *sh_sub = mpctx->osd->sh_sub; - if (sh_sub && sh_sub->active && sh_sub->sd_driver->get_text) - mpctx->osd->render_bitmap_subs = opts->ass_enabled; + mpctx->osd->render_bitmap_subs = + opts->ass_enabled || !sub_has_get_text(dec_sub); + + reset_subtitles(mpctx); } static char *track_layout_hash(struct MPContext *mpctx) diff --git a/demux/stheader.h b/demux/stheader.h index 09e9d8682b..8220d65a61 100644 --- a/demux/stheader.h +++ b/demux/stheader.h @@ -161,11 +161,10 @@ typedef struct sh_video { typedef struct sh_sub { SH_COMMON - bool active; // after track switch decoder may stay initialized, not active unsigned char *extradata; // extra header data passed from demuxer int extradata_len; struct ass_track *track; // loaded by libass - const struct sd_functions *sd_driver; + struct dec_sub *dec_sub; // decoder context } sh_sub_t; // demuxer.c: diff --git a/sub/dec_sub.c b/sub/dec_sub.c index 2cc02efb79..67828921b4 100644 --- a/sub/dec_sub.c +++ b/sub/dec_sub.c @@ -40,95 +40,136 @@ static const struct sd_functions *sd_list[] = { NULL }; -void sub_init(struct sh_sub *sh, struct osd_state *osd) +struct dec_sub { + struct MPOpts *opts; + struct sd init_sd; + + struct sd *sd; +}; + +struct dec_sub *sub_create(struct MPOpts *opts) +{ + struct dec_sub *sub = talloc_zero(NULL, struct dec_sub); + sub->opts = opts; + return sub; +} + +void sub_destroy(struct dec_sub *sub) +{ + if (!sub) + return; + if (sub->sd && sub->sd->driver->uninit) + sub->sd->driver->uninit(sub->sd); + talloc_free(sub->sd); + talloc_free(sub); +} + +bool sub_is_initialized(struct dec_sub *sub) +{ + return !!sub->sd; +} + +struct sd *sub_get_sd(struct dec_sub *sub) +{ + return sub->sd; +} + +void sub_set_video_res(struct dec_sub *sub, int w, int h) +{ + sub->init_sd.sub_video_w = w; + sub->init_sd.sub_video_h = h; +} + +void sub_set_extradata(struct dec_sub *sub, void *data, int data_len) +{ + sub->init_sd.extradata = data_len ? talloc_memdup(sub, data, data_len) : NULL; + sub->init_sd.extradata_len = data_len; +} + +void sub_set_ass_renderer(struct dec_sub *sub, struct ass_library *ass_library, + struct ass_renderer *ass_renderer) +{ + sub->init_sd.ass_library = ass_library; + sub->init_sd.ass_renderer = ass_renderer; +} + +static int sub_init_decoder(struct dec_sub *sub, struct sd *sd) { - sh->sd_driver = NULL; + sd->driver = NULL; for (int n = 0; sd_list[n]; n++) { - if (sd_list[n]->supports_format(sh->gsh->codec)) { - sh->sd_driver = sd_list[n]; + if (sd_list[n]->supports_format(sd->codec)) { + sd->driver = sd_list[n]; break; } } - if (sh->sd_driver) { - if (sh->sd_driver->init(sh, osd) < 0) - return; - osd->sh_sub = sh; - osd->switch_sub_id++; - sh->initialized = true; - sh->active = true; + if (!sd->driver) + return -1; + + if (sd->driver->init(sd) < 0) + return -1; + + return 0; +} + +void sub_init_from_sh(struct dec_sub *sub, struct sh_sub *sh) +{ + assert(!sub->sd); + if (sh->extradata && !sub->init_sd.extradata) + sub_set_extradata(sub, sh->extradata, sh->extradata_len); + struct sd *sd = talloc(NULL, struct sd); + *sd = sub->init_sd; + sd->opts = sub->opts; + sd->codec = sh->gsh->codec; + sd->ass_track = sh->track; + if (sub_init_decoder(sub, sd) < 0) { + talloc_free(sd); + sd = NULL; } + sub->sd = sd; } -bool sub_accept_packets_in_advance(struct sh_sub *sh) +bool sub_accept_packets_in_advance(struct dec_sub *sub) { - return sh->active && sh->sd_driver->accept_packets_in_advance; + return sub->sd && sub->sd->driver->accept_packets_in_advance; } -void sub_decode(struct sh_sub *sh, struct osd_state *osd, void *data, - int data_len, double pts, double duration) +void sub_decode(struct dec_sub *sub, struct demux_packet *packet) { - if (sh->active && sh->sd_driver->decode) - sh->sd_driver->decode(sh, osd, data, data_len, pts, duration); + if (sub->sd) + sub->sd->driver->decode(sub->sd, packet); } -void sub_get_bitmaps(struct osd_state *osd, struct mp_osd_res dim, double pts, +void sub_get_bitmaps(struct dec_sub *sub, struct mp_osd_res dim, double pts, struct sub_bitmaps *res) { - struct MPOpts *opts = osd->opts; + struct MPOpts *opts = sub->opts; *res = (struct sub_bitmaps) {0}; - if (!opts->sub_visibility || !osd->sh_sub || !osd->sh_sub->active) { - /* Change ID in case we just switched from visible subtitles - * to current state. Hopefully, unnecessarily claiming that - * things may have changed is harmless for empty contents. - * Increase osd-> values ahead so that _next_ returned id - * is also guaranteed to differ from this one. - */ - osd->switch_sub_id++; - } else { - if (osd->sh_sub->sd_driver->get_bitmaps) - osd->sh_sub->sd_driver->get_bitmaps(osd->sh_sub, osd, dim, pts, res); + if (sub->sd && opts->sub_visibility) { + if (sub->sd->driver->get_bitmaps) + sub->sd->driver->get_bitmaps(sub->sd, dim, pts, res); } - - res->bitmap_id += osd->switch_sub_id; - res->bitmap_pos_id += osd->switch_sub_id; - osd->switch_sub_id = 0; } -char *sub_get_text(struct osd_state *osd, double pts) +bool sub_has_get_text(struct dec_sub *sub) { - struct MPOpts *opts = osd->opts; - char *text = NULL; - if (!opts->sub_visibility || !osd->sh_sub || !osd->sh_sub->active) { - // - - } else { - if (osd->sh_sub->sd_driver->get_text) - text = osd->sh_sub->sd_driver->get_text(osd->sh_sub, osd, pts); - } - return text; + return sub->sd && sub->sd->driver->get_text; } -void sub_reset(struct sh_sub *sh, struct osd_state *osd) +char *sub_get_text(struct dec_sub *sub, double pts) { - if (sh->active && sh->sd_driver->reset) - sh->sd_driver->reset(sh, osd); -} - -void sub_switchoff(struct sh_sub *sh, struct osd_state *osd) -{ - if (sh->active && sh->sd_driver->switch_off) { - assert(osd->sh_sub == sh); - sh->sd_driver->switch_off(sh, osd); - osd->sh_sub = NULL; + struct MPOpts *opts = sub->opts; + char *text = NULL; + if (sub->sd && opts->sub_visibility) { + if (sub->sd->driver->get_text) + text = sub->sd->driver->get_text(sub->sd, pts); } - sh->active = false; + return text; } -void sub_uninit(struct sh_sub *sh) +void sub_reset(struct dec_sub *sub) { - assert (!sh->active); - if (sh->initialized && sh->sd_driver->uninit) - sh->sd_driver->uninit(sh); - sh->initialized = false; + if (sub->sd && sub->sd->driver->reset) + sub->sd->driver->reset(sub->sd); } diff --git a/sub/dec_sub.h b/sub/dec_sub.h index 4eb833c52b..39632d21a9 100644 --- a/sub/dec_sub.h +++ b/sub/dec_sub.h @@ -9,20 +9,36 @@ struct sh_sub; struct ass_track; struct MPOpts; +struct demux_packet; +struct ass_library; +struct ass_renderer; -bool sub_accept_packets_in_advance(struct sh_sub *sh); -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 mp_osd_res dim, double pts, +struct dec_sub; +struct sd; + +struct dec_sub *sub_create(struct MPOpts *opts); +void sub_destroy(struct dec_sub *sub); + +void sub_set_video_res(struct dec_sub *sub, int w, int h); +void sub_set_extradata(struct dec_sub *sub, void *data, int data_len); +void sub_set_ass_renderer(struct dec_sub *sub, struct ass_library *ass_library, + struct ass_renderer *ass_renderer); +void sub_init_from_sh(struct dec_sub *sub, struct sh_sub *sh); + +bool sub_is_initialized(struct dec_sub *sub); + +bool sub_accept_packets_in_advance(struct dec_sub *sub); +void sub_decode(struct dec_sub *sub, struct demux_packet *packet); +void sub_get_bitmaps(struct dec_sub *sub, struct mp_osd_res dim, double pts, struct sub_bitmaps *res); -char *sub_get_text(struct osd_state *osd, double pts); -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); +bool sub_has_get_text(struct dec_sub *sub); +char *sub_get_text(struct dec_sub *sub, double pts); +void sub_reset(struct dec_sub *sub); + +struct sd *sub_get_sd(struct dec_sub *sub); #ifdef CONFIG_ASS -struct ass_track *sub_get_ass_track(struct osd_state *osd); +struct ass_track *sub_get_ass_track(struct dec_sub *sub); #endif #endif diff --git a/sub/sd.h b/sub/sd.h index 123a9bc45d..42f7b8a445 100644 --- a/sub/sd.h +++ b/sub/sd.h @@ -2,20 +2,42 @@ #define MPLAYER_SD_H #include "dec_sub.h" +#include "demux/demux_packet.h" + +struct sd { + struct MPOpts *opts; + + const struct sd_functions *driver; + void *priv; + + const char *codec; + + // Extra header data passed from demuxer + char *extradata; + int extradata_len; + + // Video resolution used for subtitle decoding. Doesn't necessarily match + // the resolution of the VO, nor does it have to be the OSD resolution. + int sub_video_w, sub_video_h; + + // Make sd_ass use an existing track + struct ass_track *ass_track; + + // Shared renderer for ASS - done to avoid reloading embedded fonts. + struct ass_library *ass_library; + struct ass_renderer *ass_renderer; +}; struct sd_functions { bool accept_packets_in_advance; bool (*supports_format)(const char *format); - 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 mp_osd_res dim, double pts, + int (*init)(struct sd *sd); + void (*decode)(struct sd *sd, struct demux_packet *packet); + void (*get_bitmaps)(struct sd *sd, struct mp_osd_res dim, double pts, struct sub_bitmaps *res); - char *(*get_text)(struct sh_sub *sh, struct osd_state *osd, double pts); - 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); + char *(*get_text)(struct sd *sd, double pts); + void (*reset)(struct sd *sd); + void (*uninit)(struct sd *sd); }; #endif diff --git a/sub/sd_ass.c b/sub/sd_ass.c index b107e0438f..2ebd2164be 100644 --- a/sub/sd_ass.c +++ b/sub/sd_ass.c @@ -69,39 +69,39 @@ static void free_last_event(ASS_Track *track) track->n_events--; } -static int init(struct sh_sub *sh, struct osd_state *osd) +static int init(struct sd *sd) { - struct sd_ass_priv *ctx; - bool ass = is_ass_sub(sh->gsh->codec); - - if (sh->initialized) { - ctx = sh->context; - } else { - ctx = talloc_zero(NULL, struct sd_ass_priv); - sh->context = ctx; - if (sh->track) { - ctx->ass_track = sh->track; - } else if (ass) { - ctx->ass_track = ass_new_track(osd->ass_library); - if (sh->extradata) - ass_process_codec_private(ctx->ass_track, sh->extradata, - sh->extradata_len); - } else - ctx->ass_track = mp_ass_default_track(osd->ass_library, sh->opts); - } + if (!sd->ass_library || !sd->ass_renderer) + return -1; + + bool ass = is_ass_sub(sd->codec); + struct sd_ass_priv *ctx = talloc_zero(NULL, struct sd_ass_priv); + sd->priv = ctx; + if (sd->ass_track) { + ctx->ass_track = sd->ass_track; + } else if (ass) { + ctx->ass_track = ass_new_track(sd->ass_library); + if (sd->extradata) + ass_process_codec_private(ctx->ass_track, sd->extradata, + sd->extradata_len); + } else + ctx->ass_track = mp_ass_default_track(sd->ass_library, sd->opts); ctx->vsfilter_aspect = ass; return 0; } -static void decode(struct sh_sub *sh, struct osd_state *osd, void *data, - int data_len, double pts, double duration) +static void decode(struct sd *sd, struct demux_packet *packet) { + void *data = packet->buffer; + int data_len = packet->len; + double pts = packet->pts; + double duration = packet->duration; unsigned char *text = data; - struct sd_ass_priv *ctx = sh->context; + struct sd_ass_priv *ctx = sd->priv; ASS_Track *track = ctx->ass_track; - if (is_ass_sub(sh->gsh->codec)) { + if (is_ass_sub(sd->codec)) { if (bstr_startswith0((bstr){data, data_len}, "Dialogue: ")) { // broken ffmpeg ASS packet format ctx->flush_on_seek = true; @@ -158,14 +158,13 @@ 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 mp_osd_res dim, double pts, +static void get_bitmaps(struct sd *sd, struct mp_osd_res dim, double pts, struct sub_bitmaps *res) { - struct sd_ass_priv *ctx = sh->context; - struct MPOpts *opts = osd->opts; + struct sd_ass_priv *ctx = sd->priv; + struct MPOpts *opts = sd->opts; - if (pts == MP_NOPTS_VALUE) + if (pts == MP_NOPTS_VALUE || !sd->ass_renderer) return; double scale = dim.display_par; @@ -173,7 +172,7 @@ static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd, ? opts->ass_vsfilter_aspect_compat : 1; if (ctx->vsfilter_aspect && use_vs_aspect) scale = scale * dim.video_par; - ASS_Renderer *renderer = osd->ass_renderer; + ASS_Renderer *renderer = sd->ass_renderer; mp_ass_configure(renderer, opts, &dim); ass_set_aspect_ratio(renderer, scale, 1); mp_ass_render_frame(renderer, ctx->ass_track, pts * 1000 + .5, @@ -234,9 +233,9 @@ static void ass_to_plaintext(struct buf *b, const char *in) } } -static char *get_text(struct sh_sub *sh, struct osd_state *osd, double pts) +static char *get_text(struct sd *sd, double pts) { - struct sd_ass_priv *ctx = sh->context; + struct sd_ass_priv *ctx = sd->priv; ASS_Track *track = ctx->ass_track; if (pts == MP_NOPTS_VALUE) @@ -264,9 +263,9 @@ static char *get_text(struct sh_sub *sh, struct osd_state *osd, double pts) return ctx->last_text; } -static void reset(struct sh_sub *sh, struct osd_state *osd) +static void reset(struct sd *sd) { - struct sd_ass_priv *ctx = sh->context; + struct sd_ass_priv *ctx = sd->priv; if (ctx->incomplete_event) free_last_event(ctx->ass_track); ctx->incomplete_event = false; @@ -275,11 +274,11 @@ static void reset(struct sh_sub *sh, struct osd_state *osd) ctx->flush_on_seek = false; } -static void uninit(struct sh_sub *sh) +static void uninit(struct sd *sd) { - struct sd_ass_priv *ctx = sh->context; + struct sd_ass_priv *ctx = sd->priv; - if (sh->track != ctx->ass_track) + if (sd->ass_track != ctx->ass_track) ass_free_track(ctx->ass_track); talloc_free(ctx); } @@ -292,15 +291,14 @@ const struct sd_functions sd_ass = { .get_bitmaps = get_bitmaps, .get_text = get_text, .reset = reset, - .switch_off = reset, .uninit = uninit, }; -struct ass_track *sub_get_ass_track(struct osd_state *osd) +struct ass_track *sub_get_ass_track(struct dec_sub *sub) { - struct sh_sub *sh = osd ? osd->sh_sub : NULL; - if (sh && sh->sd_driver == &sd_ass && sh->context) { - struct sd_ass_priv *ctx = sh->context; + struct sd *sd = sub_get_sd(sub); + if (sd && sd->driver == &sd_ass && sd->priv) { + struct sd_ass_priv *ctx = sd->priv; return ctx->ass_track; } return NULL; diff --git a/sub/sd_lavc.c b/sub/sd_lavc.c index 4c7dfd12a5..9f8db2d877 100644 --- a/sub/sd_lavc.c +++ b/sub/sd_lavc.c @@ -81,12 +81,10 @@ static void guess_resolution(enum AVCodecID type, int *w, int *h) } } -static int init(struct sh_sub *sh, struct osd_state *osd) +static int init(struct sd *sd) { - if (sh->initialized) - return 0; struct sd_lavc_priv *priv = talloc_zero(NULL, struct sd_lavc_priv); - enum AVCodecID cid = mp_codec_to_av_codec_id(sh->gsh->codec); + enum AVCodecID cid = mp_codec_to_av_codec_id(sd->codec); AVCodecContext *ctx = NULL; AVCodec *sub_codec = avcodec_find_decoder(cid); if (!sub_codec) @@ -94,12 +92,12 @@ static int init(struct sh_sub *sh, struct osd_state *osd) ctx = avcodec_alloc_context3(sub_codec); if (!ctx) goto error; - ctx->extradata_size = sh->extradata_len; - ctx->extradata = sh->extradata; + ctx->extradata_size = sd->extradata_len; + ctx->extradata = sd->extradata; if (avcodec_open2(ctx, sub_codec, NULL) < 0) goto error; priv->avctx = ctx; - sh->context = priv; + sd->priv = priv; return 0; error: @@ -126,18 +124,19 @@ static void clear(struct sd_lavc_priv *priv) priv->have_sub = false; } -static void decode(struct sh_sub *sh, struct osd_state *osd, void *data, - int data_len, double pts, double duration) +static void decode(struct sd *sd, struct demux_packet *packet) { - struct sd_lavc_priv *priv = sh->context; + struct sd_lavc_priv *priv = sd->priv; AVCodecContext *ctx = priv->avctx; + double pts = packet->pts; + double duration = packet->duration; AVSubtitle sub; AVPacket pkt; clear(priv); av_init_packet(&pkt); - pkt.data = data; - pkt.size = data_len; + pkt.data = packet->buffer; + pkt.size = packet->len; pkt.pts = pts * 1000; if (duration >= 0) pkt.convergence_duration = duration * 1000; @@ -189,11 +188,10 @@ static void decode(struct sh_sub *sh, struct osd_state *osd, void *data, } } -static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd, - struct mp_osd_res d, double pts, +static void get_bitmaps(struct sd *sd, struct mp_osd_res d, double pts, struct sub_bitmaps *res) { - struct sd_lavc_priv *priv = sh->context; + struct sd_lavc_priv *priv = sd->priv; if (priv->pts != MP_NOPTS_VALUE && pts < priv->pts) return; @@ -225,9 +223,9 @@ static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd, res->scaled = xscale != 1 || yscale != 1; } -static void reset(struct sh_sub *sh, struct osd_state *osd) +static void reset(struct sd *sd) { - struct sd_lavc_priv *priv = sh->context; + struct sd_lavc_priv *priv = sd->priv; if (priv->pts == MP_NOPTS_VALUE) clear(priv); @@ -235,9 +233,9 @@ static void reset(struct sh_sub *sh, struct osd_state *osd) avcodec_flush_buffers(priv->avctx); } -static void uninit(struct sh_sub *sh) +static void uninit(struct sd *sd) { - struct sd_lavc_priv *priv = sh->context; + struct sd_lavc_priv *priv = sd->priv; clear(priv); avcodec_close(priv->avctx); @@ -251,6 +249,5 @@ const struct sd_functions sd_lavc = { .decode = decode, .get_bitmaps = get_bitmaps, .reset = reset, - .switch_off = reset, .uninit = uninit, }; diff --git a/sub/sd_spu.c b/sub/sd_spu.c index 8b87b7a0dc..d2dd5f56e0 100644 --- a/sub/sd_spu.c +++ b/sub/sd_spu.c @@ -40,37 +40,34 @@ static bool supports_format(const char *format) return is_dvd_sub(format); } -static int init(struct sh_sub *sh, struct osd_state *osd) +static int init(struct sd *sd) { - if (sh->initialized) - return 0; - void *spudec = spudec_new_scaled(osd->sub_video_w, osd->sub_video_h, - sh->extradata, sh->extradata_len); + void *spudec = spudec_new_scaled(sd->sub_video_w, sd->sub_video_h, + sd->extradata, sd->extradata_len); if (!spudec) return -1; struct sd_spu_priv *priv = talloc_zero(NULL, struct sd_spu_priv); priv->spudec = spudec; - sh->context = priv; + sd->priv = priv; return 0; } -static void decode(struct sh_sub *sh, struct osd_state *osd, void *data, - int data_len, double pts, double duration) +static void decode(struct sd *sd, struct demux_packet *packet) { - struct sd_spu_priv *priv = sh->context; + struct sd_spu_priv *priv = sd->priv; - if (pts < 0 || data_len == 0) + if (packet->pts < 0 || packet->len == 0) return; - spudec_assemble(priv->spudec, data, data_len, pts * 90000); + spudec_assemble(priv->spudec, packet->buffer, packet->len, + packet->pts * 90000); } -static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd, - struct mp_osd_res d, double pts, +static void get_bitmaps(struct sd *sd, struct mp_osd_res d, double pts, struct sub_bitmaps *res) { - struct MPOpts *opts = sh->opts; - struct sd_spu_priv *priv = sh->context; + struct MPOpts *opts = sd->opts; + struct sd_spu_priv *priv = sd->priv; spudec_set_forced_subs_only(priv->spudec, opts->forced_subs_only); spudec_heartbeat(priv->spudec, pts * 90000); @@ -79,16 +76,16 @@ static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd, spudec_get_indexed(priv->spudec, &d, res); } -static void reset(struct sh_sub *sh, struct osd_state *osd) +static void reset(struct sd *sd) { - struct sd_spu_priv *priv = sh->context; + struct sd_spu_priv *priv = sd->priv; spudec_reset(priv->spudec); } -static void uninit(struct sh_sub *sh) +static void uninit(struct sd *sd) { - struct sd_spu_priv *priv = sh->context; + struct sd_spu_priv *priv = sd->priv; spudec_free(priv->spudec); talloc_free(priv); @@ -100,6 +97,5 @@ const struct sd_functions sd_spu = { .decode = decode, .get_bitmaps = get_bitmaps, .reset = reset, - .switch_off = reset, .uninit = uninit, }; diff --git a/sub/sub.c b/sub/sub.c index 9dc5722469..a0965dc1ec 100644 --- a/sub/sub.c +++ b/sub/sub.c @@ -159,11 +159,11 @@ static void render_object(struct osd_state *osd, struct osd_object *obj, obj->vo_res = res; if (obj->type == OSDTYPE_SUB) { - if (osd->render_bitmap_subs) { + if (osd->render_bitmap_subs && osd->dec_sub) { double sub_pts = video_pts; if (sub_pts != MP_NOPTS_VALUE) sub_pts -= osd->sub_offset; - sub_get_bitmaps(osd, obj->vo_res, sub_pts, out_imgs); + sub_get_bitmaps(osd->dec_sub, obj->vo_res, sub_pts, out_imgs); } } else { osd_object_get_bitmaps(osd, obj, out_imgs); diff --git a/sub/sub.h b/sub/sub.h index fae7202ed5..a13d3ca6f8 100644 --- a/sub/sub.h +++ b/sub/sub.h @@ -120,7 +120,6 @@ struct osd_state { struct ass_library *ass_library; struct ass_renderer *ass_renderer; - struct sh_sub *sh_sub; double sub_offset; double vo_pts; @@ -138,15 +137,11 @@ struct osd_state { float progbar_value; // range 0.0-1.0 float *progbar_stops; // used for chapter indicators (0.0-1.0 each) int progbar_num_stops; - - int switch_sub_id; + // OSDTYPE_SUB + struct dec_sub *dec_sub; struct MPOpts *opts; - // Video resolution used for subtitle decoding. Doesn't necessarily match - // the resolution of the VO, nor does it have to be the OSD resolution. - int sub_video_w, sub_video_h; - // Internal to sub.c struct mp_draw_sub_cache *draw_cache; -- cgit v1.2.3