diff options
Diffstat (limited to 'sub')
-rw-r--r-- | sub/dec_sub.c | 28 | ||||
-rw-r--r-- | sub/sd_ass.c | 1 | ||||
-rw-r--r-- | sub/sd_lavc.c | 8 | ||||
-rw-r--r-- | sub/sd_spu.c | 99 | ||||
-rw-r--r-- | sub/spudec.c | 31 | ||||
-rw-r--r-- | sub/spudec.h | 4 | ||||
-rw-r--r-- | sub/sub.c | 16 | ||||
-rw-r--r-- | sub/sub.h | 8 |
8 files changed, 149 insertions, 46 deletions
diff --git a/sub/dec_sub.c b/sub/dec_sub.c index 3de7d1223d..36ba25edd2 100644 --- a/sub/dec_sub.c +++ b/sub/dec_sub.c @@ -29,6 +29,16 @@ extern const struct sd_functions sd_ass; extern const struct sd_functions sd_lavc; +extern const struct sd_functions sd_spu; + +static const struct sd_functions *sd_list[] = { +#ifdef CONFIG_ASS + &sd_ass, +#endif + &sd_lavc, + &sd_spu, + NULL +}; bool is_text_sub(const char *t) { @@ -46,20 +56,20 @@ bool is_ass_sub(const char *t) bool is_dvd_sub(const char *t) { - return t && strcmp(t, "dvd_subtitle") == 0; + return t && (strcmp(t, "dvd_subtitle") == 0 || + strcmp(t, "dvd_subtitle_mpg") == 0); } void sub_init(struct sh_sub *sh, struct osd_state *osd) { - const char *format = sh->gsh->codec; + sh->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]; + break; + } + } - assert(!osd->sh_sub); - if (sd_lavc.supports_format(format)) - sh->sd_driver = &sd_lavc; -#ifdef CONFIG_ASS - if (sd_ass.supports_format(format)) - sh->sd_driver = &sd_ass; -#endif if (sh->sd_driver) { if (sh->sd_driver->init(sh, osd) < 0) return; diff --git a/sub/sd_ass.c b/sub/sd_ass.c index 1501f5da54..3dfbbd05fb 100644 --- a/sub/sd_ass.c +++ b/sub/sd_ass.c @@ -295,7 +295,6 @@ struct sh_sub *sd_ass_create_from_track(struct ass_track *track, .gsh = talloc_struct(sh, struct sh_stream, { .codec = codec, }), - .sd_driver = &sd_ass, .context = talloc_struct(sh, struct sd_ass_priv, { .ass_track = track, .vsfilter_aspect = is_ass_sub(codec), diff --git a/sub/sd_lavc.c b/sub/sd_lavc.c index e067da6a43..4e1d80d8ce 100644 --- a/sub/sd_lavc.c +++ b/sub/sd_lavc.c @@ -43,6 +43,14 @@ struct sd_lavc_priv { static bool supports_format(const char *format) { + // lavc dvdsubdec doesn't read color/resolution on Libav 9.1 and below, + // so fall back to sd_spu in this case. Never use sd_spu with new ffmpeg; + // spudec can't handle ffmpeg .idx demuxing (added to lavc in 54.79.100). +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 40, 0) + if (is_dvd_sub(format)) + return false; +#endif + enum AVCodecID cid = mp_codec_to_av_codec_id(format); // Supported codecs must be known to decode to paletted bitmaps switch (cid) { diff --git a/sub/sd_spu.c b/sub/sd_spu.c new file mode 100644 index 0000000000..fc4e4701dc --- /dev/null +++ b/sub/sd_spu.c @@ -0,0 +1,99 @@ +/* + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with mpv. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <assert.h> + +#include "talloc.h" +#include "core/options.h" +#include "demux/stheader.h" +#include "sd.h" +#include "sub.h" +#include "spudec.h" + +struct sd_spu_priv { + void *spudec; +}; + +static bool supports_format(const char *format) +{ + return is_dvd_sub(format); +} + +static int init(struct sh_sub *sh, struct osd_state *osd) +{ + if (sh->initialized) + return 0; + void *spudec = spudec_new_scaled(osd->sub_video_w, osd->sub_video_h, + sh->extradata, sh->extradata_len); + if (!spudec) + return -1; + struct sd_spu_priv *priv = talloc_zero(NULL, struct sd_spu_priv); + priv->spudec = spudec; + sh->context = priv; + return 0; +} + +static void decode(struct sh_sub *sh, struct osd_state *osd, void *data, + int data_len, double pts, double duration) +{ + struct sd_spu_priv *priv = sh->context; + + if (pts < 0 || data_len == 0) + return; + + spudec_assemble(priv->spudec, data, data_len, pts * 90000); +} + +static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd, + struct mp_osd_res d, double pts, + struct sub_bitmaps *res) +{ + struct MPOpts *opts = sh->opts; + struct sd_spu_priv *priv = sh->context; + + spudec_set_forced_subs_only(priv->spudec, opts->forced_subs_only); + spudec_heartbeat(priv->spudec, pts * 90000); + + if (spudec_visible(priv->spudec)) + spudec_get_indexed(priv->spudec, &d, res); +} + +static void reset(struct sh_sub *sh, struct osd_state *osd) +{ + struct sd_spu_priv *priv = sh->context; + + spudec_reset(priv->spudec); +} + +static void uninit(struct sh_sub *sh) +{ + struct sd_spu_priv *priv = sh->context; + + spudec_free(priv->spudec); + talloc_free(priv); +} + +const struct sd_functions sd_spu = { + .supports_format = supports_format, + .init = init, + .decode = decode, + .get_bitmaps = get_bitmaps, + .reset = reset, + .switch_off = reset, + .uninit = uninit, +}; diff --git a/sub/spudec.c b/sub/spudec.c index 59c3058251..87cd46bdd7 100644 --- a/sub/spudec.c +++ b/sub/spudec.c @@ -575,6 +575,13 @@ void spudec_assemble(void *this, unsigned char *packet, unsigned int len, int pt #endif } +void spudec_set_changed(void *this) +{ + spudec_handle_t *spu = this; + + spu->spu_changed = 1; +} + void spudec_reset(void *this) // called after seek { spudec_handle_t *spu = this; @@ -583,6 +590,7 @@ void spudec_reset(void *this) // called after seek spu->now_pts = 0; spu->end_pts = 0; spu->packet_size = spu->packet_offset = 0; + spudec_set_changed(spu); } void spudec_heartbeat(void *this, unsigned int pts100) @@ -611,7 +619,7 @@ void spudec_heartbeat(void *this, unsigned int pts100) spudec_process_data(spu, packet); } spudec_free_packet(packet); - spu->spu_changed = 1; + spudec_set_changed(spu); } } @@ -626,10 +634,11 @@ int spudec_visible(void *this){ void spudec_set_forced_subs_only(void * const this, const unsigned int flag) { - if(this){ - ((spudec_handle_t *)this)->forced_subs_only=flag; - mp_msg(MSGT_SPUDEC,MSGL_DBG2,"SPU: Display only forced subs now %s\n", flag ? "enabled": "disabled"); - } + spudec_handle_t *spu = this; + if (!!flag != !!spu->forced_subs_only) { + spu->forced_subs_only = !!flag; + spudec_set_changed(spu); + } } void spudec_get_indexed(void *this, struct mp_osd_res *dim, @@ -738,17 +747,14 @@ static void spudec_parse_extradata(spudec_handle_t *this, free(buffer); } -void *spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigned int frame_height, uint8_t *extradata, int extradata_len) +void *spudec_new_scaled(unsigned int frame_width, unsigned int frame_height, uint8_t *extradata, int extradata_len) { spudec_handle_t *this = calloc(1, sizeof(spudec_handle_t)); if (this){ this->orig_frame_height = frame_height; this->orig_frame_width = frame_width; // set up palette: - if (palette) - memcpy(this->global_palette, palette, sizeof(this->global_palette)); - else - this->auto_palette = 1; + this->auto_palette = 1; if (extradata) spudec_parse_extradata(this, extradata, extradata_len); /* XXX Although the video frame is some size, the SPU frame is @@ -768,11 +774,6 @@ void *spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigne return this; } -void *spudec_new(unsigned int *palette) -{ - return spudec_new_scaled(palette, 0, 0, NULL, 0); -} - void spudec_free(void *this) { spudec_handle_t *spu = this; diff --git a/sub/spudec.h b/sub/spudec.h index fa395798ac..3a44bd1e2e 100644 --- a/sub/spudec.h +++ b/sub/spudec.h @@ -27,12 +27,12 @@ struct mp_osd_res; void spudec_heartbeat(void *this, unsigned int pts100); void spudec_assemble(void *this, unsigned char *packet, unsigned int len, int pts100); void spudec_get_indexed(void *this, struct mp_osd_res *dim, struct sub_bitmaps *res); -void *spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigned int frame_height, uint8_t *extradata, int extradata_len); -void *spudec_new(unsigned int *palette); +void *spudec_new_scaled(unsigned int frame_width, unsigned int frame_height, uint8_t *extradata, int extradata_len); void spudec_free(void *this); void spudec_reset(void *this); // called after seek int spudec_visible(void *this); // check if spu is visible int spudec_changed(void *this); +void spudec_set_changed(void *this); void spudec_set_forced_subs_only(void * const this, const unsigned int flag); #endif /* MPLAYER_SPUDEC_H */ @@ -37,7 +37,6 @@ #include "dec_sub.h" #include "img_convert.h" #include "draw_bmp.h" -#include "spudec.h" #include "subreader.h" #include "video/mp_image.h" #include "video/mp_image_pool.h" @@ -48,9 +47,6 @@ int sub_visibility=1; float sub_delay = 0; float sub_fps = 0; -void *vo_spudec=NULL; -void *vo_vobsub=NULL; - static const struct osd_style_opts osd_style_opts_def = { .font = "Sans", .font_size = 45, @@ -114,7 +110,6 @@ struct osd_state *osd_create(struct MPOpts *opts, struct ass_library *asslib) osd->objs[n] = obj; } - osd->objs[OSDTYPE_SPU]->is_sub = true; // spudec.c osd->objs[OSDTYPE_SUB]->is_sub = true; // dec_sub.c osd->objs[OSDTYPE_SUBTEXT]->is_sub = true; // osd_libass.c @@ -155,12 +150,6 @@ void osd_set_sub(struct osd_state *osd, const char *text) vo_osd_changed(OSDTYPE_SUBTEXT); } -static bool spu_visible(struct osd_state *osd, struct osd_object *obj) -{ - struct MPOpts *opts = osd->opts; - return opts->sub_visibility && vo_spudec && spudec_visible(vo_spudec); -} - static void render_object(struct osd_state *osd, struct osd_object *obj, struct mp_osd_res res, double video_pts, const bool sub_formats[SUBBITMAP_COUNT], @@ -179,10 +168,7 @@ static void render_object(struct osd_state *osd, struct osd_object *obj, obj->force_redraw = true; obj->vo_res = res; - if (obj->type == OSDTYPE_SPU) { - if (spu_visible(osd, obj)) - spudec_get_indexed(vo_spudec, &obj->vo_res, out_imgs); - } else if (obj->type == OSDTYPE_SUB) { + if (obj->type == OSDTYPE_SUB) { if (osd->render_bitmap_subs) { double sub_pts = video_pts; if (sub_pts != MP_NOPTS_VALUE) @@ -86,7 +86,6 @@ struct mp_osd_res { enum mp_osdtype { OSDTYPE_SUB, OSDTYPE_SUBTEXT, - OSDTYPE_SPU, OSDTYPE_PROGBAR, OSDTYPE_OSD, @@ -144,6 +143,10 @@ struct osd_state { 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; @@ -152,9 +155,6 @@ struct osd_state { struct ass_library *osd_ass_library; }; -extern void* vo_spudec; -extern void* vo_vobsub; - // Start of OSD symbols in osd_font.pfb #define OSD_CODEPOINTS 0xE000 |