summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-04-29 01:13:22 +0200
committerwm4 <wm4@nowhere>2013-05-30 22:40:32 +0200
commit26842806431a1d21e3c3c430994cd6901e36a08e (patch)
treeef0c302e3a60cd7c20e98787de1ccef9ed7ee32b /core
parent724f576211c1ea07e0423ac8a9c0e4f273c452fb (diff)
downloadmpv-26842806431a1d21e3c3c430994cd6901e36a08e.tar.bz2
mpv-26842806431a1d21e3c3c430994cd6901e36a08e.tar.xz
sub: add sd_spu.c to wrap spudec, cleanup mplayer.c
This unifies the subtitle rendering path. Now all subtitle rendering goes through sd_ass.c/sd_lavc.c/sd_spu.c. Before that commit, the spudec.h functions were used directly in mplayer.c, which introduced many special cases. Add sd_spu.c, which is just a small wrapper connecting the new subtitle render API with the dusty old vobsub decoder in spudec.c. One detail that changes is that we always pass the palette as extra data, instead of passing the libdvdread palette as pointer to spudec directly. This is a bit roundabout, but actually makes the code simpler and more elegant: the difference between DVD and non-DVD dvdsubs is reduced. Ideally, we would just delete spudec.c and use libavcodec's DVD sub decoder. However, DVD playback with demux_mpg produces packets incompatible to lavc. There are incompatibilities the other way around as well: packets from libavformat's vobsub demuxer are incompatible to spudec.c. So we define a new subtitle codec name for demux_mpg subs, "dvd_subtitle_mpg", which only sd_spu can decode. There is actually code in spudec.c to "assemble" fragments into complete packets, but using the whole spudec.c is easier than trying to move this code into demux_mpg to fix subtitle packets. As additional complication, Libav 9.x can't decode DVD subs correctly, so use sd_spu in that case as well.
Diffstat (limited to 'core')
-rw-r--r--core/command.c23
-rw-r--r--core/mp_core.h2
-rw-r--r--core/mplayer.c127
3 files changed, 20 insertions, 132 deletions
diff --git a/core/command.c b/core/command.c
index 7eb36be5f3..4e82ceccd8 100644
--- a/core/command.c
+++ b/core/command.c
@@ -50,7 +50,6 @@
#include "audio/filter/af.h"
#include "video/decode/dec_video.h"
#include "audio/decode/dec_audio.h"
-#include "sub/spudec.h"
#include "core/path.h"
#include "sub/ass_mp.h"
#include "stream/tv.h"
@@ -1307,8 +1306,7 @@ static int mp_property_sub_visibility(m_option_t *prop, int action,
switch (action) {
case M_PROPERTY_SET:
opts->sub_visibility = *(int *)arg;
- if (vo_spudec)
- vo_osd_changed(OSDTYPE_SPU);
+ osd_changed_all(mpctx->osd);
return M_PROPERTY_OK;
case M_PROPERTY_GET:
*(int *)arg = opts->sub_visibility;
@@ -1317,23 +1315,6 @@ static int mp_property_sub_visibility(m_option_t *prop, int action,
return M_PROPERTY_NOT_IMPLEMENTED;
}
-/// Show only forced subtitles (RW)
-static int mp_property_sub_forced_only(m_option_t *prop, int action,
- void *arg, MPContext *mpctx)
-{
- struct MPOpts *opts = &mpctx->opts;
-
- if (!vo_spudec)
- return M_PROPERTY_UNAVAILABLE;
-
- if (action == M_PROPERTY_SET) {
- opts->forced_subs_only = *(int *)arg;
- spudec_set_forced_subs_only(vo_spudec, opts->forced_subs_only);
- return M_PROPERTY_OK;
- }
- return mp_property_generic_option(prop, action, arg, mpctx);
-}
-
#ifdef CONFIG_TV
@@ -1514,7 +1495,7 @@ static const m_option_t mp_properties[] = {
M_OPTION_PROPERTY_CUSTOM("sub-pos", mp_property_sub_pos),
{ "sub-visibility", mp_property_sub_visibility, CONF_TYPE_FLAG,
M_OPT_RANGE, 0, 1, NULL },
- M_OPTION_PROPERTY_CUSTOM("sub-forced-only", mp_property_sub_forced_only),
+ M_OPTION_PROPERTY_CUSTOM("sub-forced-only", property_osd_helper),
M_OPTION_PROPERTY_CUSTOM("sub-scale", property_osd_helper),
#ifdef CONFIG_ASS
M_OPTION_PROPERTY_CUSTOM("ass-use-margins", property_osd_helper),
diff --git a/core/mp_core.h b/core/mp_core.h
index 665588c5c0..db6bc570e1 100644
--- a/core/mp_core.h
+++ b/core/mp_core.h
@@ -31,7 +31,6 @@
#define INITIALIZED_AO 2
#define INITIALIZED_VOL 4
#define INITIALIZED_GETCH2 8
-#define INITIALIZED_SPUDEC 32
#define INITIALIZED_STREAM 64
#define INITIALIZED_DEMUXER 512
#define INITIALIZED_ACODEC 1024
@@ -293,7 +292,6 @@ extern int forced_subs_only;
void uninit_player(struct MPContext *mpctx, unsigned int mask);
void reinit_audio_chain(struct MPContext *mpctx);
-void init_vo_spudec(struct MPContext *mpctx);
double playing_audio_pts(struct MPContext *mpctx);
struct track *mp_add_subtitles(struct MPContext *mpctx, char *filename,
float fps, int noerr);
diff --git a/core/mplayer.c b/core/mplayer.c
index bb6a0872cc..c596aa8504 100644
--- a/core/mplayer.c
+++ b/core/mplayer.c
@@ -95,8 +95,6 @@
#include "core/codecs.h"
-#include "sub/spudec.h"
-
#include "osdep/getch2.h"
#include "osdep/timer.h"
@@ -554,12 +552,6 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask)
getch2_disable();
}
- if (mask & INITIALIZED_SPUDEC) {
- mpctx->initialized_flags &= ~INITIALIZED_SPUDEC;
- spudec_free(vo_spudec);
- vo_spudec = NULL;
- }
-
if (mask & INITIALIZED_VOL) {
mpctx->initialized_flags &= ~INITIALIZED_VOL;
if (mpctx->mixer.ao) {
@@ -1104,38 +1096,6 @@ struct track *mp_add_subtitles(struct MPContext *mpctx, char *filename,
return track;
}
-void init_vo_spudec(struct MPContext *mpctx)
-{
- uninit_player(mpctx, INITIALIZED_SPUDEC);
- unsigned width, height;
-
- // we currently can't work without video stream
- if (!mpctx->sh_video)
- return;
-
- width = mpctx->sh_video->disp_w;
- height = mpctx->sh_video->disp_h;
-
-#ifdef CONFIG_DVDREAD
- if (vo_spudec == NULL && mpctx->stream->type == STREAMTYPE_DVD) {
- vo_spudec = spudec_new_scaled(((dvd_priv_t *)(mpctx->stream->priv))->
- cur_pgc->palette, width, height, NULL, 0);
- }
-#endif
-
- if (vo_spudec == NULL && mpctx->sh_sub) {
- sh_sub_t *sh = mpctx->sh_sub;
- vo_spudec = spudec_new_scaled(NULL, width, height, sh->extradata,
- sh->extradata_len);
- }
-
- if (vo_spudec != NULL) {
- mpctx->initialized_flags |= INITIALIZED_SPUDEC;
- mp_property_do("sub-forced-only", M_PROPERTY_SET,
- &mpctx->opts.forced_subs_only, mpctx);
- }
-}
-
int mp_get_cache_percent(struct MPContext *mpctx)
{
if (mpctx->stream) {
@@ -1867,10 +1827,6 @@ static void reset_subtitles(struct MPContext *mpctx)
if (mpctx->sh_sub)
sub_reset(mpctx->sh_sub, mpctx->osd);
set_osd_subtitle(mpctx, NULL);
- if (vo_spudec) {
- spudec_reset(vo_spudec);
- vo_osd_changed(OSDTYPE_SPU);
- }
}
static void update_subtitles(struct MPContext *mpctx, double refpts_tl)
@@ -1892,46 +1848,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;
- // DVD sub:
- if (is_dvd_sub(type) && !(sh_sub && sh_sub->active)) {
- int timestamp;
- // Get a sub packet from the demuxer (or the vobsub.c thing, which
- // should be a demuxer, but isn't).
- while (1) {
- // Vobsub
- len = 0;
- {
- // DVD sub
- assert(d_sub->sh == sh_sub);
- len = ds_get_packet_sub(d_sub, (unsigned char **)&packet);
- if (len > 0) {
- // XXX This is wrong, sh_video->pts can be arbitrarily
- // much behind demuxing position. Unfortunately using
- // d_video->pts which would have been the simplest
- // improvement doesn't work because mpeg specific hacks
- // in video.c set d_video->pts to 0.
- float x = d_sub->pts - refpts_s;
- if (x > -20 && x < 20) // prevent missing subs on pts reset
- timestamp = 90000 * d_sub->pts;
- else
- timestamp = 90000 * curpts_s;
- mp_dbg(MSGT_CPLAYER, MSGL_V, "\rDVD sub: len=%d "
- "v_pts=%5.3f s_pts=%5.3f ts=%d \n", len,
- refpts_s, d_sub->pts, timestamp);
- }
- }
- if (len <= 0 || !packet)
- break;
- // create it only here, since with some broken demuxers we might
- // type = v but no DVD sub and we currently do not change the
- // "original frame size" ever after init, leading to wrong-sized
- // PGS subtitles.
- if (!vo_spudec)
- vo_spudec = spudec_new(NULL);
- if (timestamp >= 0)
- spudec_assemble(vo_spudec, packet, len, timestamp);
- }
- } else if (d_sub && sh_sub && sh_sub->active) {
+ if (d_sub && sh_sub && sh_sub->active) {
bool non_interleaved = is_non_interleaved(mpctx, track);
if (non_interleaved)
ds_get_next_pts(d_sub);
@@ -1979,11 +1896,6 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl)
ds_get_next_pts(d_sub);
}
}
- if (vo_spudec) {
- spudec_heartbeat(vo_spudec, 90000 * curpts_s);
- if (spudec_changed(vo_spudec))
- vo_osd_changed(OSDTYPE_SPU);
- }
if (!mpctx->osd->render_bitmap_subs)
set_osd_subtitle(mpctx, sub_get_text(mpctx->osd, curpts_s));
@@ -2030,10 +1942,10 @@ static double timing_sleep(struct MPContext *mpctx, double time_frame)
}
static void set_dvdsub_fake_extradata(struct sh_sub *sh_sub, struct stream *st,
- struct sh_video *sh_video)
+ int width, int height)
{
#ifdef CONFIG_DVDREAD
- if (st->type != STREAMTYPE_DVD || !sh_video)
+ if (st->type != STREAMTYPE_DVD)
return;
struct mp_csp_params csp = MP_CSP_PARAMS_DEFAULTS;
@@ -2042,10 +1954,13 @@ static void set_dvdsub_fake_extradata(struct sh_sub *sh_sub, struct stream *st,
float cmatrix[3][4];
mp_get_yuv2rgb_coeffs(&csp, cmatrix);
- int width = sh_video->disp_w;
- int height = sh_video->disp_h;
int *palette = ((dvd_priv_t *)st->priv)->cur_pgc->palette;
+ if (width == 0 || height == 0) {
+ width = 720;
+ height = 480;
+ }
+
char *s = NULL;
s = talloc_asprintf_append(s, "size: %dx%d\n", width, height);
s = talloc_asprintf_append(s, "palette: ");
@@ -2072,6 +1987,7 @@ 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));
@@ -2098,24 +2014,17 @@ static void reinit_subs(struct MPContext *mpctx)
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;
+
if (track->sh_sub) {
- sub_init(track->sh_sub, mpctx->osd);
+ sub_init(track->sh_sub, osd);
} else if (track->stream) {
- struct stream *s = track->demuxer ? track->demuxer->stream : NULL;
- if (s && s->type == STREAMTYPE_DVD)
- set_dvdsub_fake_extradata(mpctx->sh_sub, s, mpctx->sh_video);
- // lavc dvdsubdec doesn't read color/resolution on Libav 9.1 and below
- // Don't use it for new ffmpeg; spudec can't handle ffmpeg .idx demuxing
- // (ffmpeg added .idx demuxing during lavc 54.79.100)
- bool broken_lavc = false;
-#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 40, 0)
- broken_lavc = true;
-#endif
- if (is_dvd_sub(mpctx->sh_sub->gsh->codec) && track->demuxer
- && (track->demuxer->type == DEMUXER_TYPE_MPEG_PS || broken_lavc))
- init_vo_spudec(mpctx);
- else
- sub_init(mpctx->sh_sub, mpctx->osd);
+ 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);
}
// Decides whether to use OSD path or normal subtitle rendering path.