oggのページヘッダを表示してみる
某ゲームのBGMを切り出すついでに、oggフォーマットについて調べてみたのでほんの少しだけメモ。
- OggフォーマットはRFC3533に記述されてる
- ページと呼ばれる単位に分かれている
- ページが連なってひとつのストリームになっている
- 開始ページ(bos = begining of stream)で始まって、終了ページ(eos = end of stream)で終わる
- header_typeはbitで管理されている
- 開始ページは0x02の位置のbitがsetされているページ
- 終了ページは0x04の位置のbitがsetされているページ
- bitstream_serial_numberはストリームに固有の番号が割り振られている
- page_sequence_numberはページの欠損・順序の識別のためのシーケンス番号
#!/usr/bin/perl # print_ogg_header.pl, v 0.1, hiyokomanjiu, 2010/7/19 use strict; use warnings; my $filename = $ARGV[0] if $#ARGV >= 0; open( my $oggfile, $filename ) or die "Can't open file " . $ARGV[0]; binmode $oggfile; my $buf; while( read( $oggfile, $buf, 4 ) ) { if( $buf =~ /OggS/ ) { my $capture_pattern = $buf; my ($version, $header_type, $granule_position, $bitstream_serial_number, $page_sequence_number, $crc_checksum, $number_page_segments, $segment_table, $stream_data); read( $oggfile, $version, 1 ); read( $oggfile, $header_type, 1 ); read( $oggfile, $granule_position, 8 ); read( $oggfile, $bitstream_serial_number, 4 ); read( $oggfile, $page_sequence_number, 4 ); read( $oggfile, $crc_checksum, 4 ); read( $oggfile, $number_page_segments, 1 ); read( $oggfile, $segment_table, unpack("C", $number_page_segments) ); my $data_size = 0; for( my $i = 0; $i < unpack("C", $number_page_segments); $i++ ) { $data_size += unpack("C", substr($segment_table, $i)); } read( $oggfile, $stream_data, $data_size ); printf( "version: %d\n", unpack("C", $version) ); printf( "header type: %02X\n", unpack("C", $header_type) ); printf( "granule position: %d\n", unpack("i", $granule_position) ); printf( "bitstream serial number: %d\n", unpack("i", $bitstream_serial_number) ); printf( "page sequence number: %d\n", unpack("i", $page_sequence_number) ); printf( "number page segments: %d\n", unpack("C", $number_page_segments) ); printf( "data_size: %d\n\n", $data_size ); }else{ die "This file isn't ogg format\n"; } } close $oggfile;