summaryrefslogtreecommitdiffstats
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
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.
-rw-r--r--core/command.c4
-rw-r--r--core/mplayer.c80
-rw-r--r--demux/stheader.h3
-rw-r--r--sub/dec_sub.c163
-rw-r--r--sub/dec_sub.h36
-rw-r--r--sub/sd.h40
-rw-r--r--sub/sd_ass.c80
-rw-r--r--sub/sd_lavc.c37
-rw-r--r--sub/sd_spu.c36
-rw-r--r--sub/sub.c4
-rw-r--r--sub/sub.h9
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);
}