summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-04-15 21:25:21 +0200
committerwm4 <wm4@nowhere>2013-04-20 23:28:27 +0200
commit331982b99ce3b50b95ac340eb17c6116913480f3 (patch)
treeb0e0c14521f509a883c0420d9e6277c0329eb773
parent5ac50f88c90167e9ade0c998ac62e935e259acee (diff)
downloadmpv-331982b99ce3b50b95ac340eb17c6116913480f3.tar.bz2
mpv-331982b99ce3b50b95ac340eb17c6116913480f3.tar.xz
sub, demux: identify subtitle types with the codec name
Get rid of the 1-char subtitle type field. Use sh_stream->codec instead just like audio and video do. Use codec names as defined by libavcodec for simplicity, even if they're somewhat verbose and annoying. Note that ffmpeg might switch to "ass" as codec name for ASS, so we don't bother with the current silly "ssa" name.
-rw-r--r--core/mplayer.c14
-rw-r--r--demux/demux.c15
-rw-r--r--demux/demux_lavf.c21
-rw-r--r--demux/demux_mkv.c37
-rw-r--r--demux/demux_mpg.c2
-rw-r--r--demux/demux_ts.c6
-rw-r--r--demux/stheader.h3
-rw-r--r--sub/dec_sub.c25
-rw-r--r--sub/dec_sub.h7
-rw-r--r--sub/sd.h1
-rw-r--r--sub/sd_ass.c17
-rw-r--r--sub/sd_lavc.c35
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);
diff --git a/sub/sd.h b/sub/sd.h
index 29f021ab5e..881c429689 100644
--- a/sub/sd.h
+++ b/sub/sd.h
@@ -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,