diff options
-rw-r--r-- | core/mplayer.c | 14 | ||||
-rw-r--r-- | demux/demux.c | 15 | ||||
-rw-r--r-- | demux/demux_lavf.c | 21 | ||||
-rw-r--r-- | demux/demux_mkv.c | 37 | ||||
-rw-r--r-- | demux/demux_mpg.c | 2 | ||||
-rw-r--r-- | demux/demux_ts.c | 6 | ||||
-rw-r--r-- | demux/stheader.h | 3 | ||||
-rw-r--r-- | sub/dec_sub.c | 25 | ||||
-rw-r--r-- | sub/dec_sub.h | 7 | ||||
-rw-r--r-- | sub/sd.h | 1 | ||||
-rw-r--r-- | sub/sd_ass.c | 17 | ||||
-rw-r--r-- | sub/sd_lavc.c | 35 |
12 files changed, 91 insertions, 92 deletions
diff --git a/core/mplayer.c b/core/mplayer.c index 41fac2adf8..2df036307b 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -275,10 +275,8 @@ static void print_stream(struct MPContext *mpctx, struct track *t, int id) if (t->title) mp_msg(MSGT_CPLAYER, MSGL_INFO, " '%s'", t->title); const char *codec = s ? s->codec : NULL; - if (s && t->type == STREAM_SUB) - codec = sh_sub_type2str(s->sub->type); if (t->sh_sub) // external subs hack - codec = sh_sub_type2str(t->sh_sub->type); + codec = t->sh_sub->gsh->codec; mp_msg(MSGT_CPLAYER, MSGL_INFO, " (%s)", codec ? codec : "<unknown>"); if (t->is_external) mp_msg(MSGT_CPLAYER, MSGL_INFO, " (external)"); @@ -1724,7 +1722,7 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl) struct demux_stream *d_sub = sh_sub ? sh_sub->ds : NULL; unsigned char *packet = NULL; int len; - int type = sh_sub ? sh_sub->type : '\0'; + const char *type = sh_sub ? sh_sub->gsh->codec : NULL; mpctx->osd->sub_offset = mpctx->video_offset; @@ -1747,7 +1745,7 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl) } // DVD sub: - if (type == 'v' && !(sh_sub && sh_sub->active)) { + 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). @@ -1808,7 +1806,7 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl) mp_dbg(MSGT_CPLAYER, MSGL_V, "Sub: c_pts=%5.3f s_pts=%5.3f " "duration=%5.3f len=%d\n", curpts_s, subpts_s, duration, len); - if (type == 'm') { + if (type && strcmp(type, "mov_text") == 0) { if (len < 2) continue; len = FFMIN(len - 2, AV_RB16(packet)); @@ -1820,7 +1818,7 @@ static void update_subtitles(struct MPContext *mpctx, double refpts_tl) // text sub if (duration < 0) sub_clear_text(&mpctx->subs, MP_NOPTS_VALUE); - if (type == 'a') { // ssa/ass subs without libass => convert to plaintext + if (is_ass_sub(type)) { // ssa/ass subs without libass => convert to plaintext int i; unsigned char *p = packet; for (i = 0; i < 8 && *p != '\0'; p++) @@ -1977,7 +1975,7 @@ static void reinit_subs(struct MPContext *mpctx) #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 40, 0) broken_lavc = true; #endif - if (mpctx->sh_sub->type == 'v' && track->demuxer + 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 diff --git a/demux/demux.c b/demux/demux.c index c23185c90b..b3cb078dcb 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -241,21 +241,6 @@ demuxer_t *new_demuxer(struct MPOpts *opts, stream_t *stream, int type, return d; } -const char *sh_sub_type2str(int type) -{ - switch (type) { - case 't': return "text"; - case 'm': return "movtext"; - case 'a': return "ass"; - case 'v': return "vobsub"; - case 'x': return "xsub"; - case 'b': return "dvb"; - case 'd': return "dvb-teletext"; - case 'p': return "hdmv pgs"; - } - return "unknown"; -} - static struct sh_stream *new_sh_stream_id(demuxer_t *demuxer, enum stream_type type, int stream_index, diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index 498f99e014..968e9e60c8 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -387,32 +387,11 @@ static void handle_stream(demuxer_t *demuxer, int i) } case AVMEDIA_TYPE_SUBTITLE: { sh_sub_t *sh_sub; - char type; - if (codec->codec_id == AV_CODEC_ID_TEXT || - codec->codec_id == AV_CODEC_ID_SUBRIP) - type = 't'; - else if (codec->codec_id == AV_CODEC_ID_MOV_TEXT) - type = 'm'; - else if (codec->codec_id == AV_CODEC_ID_SSA) - type = 'a'; - else if (codec->codec_id == AV_CODEC_ID_DVD_SUBTITLE) - type = 'v'; - else if (codec->codec_id == AV_CODEC_ID_XSUB) - type = 'x'; - else if (codec->codec_id == AV_CODEC_ID_DVB_SUBTITLE) - type = 'b'; - else if (codec->codec_id == AV_CODEC_ID_DVB_TELETEXT) - type = 'd'; - else if (codec->codec_id == AV_CODEC_ID_HDMV_PGS_SUBTITLE) - type = 'p'; - else - break; sh = new_sh_stream(demuxer, STREAM_SUB); if (!sh) break; sh_sub = sh->sub; - sh_sub->type = type; if (codec->extradata_size) { sh_sub->extradata = malloc(codec->extradata_size); memcpy(sh_sub->extradata, codec->extradata, codec->extradata_size); diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 03789631dc..647f831630 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -133,8 +133,6 @@ typedef struct mkv_track { int fix_i_bps; double qt_last_a_pts; - int subtitle_type; - /* generic content encoding support */ mkv_content_encoding_t *encodings; int num_encodings; @@ -602,18 +600,6 @@ static void parse_trackentry(struct demuxer *demuxer, if (!strcmp(track->codec_id, MKV_V_MSCOMP) || !strcmp(track->codec_id, MKV_A_ACM)) track->ms_compat = 1; - else if (!strcmp(track->codec_id, MKV_S_VOBSUB)) - track->subtitle_type = 'v'; - else if (!strcmp(track->codec_id, MKV_S_TEXTSSA) - || !strcmp(track->codec_id, MKV_S_TEXTASS) - || !strcmp(track->codec_id, MKV_S_SSA) - || !strcmp(track->codec_id, MKV_S_ASS)) - track->subtitle_type = 'a'; - else if (!strcmp(track->codec_id, MKV_S_TEXTASCII) - || !strcmp(track->codec_id, MKV_S_TEXTUTF8)) - track->subtitle_type = 't'; - else if (!strcmp(track->codec_id, MKV_S_PGS)) - track->subtitle_type = 'p'; mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Codec ID: %s\n", track->codec_id); } else @@ -1571,9 +1557,28 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track) return 1; } +static const char *mkv_sub_tag[][2] = { + { MKV_S_VOBSUB, "dvd_subtitle" }, + { MKV_S_TEXTSSA, "ass"}, + { MKV_S_TEXTASS, "ass"}, + { MKV_S_SSA, "ass"}, + { MKV_S_ASS, "ass"}, + { MKV_S_TEXTASCII, "subrip"}, + { MKV_S_TEXTUTF8, "subrip"}, + { MKV_S_PGS, "hdmv_pgs_subtitle"}, + {0} +}; + static int demux_mkv_open_sub(demuxer_t *demuxer, mkv_track_t *track) { - if (track->subtitle_type) { + const char *subtitle_type = NULL; + for (int n = 0; mkv_sub_tag[n][0]; n++) { + if (strcmp(track->codec_id, mkv_sub_tag[n][0]) == 0) { + subtitle_type = mkv_sub_tag[n][1]; + break; + } + } + if (subtitle_type) { bstr in = (bstr){track->private_data, track->private_size}; struct sh_stream *gsh = new_sh_stream(demuxer, STREAM_SUB); if (!gsh) @@ -1582,7 +1587,7 @@ static int demux_mkv_open_sub(demuxer_t *demuxer, mkv_track_t *track) sh_sub_t *sh = gsh->sub; sh->gsh->demuxer_id = track->tnum; track->sh_sub = sh; - sh->type = track->subtitle_type; + sh->gsh->codec = subtitle_type; bstr buffer = demux_mkv_decode(track, in, 2); if (buffer.start && buffer.start != track->private_data) { talloc_free(track->private_data); diff --git a/demux/demux_mpg.c b/demux/demux_mpg.c index 52153b9a6a..b30fb8e6e1 100644 --- a/demux/demux_mpg.c +++ b/demux/demux_mpg.c @@ -523,7 +523,7 @@ static int demux_mpg_read_packet(demuxer_t *demux,int id){ if(!demux->s_streams[aid]){ sh_sub_t *sh = new_sh_sub(demux, aid); - if (sh) sh->type = 'v'; + if (sh) sh->gsh->codec = "dvd_subtitle"; mp_msg(MSGT_DEMUX,MSGL_V,"==> Found subtitle: %d\n",aid); } diff --git a/demux/demux_ts.c b/demux/demux_ts.c index ac23f0e71b..6d41dfd939 100644 --- a/demux/demux_ts.c +++ b/demux/demux_ts.c @@ -415,11 +415,11 @@ static void ts_add_stream(demuxer_t * demuxer, ES_stream_t *es) if (sh) { switch (es->type) { case SPU_DVB: - sh->type = 'b'; break; + sh->gsh->codec = "dvb_subtitle"; break; case SPU_DVD: - sh->type = 'v'; break; + sh->gsh->codec = "dvd_subtitle"; break; case SPU_PGS: - sh->type = 'p'; break; + sh->gsh->codec = "hdmv_pgs_subtitle"; break; } priv->ts.streams[es->pid].id = priv->last_sid; priv->ts.streams[es->pid].sh = sh; diff --git a/demux/stheader.h b/demux/stheader.h index 2fe1ac40c5..47dcf7a207 100644 --- a/demux/stheader.h +++ b/demux/stheader.h @@ -171,7 +171,6 @@ typedef struct sh_video { typedef struct sh_sub { SH_COMMON - char type; // t = text, v = VobSub, a = SSA/ASS, m, x, b, d, p bool active; // after track switch decoder may stay initialized, not active unsigned char *extradata; // extra header data passed from demuxer int extradata_len; @@ -189,8 +188,6 @@ struct sh_sub *new_sh_sub_sid_lang(struct demuxer *demuxer, int id, int sid, const char *lang); struct sh_stream *new_sh_stream(struct demuxer *demuxer, enum stream_type type); -const char *sh_sub_type2str(int type); - // video.c: int video_read_properties(struct sh_video *sh_video); int video_read_frame(struct sh_video *sh_video, float *frame_time_ptr, diff --git a/sub/dec_sub.c b/sub/dec_sub.c index 4e703e7dc0..d3cedea80d 100644 --- a/sub/dec_sub.c +++ b/sub/dec_sub.c @@ -30,17 +30,36 @@ extern const struct sd_functions sd_ass; extern const struct sd_functions sd_lavc; +bool is_text_sub(const char *t) +{ + return t && (is_ass_sub(t) || + strcmp(t, "text") == 0 || + strcmp(t, "subrip") == 0 || + strcmp(t, "mov_text") == 0); +} + +bool is_ass_sub(const char *t) +{ + return t && (strcmp(t, "ass") == 0 || + strcmp(t, "ssa") == 0); +} + +bool is_dvd_sub(const char *t) +{ + return t && strcmp(t, "dvd_subtitle") == 0; +} + void sub_init(struct sh_sub *sh, struct osd_state *osd) { struct MPOpts *opts = sh->opts; assert(!osd->sh_sub); + if (sd_lavc.probe(sh)) + sh->sd_driver = &sd_lavc; #ifdef CONFIG_ASS - if (opts->ass_enabled && is_text_sub(sh->type)) + if (opts->ass_enabled && sd_ass.probe(sh)) sh->sd_driver = &sd_ass; #endif - if (strchr("bpxv", sh->type)) - sh->sd_driver = &sd_lavc; if (sh->sd_driver) { if (sh->sd_driver->init(sh, osd) < 0) return; diff --git a/sub/dec_sub.h b/sub/dec_sub.h index f66f05c021..593eac1e03 100644 --- a/sub/dec_sub.h +++ b/sub/dec_sub.h @@ -10,10 +10,9 @@ struct sh_sub; struct ass_track; struct MPOpts; -static inline bool is_text_sub(int type) -{ - return type == 't' || type == 'm' || type == 'a'; -} +bool is_text_sub(const char *t); +bool is_ass_sub(const char *t); +bool is_dvd_sub(const char *t); void sub_decode(struct sh_sub *sh, struct osd_state *osd, void *data, int data_len, double pts, double duration); @@ -4,6 +4,7 @@ #include "dec_sub.h" struct sd_functions { + bool (*probe)(struct sh_sub *sh); 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); diff --git a/sub/sd_ass.c b/sub/sd_ass.c index 00f2f8d796..8d17835809 100644 --- a/sub/sd_ass.c +++ b/sub/sd_ass.c @@ -41,6 +41,11 @@ struct sd_ass_priv { bool flush_on_seek; }; +static bool probe(struct sh_sub *sh) +{ + return is_text_sub(sh->gsh->codec); +} + static void free_last_event(ASS_Track *track) { assert(track->n_events > 0); @@ -51,13 +56,14 @@ static void free_last_event(ASS_Track *track) static int init(struct sh_sub *sh, struct osd_state *osd) { 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->type == 'a') { + if (ass) { ctx->ass_track = ass_new_track(osd->ass_library); if (sh->extradata) ass_process_codec_private(ctx->ass_track, sh->extradata, @@ -66,7 +72,7 @@ static int init(struct sh_sub *sh, struct osd_state *osd) ctx->ass_track = mp_ass_default_track(osd->ass_library, sh->opts); } - ctx->vsfilter_aspect = sh->type == 'a'; + ctx->vsfilter_aspect = ass; return 0; } @@ -77,7 +83,7 @@ static void decode(struct sh_sub *sh, struct osd_state *osd, void *data, struct sd_ass_priv *ctx = sh->context; ASS_Track *track = ctx->ass_track; - if (sh->type == 'a') { // ssa/ass subs + if (is_ass_sub(sh->gsh->codec)) { if (bstr_startswith0((bstr){data, data_len}, "Dialogue: ")) { // broken ffmpeg ASS packet format ctx->flush_on_seek = true; @@ -177,6 +183,7 @@ static void uninit(struct sh_sub *sh) } const struct sd_functions sd_ass = { + .probe = probe, .init = init, .decode = decode, .get_bitmaps = get_bitmaps, @@ -199,7 +206,9 @@ struct sh_sub *sd_ass_create_from_track(struct ass_track *track, talloc_set_destructor(sh, sd_ass_track_destructor); *sh = (struct sh_sub) { .opts = opts, - .type = 'a', + .gsh = talloc_struct(sh, struct sh_stream, { + .codec = "ass", + }), .sd_driver = &sd_ass, .context = talloc_struct(sh, struct sd_ass_priv, { .ass_track = track, diff --git a/sub/sd_lavc.c b/sub/sd_lavc.c index e3f7af408a..1665e36749 100644 --- a/sub/sd_lavc.c +++ b/sub/sd_lavc.c @@ -22,6 +22,7 @@ #include "talloc.h" #include "core/mp_msg.h" +#include "core/av_common.h" #include "demux/stheader.h" #include "sd.h" #include "dec_sub.h" @@ -40,9 +41,24 @@ struct sd_lavc_priv { double endpts; }; -static void guess_resolution(char type, int *w, int *h) +static bool probe(struct sh_sub *sh) { - if (type == 'v') { + enum AVCodecID cid = mp_codec_to_av_codec_id(sh->gsh->codec); + // Supported codecs must be known to decode to paletted bitmaps + switch (cid) { + case AV_CODEC_ID_DVB_SUBTITLE: + case AV_CODEC_ID_HDMV_PGS_SUBTITLE: + case AV_CODEC_ID_XSUB: + case AV_CODEC_ID_DVD_SUBTITLE: + return true; + default: + return false; + } +} + +static void guess_resolution(enum AVCodecID type, int *w, int *h) +{ + if (type == AV_CODEC_ID_DVD_SUBTITLE) { /* XXX Although the video frame is some size, the SPU frame is always maximum size i.e. 720 wide and 576 or 480 high */ // For HD files in MKV the VobSub resolution can be higher though, @@ -65,17 +81,7 @@ static int init(struct sh_sub *sh, struct osd_state *osd) if (sh->initialized) return 0; struct sd_lavc_priv *priv = talloc_zero(NULL, struct sd_lavc_priv); - enum AVCodecID cid = AV_CODEC_ID_NONE; - switch (sh->type) { - case 'b': - cid = AV_CODEC_ID_DVB_SUBTITLE; break; - case 'p': - cid = AV_CODEC_ID_HDMV_PGS_SUBTITLE; break; - case 'x': - cid = AV_CODEC_ID_XSUB; break; - case 'v': - cid = AV_CODEC_ID_DVD_SUBTITLE; break; - } + enum AVCodecID cid = mp_codec_to_av_codec_id(sh->gsh->codec); AVCodecContext *ctx = NULL; AVCodec *sub_codec = avcodec_find_decoder(cid); if (!sub_codec) @@ -194,7 +200,7 @@ static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd, talloc_get_size(priv->inbitmaps)); int inw = priv->avctx->width; int inh = priv->avctx->height; - guess_resolution(sh->type, &inw, &inh); + guess_resolution(priv->avctx->codec_id, &inw, &inh); double xscale = (double) (d.w - d.ml - d.mr) / inw; double yscale = (double) (d.h - d.mt - d.mb) / inh; for (int i = 0; i < priv->count; i++) { @@ -235,6 +241,7 @@ static void uninit(struct sh_sub *sh) } const struct sd_functions sd_lavc = { + .probe = probe, .init = init, .decode = decode, .get_bitmaps = get_bitmaps, |