24000:1001

最近のx264とmp4boxでいくつか24fpsなmp4を作ってみると、TimeScaleが上手く23976にならなかったので、何故なのか調べてみた。

素材
DVDをDGIndexで読み込んで、TIVTCで24fps化したもの。
24000(frames), 1001.000(sec), 23.9760(fps)
ツール
x264 rev.522
mp4box 20060505版
mp4 TimeScale frames sec fps(frames/sec)
x264(--fps 23.9760)→mp4 24000 24000 1001.000 23.9760239760
h264 raw→mp4box(-fps 23.977)→mp4 23977 24000 1000.959 23.9770060511
h264 raw→mp4box(-fps 23.976)→mp4 24000 24000 1001.000 23.9760239760
h264 raw→mp4box(-fps 23.975)→mp4 23975 24000 1001.042 23.9750180312
h264 raw→mp4box(-fps 24.000)→mp4 24000 24000 1000.000 24.0000000000
  • fps=23.976以外を指定した場合はTimeScaleはfpsを1000倍した数値になる
  • オプションでfps=23.976を指定した場合はTimeScaleは24000になる
  • fps=23.976ではTimeScaleが24000に変化するが、長さがちょうど1001秒となりNTSC的には正確!

どうやら、fps=23.976が指定された場合、これはNTSCの24000:1001のことだとGPACが認識してくれて、fps*1000という単純なタイムスケール算出をしなくなるらしい。

ということでGPACを調べてみたら、該当部分のソースコードはこんな感じでした。

static void get_video_timing(Double fps, u32 *timescale, u32 *dts_inc)
{
        u32 fps_1000 = (u32) (fps*1000 + 0.5);
        /*handle all drop-frame formats*/
        if (fps_1000==29970) {
                *timescale = 30000;
                *dts_inc = 1001;
        }
        else if (fps_1000==23976) {
                *timescale = 24000;
                *dts_inc = 1001;
        }
        else if (fps_1000==59940) {
                *timescale = 60000;
                *dts_inc = 1001;
        } else {
                *timescale = fps_1000;
                *dts_inc = 1000;
        }
}