From 5606cf29482b096df7a6b4b515c9ecb3d40fdf89 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 4 Mar 2014 00:28:10 +0100 Subject: sub: use new FFmpeg API to check MicroDVD FPS Before this, it wasn't possible to distinguish MicroDVD subtitles without FPS header, and subtitles with FPS header equal to FFmpeg's fallback FPS. --- demux/demux_lavf.c | 18 +++++++++++++----- demux/demux_subreader.c | 2 +- demux/stheader.h | 3 ++- sub/dec_sub.c | 8 +++++--- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index d85e4b8095..cc503383ea 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -461,11 +461,19 @@ static void handle_stream(demuxer_t *demuxer, int i) sh_sub->w = codec->width; sh_sub->h = codec->height; - // Hack for MicroDVD: if time_base matches the ffmpeg microdvd reader's - // default FPS (23.976), assume the MicroDVD file did not declare a - // FPS, and the MicroDVD file uses frame based timing. - if (codec->time_base.num == 125 && codec->time_base.den == 2997) - sh_sub->frame_based = true; + if (matches_avinputformat_name(priv, "microdvd")) { + AVRational r; + if (av_opt_get_q(avfc, "subfps", AV_OPT_SEARCH_CHILDREN, &r) >= 0) { + // File headers don't have a FPS set. + if (r.num < 1 || r.den < 1) + sh_sub->frame_based = av_q2d(av_inv_q(codec->time_base)); + } else { + // Older libavcodec versions. If the FPS matches the microdvd + // reader's default, assume it uses frame based timing. + if (codec->time_base.num == 125 && codec->time_base.den == 2997) + sh_sub->frame_based = 23.976; + } + } break; } case AVMEDIA_TYPE_ATTACHMENT: { diff --git a/demux/demux_subreader.c b/demux/demux_subreader.c index 1fa449d7f0..d72cc209c9 100644 --- a/demux/demux_subreader.c +++ b/demux/demux_subreader.c @@ -1361,7 +1361,7 @@ static int d_open_file(struct demuxer *demuxer, enum demux_check check) p->sh = new_sh_stream(demuxer, STREAM_SUB); p->sh->codec = sd->codec; - p->sh->sub->frame_based = !sd->sub_uses_time; + p->sh->sub->frame_based = sd->sub_uses_time ? 0 : 23.976; p->sh->sub->is_utf8 = sr.args.utf16 != 0; // converted from utf-16 -> utf-8 add_sub_data(demuxer, sd); diff --git a/demux/stheader.h b/demux/stheader.h index 177bf50b39..573d6ac3c6 100644 --- a/demux/stheader.h +++ b/demux/stheader.h @@ -88,7 +88,8 @@ typedef struct sh_sub { unsigned char *extradata; // extra header data passed from demuxer int extradata_len; int w, h; // mp4 vobsubs - int frame_based; // timestamps are frame-based + double frame_based; // timestamps are frame-based (and this is the + // fallback framerate used for timestamps) bool is_utf8; // if false, subtitle packet charset is unknown struct ass_track *track; // loaded by libass struct dec_sub *dec_sub; // decoder context diff --git a/sub/dec_sub.c b/sub/dec_sub.c index fdb8d8f648..0a62e52a15 100644 --- a/sub/dec_sub.c +++ b/sub/dec_sub.c @@ -464,9 +464,11 @@ bool sub_read_all_packets(struct dec_sub *sub, struct sh_stream *sh) double sub_speed = 1.0; - // 23.976 FPS is used as default timebase for frame based formats - if (sub->video_fps && sh->sub->frame_based) - sub_speed *= 23.976 / sub->video_fps; + if (sub->video_fps && sh->sub->frame_based > 0) { + MP_VERBOSE(sub, "Frame based format, dummy FPS: %f, video FPS: %f\n", + sh->sub->frame_based, sub->video_fps); + sub_speed *= sh->sub->frame_based / sub->video_fps; + } if (opts->sub_fps && sub->video_fps) sub_speed *= opts->sub_fps / sub->video_fps; -- cgit v1.2.3