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.
This commit is contained in:
wm4 2014-03-04 00:28:10 +01:00
parent 43e997ca07
commit 5606cf2948
4 changed files with 21 additions and 10 deletions

View File

@ -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: {

View File

@ -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);

View File

@ -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

View File

@ -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;