ドライブレコーダーのデータ解析をした話


初めに

IoTLT Advent Calendar 2021 に投稿した記事です。ここでは、私が主催してます KURUMA IoTLT で発表した内容を書き起こしました。

ここで解析した内容の正確性につきましては保証できませんので、引用する際にはご注意くださいますようお願いいたします。

KURUMA IoTLT は、車とIoTの組合せをテーマにしたLightning Talkの発表会です。一般的にIoTはインターネットに繋がった物( Internet of Things )を指しますが、自動車のコネクテッド化は現段階ではまだまだ進んでいない状況ですので、 Internet or Things としています。ですので、インターネットに繋がっていないマイコンでもいいですし、スマホアプリのようにモノの要素が無いテーマでもウェルカムです。

ドライブレコーダーに記録されているデータについて

世の中には様々な種類のドライブレコーダーが販売されています。カメラで映像を記録するだけでなくGPSやGセンサーが搭載されているものもあり、これらのデータを専用のソフトウェアを使って表示したり、映像に表示させることが可能となってます。

なお、業務用のドライブレコーダーにはウィンカーの作動状況やハンドル操作など車両からの情報も記録するような高度な機器も存在しますが、本記事では扱いません。一般的な家庭用レベルの機器を前提として話をすすめます。

GPS (Global Positioning System)

今いる場所を把握するためのモジュールで、スマートフォンやカーナビ等にも搭載されている身近な存在となってます。正確には GNSS (Global Navigation Satellite System: 全球測位衛星システム)と言わなければならないのですが、Geolocation方面ではない人にとっては「GPS」という方が馴染み深いと思うので、ここでは敢えてGPSと表記しています。

GPSモジュールからは次のデータが取得できます。ただし下3つ(高度、進行方向、位置情報の精度)に関しては映像記録の観点では不要となることから、記録されない機種も存在します。

データ名 利用目的
緯度経度 映像を記録した場所を地図に表示するため
時刻 映像を撮影した時刻を記録するため
速度 映像を記録した時点の走行速度を記録するため
高度 走行した場所の標高を記録するため
進行方向 どの方向に向かって走行していたかを把握するため
位置情報の精度 GPSから得られた緯度経度の正確性を把握するため

Gセンサー

Gは重力(Gravity)です。「加速度センサー」や「IMU」と呼ばれることがあります。スマートフォンにも同様のセンサーがあり、重力方向を検知して画面の向きを変えるのに使用されますが、車にGセンサーを取り付けた場合は車が何かにぶつかった時の衝撃検知や、道路の凹凸検知、運転操作の滑らかさ(急の付く操作を行ってないか)の判定に使われます。

機種により1秒間に1~10サンプルと幅があり精度が異なることや、ドアの開閉や手や小物がぶつかった時の衝撃によるノイズ成分などで信頼性としては高くないデータとなります。

解析した機種

今回見ていくデータの機種は Pioneer VREC-DH300D です。この機種を選んだ理由はもちろんGPSとGセンサーの搭載は前提としてますが、Pioneerの この機種だけなぜかPC用アプリが非対応 だったので、どんな状況なのかを知りたくて調査の目的として選びました。

Pioneer ドライブレコーダー 主な機能比較表
https://jpn.pioneer/ja/carrozzeria/recorder_sd/list/

Pioneer VREC-DH300Dの仕様

解析に関係する所だけ (映像の良し悪しには触れない為) ですが、ドライブレコーダーの仕様をまとめました。

項目 備考
カメラ数 2カメラ(前後) 前:WQHD、後:Full HD
動画形式 H.264(MP4) / H.265(MOV) 初期状態はH.264でした。変更せずに使ってます
microSD容量 16 ~ 128GB 出来るだけ多くのデータを残すために256GBを使ってます(自己責任で)
音声録音 ON / OFF 音声は記録するようにしています
GPS 搭載 GLONASS、みちびきの対応は不明(恐らく非対応)
Gセンサー 3軸センサー搭載
動画ファイル長さ 1分 / 3分 3分のファイルを解析対象としてます

解析する

解析の前段階として、まずはドライブレコーダーを動かしてみて、microSDに書き込まれるファイルとディレクトリ構造を確認します。

ディレクトリ構造とファイル

microSDの中身を確認すると、最上位には EventVideo の2つのディレクトリのみとなってました。一応、隠しファイルも確認してますが存在してません。

Event は強い衝撃が加わった時に記録されるディレクトリで、 Video は通常時の映像が入っていくディレクトリです。怪しい所は見当たりません。

Video ディレクトリを見ると、MP4の動画ファイルが格納されているだけでした。Pioneerの他の機種では nmea という拡張子のファイルが存在して、GPSモジュールが出しているテキストをそのまま書き出しているようだったのですが、VREC-DH300Dは異なるようです。

前後のカメラで ... A.MP4... B.MP4 と別のファイルとなってました。

MP4ファイルの構造

MP4ファイルしか存在しないとの事なので、MP4ファイルの中を見ていきます。

MP4(MPEG4)の仕様

ここでは大雑把な説明にとどめておきます。大元の仕様はISOで定義されており「ISO_IEC 14496」で検索すれば色々出てくると思います。

MP4ファイルはBOXと呼ばれるデータ領域の集まりとなってます。先頭4バイトでBOXの大きさを示し、続いて4バイトで FourCC と言う4文字のアスキーで何のデータが入っているかを表します。その後にデータ本体(Payload)が続きます。

image.png

Payloadの中に、更に別のBOXが入って親子関係になる場合もあります。これによって階層構造を作り出しています。

FourCCについてはApple QuickTimeのドキュメントにも詳しく出ています。

なぜAppleなのかと疑問に思う人がいるかもしれませんが、元々Appleが作っていたQuickTimeフォーマットが後にMPEG4としてISOで標準化された経緯があるためです。ちなみにドライブレコーダーにもMOV(Quick Time)形式で書き出す機種もありますが、ファイル構造においてはMP4と同じです。ただし、「BOX」の事を、QuickTimeでは「ATOM」と呼ぶ点が異なります。ドキュメントを見る際にはお気を付けください。

VREC-DH300Dの動画ファイルで変わっている所

解析を進めるにはBOXを調べていけばいいのですが、一般的な動画ファイルとVREC-DH300Dが書き出す動画ファイルで変わった点が無いか見ていきます。

見慣れないFourCCやBOXの外のデータ

MP4の規格にないFourCCやSizeで指定してる領域の外に余分なデータを付けている可能性を疑ってみましたが、見慣れないFourCCは無く、Sizeからはみ出しているデータは存在しませんでした。

一見すると、VREC-DH300Dが書き出すファイルは規格に沿っている、まともなMP4ファイルに見えます。

見慣れないトラック

ffprobeで確認すると3つのストリームがあり、3番目にメタデータのトラックが存在してました。

ffprobeの実行結果
$ ffprobe 2021_07_18_165224_A.MP4 
ffprobe version N-98670-g8d48e8d Copyright (c) 2007-2020 the FFmpeg developers
  built with gcc 9.3.0 (GCC)
  configuration: --prefix=/usr --libdir=/usr/lib64 --shlibdir=/usr/lib64 --disable-debug --enable-shared --enable-pic --enable-gpl --enable-version3 --enable-nonfree --enable-doc --enable-ffmpeg --disable-ffplay --disable-avisynth --enable-gray --enable-avdevice --enable-avcodec --enable-avformat --enable-avfilter --enable-postproc --enable-bzlib --enable-fontconfig --enable-libcelt --enable-swresample --enable-swscale --disable-libopencore-amrnb --disable-libopencore-amrwb --disable-libopencv --disable-libdc1394 --enable-libfdk-aac --enable-libfreetype --enable-libgsm --enable-libmp3lame --enable-libopenjpeg --enable-librtmp --enable-libspeex --enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --disable-libxavs --enable-zlib
  libavutil      56. 58.100 / 56. 58.100
  libavcodec     58.100.100 / 58.100.100
  libavformat    58. 50.100 / 58. 50.100
  libavdevice    58. 11.101 / 58. 11.101
  libavfilter     7. 87.100 /  7. 87.100
  libswscale      5.  8.100 /  5.  8.100
  libswresample   3.  8.100 /  3.  8.100
  libpostproc    55.  8.100 / 55.  8.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '2021_07_18_165224_A.MP4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: mp42isom
    creation_time   : 2021-07-18T07:52:24.000000Z
  Duration: 00:03:00.00, start: 0.000000, bitrate: 11184 kb/s
    Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuvj420p(pc, bt709), 2560x1440, 10848 kb/s, 27 fps, 27 tbr, 108k tbn, 216k tbc (default)
    Metadata:
      creation_time   : 2021-07-18T07:52:24.000000Z
      handler_name    : ?Hisilicon VIDEO
    Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, mono, fltp, 125 kb/s (default)
    Metadata:
      creation_time   : 2021-07-18T07:52:24.000000Z
      handler_name    : ?Hisilicon AUDIO
    Stream #0:2(eng): Data: bin_data (gpmd / 0x646D7067), 44 kb/s (default)
    Metadata:
      creation_time   : 2021-07-18T07:52:24.000000Z
      handler_name    : ?Hisilicon MetaData
Unsupported codec with id 100359 for input stream 2

通常は映像で音声で2ストリームですので、メタデータとしてGPSとGセンサーのデータを格納している可能性が出てきました。

3番目のトラックからデータを抜き出す

ffprobeの出力に Data: bin_data (gpmd / 0x646D7067) という記述があったので gpmd とは何だろうと調べて、GoPro等で使われる周期的なセンサーのデータを格納する方法にたどり着きました。パーサーもあるようでここの情報とVREC-DH300Dのファイルを見ていきました。

調べた所、メタデータはGPMDの形式ではなさそうでした。

調査にあたって色々あったような気がするのですが細かい経緯は忘れました。メタデータストリームの stbl (Sample Table) の中の stco (Chunk Offset) のデータを読み取って、 276バイト の領域が 180(偶に181)個 存在するのを見つけました。

この数からすると、1秒間のデータが格納されていると想定されます。また、Chunk Offsetが示す 0x2A6832 アドレスから276バイト分を見てみると、「FMAS」という文字列から「DATEETAD」で終わる領域で規則性がありました。

最終的に、この276バイトの領域を読み解いて行ってデータを得ることができました。データを1つ見ていきます

その時に映像に埋め込まれた値は以下です

時刻

時刻データは 0x60 から 0x66 の範囲

0x60 0x61 0x62 0x63 0x64 0x65 0x66
E5 07 0B 1A 0E 01 29
  • 年はリトルエンディアン
    • 0x07E5 → 2021
  • 時刻は日本時刻 (本体設定で変わるのかは未確認)

となり、 2021年11月26日 14時01分29秒 が取得できました

Gセンサー

Gセンサーは 0x6C から 0x77 の範囲です

1軸当たり4バイトと仮定して16進数をFloatに直してみます。

console.log(Buffer.from([0x0d, 0x34, 0xd0, 0xbc]).readFloatLE(0));
console.log(Buffer.from([0x59, 0x63, 0x8d, 0x3f]).readFloatLE(0));
console.log(Buffer.from([0x09, 0x22, 0x88, 0xbd]).readFloatLE(0));

// 実行結果
-0.025415444746613503
1.104594349861145
-0.066471166908741

ドラレコの内部でどの向きにGセンサーが付けられているかでXYZの方向は変わりますが、1に近い値が重力方向で1Gに近い値が出ているように見えます。

Gセンサーの値は映像には書かれていないので、この結果があっているのかは不明です。

緯度経度

Gセンサーの後に AEN という文字列があり、その後 0x7b から 0x83 までが緯度経度です

  • 経度の"分"が2桁なのは、理由は分かりません
  • 秒の若干のズレは、動画の埋め込みとメタデータの書き込みの間でタイムラグが生じている可能性を疑ってます
  • AENEN は恐らく East(東経) と North(北緯) を表しているような気がします

速度

0x84 に速度が入り、 3C → 60km/h となります

最後に

KURUMA IoTでは4輪自動車に限らず、もちろん2輪でも、更には車とは呼べなくても自分で操る動力機関を持って移動するための物まで幅広いテーマを扱っています。もし興味が沸いた方がおりましたら定期的に(3ヶ月間隔を目標に)開催しようと思っていますので、ご参加をお待ちしております。