summaryrefslogtreecommitdiffstats
path: root/sub/dec_sub.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-06-01 19:44:12 +0200
committerwm4 <wm4@nowhere>2013-06-01 19:44:16 +0200
commit02ce316ade9ba932ad405383278d6b01c54e5fc4 (patch)
tree4151e307fafc30a4079d4cd79c3d85d92df35105 /sub/dec_sub.c
parent27d383918a3d63559c85ca96b2162a13234f2abc (diff)
downloadmpv-02ce316ade9ba932ad405383278d6b01c54e5fc4.tar.bz2
mpv-02ce316ade9ba932ad405383278d6b01c54e5fc4.tar.xz
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.
Diffstat (limited to 'sub/dec_sub.c')
-rw-r--r--sub/dec_sub.c163
1 files changed, 102 insertions, 61 deletions
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);
}