17
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ネクストスケープ 配信事業本部Advent Calendar 2016

Day 2

H.264のmp4のキーフレーム間隔をmp4boxを使って知る

Last updated at Posted at 2016-12-01

何と言うか

キーフレームの間隔が分かったから何なんだ、と言う気がしないでもないですが、動画配信の仕事をしていると
年に2~3回はキーフレームの間隔を調べている気がするので、小ネタとして残しておきます。

mp4boxを使う

こんなコマンドを叩きます。

mp4box -dts some.mp4

すると、some_ts.txtと言う名前のファイルが出力されるのでそれを開きます。

#dumping track ID 1 timing:
Num			DTS			CTS			Size	RAP	Offset	isLeading	DependsOn	DependedOn	Redundant	RAP-SampleGroup	Roll-SampleGroup	Roll-Distance
Sample 1	DTS 0		CTS 0		1659	1	128407	0			0			0			0			0				0					0
Sample 2	DTS 1001	CTS 1001	476		0	130066	0			0			0			0			0				0					0
Sample 3	DTS 2002	CTS 2002	208		0	130542	0			0			0			0			0				0					0
Sample 4	DTS 3003	CTS 3003	167		0	130750	0			0			0			0			0				0					0
                                       ・
                                       ・
                                       ・
Sample 55	DTS 54054	CTS 54054	7228	0	453175	0			0			0			0			0				0					0
Sample 56	DTS 55055	CTS 55055	8792	0	460403	0			0			0			0			0				0					0
Sample 57	DTS 56056	CTS 56056	9341	0	469195	0			0			0			0			0				0					0
Sample 58	DTS 57057	CTS 57057	8719	0	485898	0			0			0			0			0				0					0
Sample 59	DTS 58058	CTS 58058	8430	0	494617	0			0			0			0			0				0					0
Sample 60	DTS 59059	CTS 59059	8284	0	503047	0			0			0			0			0				0					0
Sample 61	DTS 60060	CTS 60060	18047	1	511331	0			0			0			0			0				0					0
Sample 62	DTS 61061	CTS 61061	9091	0	529378	0			0			0			0			0				0					0
Sample 63	DTS 62062	CTS 62062	8669	0	538469	0			0			0			0			0				0					0
Sample 64	DTS 63063	CTS 63063	8897	0	547138	0			0			0			0			0				0					0
                                       ・
                                       ・
                                       ・
Sample 117	DTS 116116	CTS 116116	5087	0	1170777	0			0			0			0			0				0					0
Sample 118	DTS 117117	CTS 117117	4568	0	1175864	0			0			0			0			0				0					0
Sample 119	DTS 118118	CTS 118118	4550	0	1180432	0			0			0			0			0				0					0
Sample 120	DTS 119119	CTS 119119	4547	0	1184982	0			0			0			0			0				0					0
Sample 121	DTS 120120	CTS 120120	32371	1	1189529	0			0			0			0			0				0					0
Sample 122	DTS 121121	CTS 121121	1740	0	1221900	0			0			0			0			0				0					0
Sample 123	DTS 122122	CTS 122122	3630	0	1223640	0			0			0			0			0				0					0
Sample 124	DTS 123123	CTS 123123	4245	0	1227270	0			0			0			0			0				0					0
                                       ・
                                       ・
                                       ・

ファイルの中身はこんな感じです。各sampleのDTSやCTS、サイズなのが一覧できます。

一覧を眺める

各行のRAP列に注目します。RAPはRandom Access Pointの略で、要は動画再生時にシークを行った際に再生される箇所です。
このRAP列に1が立っているSampleがキーフレームです。と言う事で、RAP列に1が立ったsampleのDTSの間隔がキーフレーム間隔になります。

Sample 1	DTS 0		CTS 0		1659	1	128407	0	0	0	0	0	0	0
Sample 61	DTS 60060	CTS 60060	18047	1	511331	0	0	0	0	0	0	0
Sample 121	DTS 120120	CTS 120120	32371	1	1189529	0	0	0	0	0	0	0
Sample 181	DTS 180180	CTS 180180	21589	1	1525255	0	0	0	0	0	0	0
Sample 241	DTS 240240	CTS 240240	22444	1	1863545	0	0	0	0	0	0	0
Sample 301	DTS 300300	CTS 300300	28871	1	2082679	0	0	0	0	0	0	0
Sample 361	DTS 360360	CTS 360360	23859	1	2504712	0	0	0	0	0	0	0
Sample 421	DTS 420420	CTS 420420	29967	1	3031985	0	0	0	0	0	0	0
Sample 481	DTS 480480	CTS 480480	32377	1	3386185	0	0	0	0	0	0	0
Sample 541	DTS 540540	CTS 540540	32139	1	3677139	0	0	0	0	0	0	0
Sample 601	DTS 600600	CTS 600600	31110	1	4110642	0	0	0	0	0	0	0

キーフレームのSampleだけを幾つか抜粋してみるとこんな感じです。
きれいに60Sampleずつ、DTSが60060ずつの差になっていますね。動画配信に適したエンコードがされている様子です。

この一覧のDTSは秒ではなく、タイムスケールをベースにしたタイムスタンプなのでタイムスケールで割ってあげると秒になります。
このmp4の映像トラックのタイムスケールは30000なので、60060 ÷ 30000 = 2.002 となり、このmp4のキーフレーム間隔は約2秒となります。

別のアプローチとして

ここまではmp4boxを使ってキーフレーム間隔を調べましたが、mp4をバイナリエディタで開いて「ふむふむ、ナルホドー」と
mp4 Parsable EYEを持つ方なら、mp4の内容からキーフレーム間隔を調べることが可能です。

先程の、RAP列に1が立ったSampleの番号は、Sync Smple Box (stss) に保存されています。
ISO/IEC 14496-12の仕様で言うと

aligned(8) class SyncSampleBox extends FullBox(‘stss’, version = 0, 0) {
  unsigned int(32) entry_count;
  int i;
  for (i=0; i < entry_count; i++) {
    unsigned int(32) sample_number;
  }
}

のsample_numberがそれに当たります。
で、1sample当たりのDTSについては、Decoding Time to Sample Box (stts) に保存されています。

aligned(8) class TimeToSampleBox extends FullBox(’stts’, version = 0, 0) {
  unsigned int(32) entry_count;
  int i;
  for (i=0; i < entry_count; i++) {
    unsigned int(32) sample_count
    unsigned int(32) sample_delta;
  }
}

のsample_deltaがそれに当たります。sttsには仕様上entryを複数持つことが可能ですが、大抵の場合は1つなので
使用するsample_deltaも1つです。複数ある場合は、そのsample_deltaを適用するsampleの数がsample_countに保存されているので
sampleとsample_deltaの組合わせは一目で分かるようになっています。

タイムスケールは、Media Header Box (mdhd) のtimescaleに保存されているので、それらを使っての計算を

int i;
double[] keyframe_durations = double[stss.entry_count - 1];
for (i=0; i < stss.entry_count - 1; i++)
  int sampleCount = stss.entry[i+1].sample_number - stss.entry[i].sample_number;
  keyframe_durations = sampleCount * stts.entry[0].sample_delta / mdhd.timascale;
}

適当にコードにするとこんな感じでしょうか。
今回使用しているmp4を見てみると、

mdhd.timesclae = 30000
stss.entry_count = 30
stss.sample_number = 1, 61, 121, 181, 241, 301 ....
stts.entry_count = 1
stts.entry[0].sample_count = 1800
stts.entry[0].sample_delta = 1001

なので、
最初のキーフレームと次のキーフレームの間のsample数は、61 - 1 = 60
1sampe当たりのdeltaは1001なので60sampleだとDTSは、60 * 1001 = 60060
timescaleは30000なのでキーフレームの間隔は、60060 / 30000 = 2.002 秒
となり、mp4boxで調べた場合と同じ結果になります。

以上のように、mp4 Parsableな目を持つ方ならmp4boxを使用せずともキーフレーム間隔を知ることが出来ます。

17
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?