summaryrefslogtreecommitdiffstats
path: root/sub
diff options
context:
space:
mode:
Diffstat (limited to 'sub')
-rw-r--r--sub/dec_sub.c28
-rw-r--r--sub/sd_ass.c1
-rw-r--r--sub/sd_lavc.c8
-rw-r--r--sub/sd_spu.c99
-rw-r--r--sub/spudec.c31
-rw-r--r--sub/spudec.h4
-rw-r--r--sub/sub.c16
-rw-r--r--sub/sub.h8
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 */
diff --git a/sub/sub.c b/sub/sub.c
index 4e5420627c..d26ce17551 100644
--- a/sub/sub.c
+++ b/sub/sub.c
@@ -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)
diff --git a/sub/sub.h b/sub/sub.h
index a922d2b162..6b15cf90c0 100644
--- a/sub/sub.h
+++ b/sub/sub.h
@@ -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