summaryrefslogtreecommitdiffstats
path: root/sub
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 /sub
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.
Diffstat (limited to 'sub')
-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
5 files changed, 60 insertions, 25 deletions
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,