我有一个OEM dashcam,可以保存.MOV格式的视频。我想以编程方式从视频文件中提取嵌入的gps数据。在十六进制编辑器中打开.mov文件后,我发现了带有freeGPS
标头的数据包,我可以确认,对于我的7秒样本视频,有7个数据包,所以我知道gps数据的来源。
我已经找到了日期和时间但是我仍然坚持将十六进制值转换为纬度经度。下面是使用Registrator Viewer提取时的十六进制值及其等效坐标。
273108AC1C7996 404E ,0D022B873EA3C7 4045 - 14.637967,121.041475 516B9A771C7996 404E ,0D022B873EA3C7 4045 - 14.637963,121.041475 B9FC87F41B7996 404E ,52499D803EA3C7 4045 - 14.637955,121.041472 B9FC87F41B7996 404E ,52499D803EA3C7 4045 - 14.637955,121.041472 B459F5B91A7996 404E ,C442AD693EA3C7 4045 - 14.637935,121.041460 1DEBE2361A7996 404E ,ACADD85F3EA3C7 4045 - 14.637927,121.041455 08CE19511A7996 404E ,4FD1915C3EA3C7 4045 - 14.637928,121.041453
粗体字节直接转换为@N和@E,所以我认为它们不是转换的一部分。我已经尝试了以下答案,但我没有成功获得正确的坐标。
How to convert GPS Longitude and latitude from hex
How to convert my binary (hex) data to latitude and longitude?
我已经向dashcam提供商发送了一封电子邮件,询问他们的协议文档,但是当我要求他们自己的视频播放器时,他们发送了Registrator Viewer,看起来他们看起来并不像。
我还会包含第一个freeGPS
数据包,以防我查看错误的地方。
粗体数据按顺序提取:freeGPS,时间,纬度@ N ?,经度@ E ?,日期
我可以确认时间和日期是正确的。速度应该是1km / h,但我也找不到。
提前感谢那些可以提供帮助的人。
编辑: 这是测试视频的链接。 Test Video
答案 0 :(得分:5)
不确定这有多大帮助,但是如果你将十六进制字符串(包括末尾的0x40)转换为一个小尾数IEEE-754双精度实数,那么你得到的纬度/经度约为100倍。
在C中,我做了类似
的事情printf( "%f\n", *(double*)"\x27\x31\x08\xAC\x1C\x79\x96\x40" );
printf( "%f\n", *(double*)"\x0D\x02\x2B\x87\x3E\xA3\xC7\x40" );
然后出去了
1438.278000
12102.488500
如果将1438.278
解释为14度38.278分钟,则会得到小数值14.6379666666666667
。如果12102.4885
被解释为121度和2.4885分钟,则十进制等值为121.041475
。
执行此操作的一些示例C代码
#include<stdio.h>
double convert( double input ) {
int i = input/100;
return ( input - i*100 ) / 60 + i;
}
int main(){
printf( "%f\n", convert( *(double*)"\x27\x31\x08\xAC\x1C\x79\x96\x40" ) );
printf( "%f\n", convert( *(double*)"\x0D\x02\x2B\x87\x3E\xA3\xC7\x40" ) );
}
答案 1 :(得分:0)
找到this对GPS数据格式的解释,对我有用。
public static ViofoGpsPoint Parse(uint offset, uint size, byte[] file)
{
byte[] data = new byte[size];
Array.Copy(file, offset, data, 0, size);
uint pos = 0;
uint size1 = Box.ReadUintBE(data, pos); pos += 4;
string type = Encoding.ASCII.GetString(data, (int)pos, 4); pos += 4;
string magic = Encoding.ASCII.GetString(data, (int)pos, 4); pos += 4;
if (size != size1 || type != "free" || magic != "GPS ")
return null;
ViofoGpsPoint gps = new ViofoGpsPoint();
//# checking for weird Azdome 0xAA XOR "encrypted" GPS data.
//This portion is a quick fix.
uint payload_size = 254;
if (data[pos] == 0x05)
{
if (size < 254)
payload_size = size;
byte[] payload = new byte[payload_size];
pos += 6; //???
for (int i = 0; i < payload_size; i++)
{
payload[i] = (byte)(file[pos + i] ^ 0xAA);
}
}
else if ((char)data[pos] == 'L')
{
const uint OFFSET_V2 = 48, OFFSET_V1 = 16;
pos = OFFSET_V2;
//# Datetime data
int hour = (int)Box.ReadUintLE(data, pos); pos += 4;
int minute = (int)Box.ReadUintLE(data, pos); pos += 4;
int second = (int)Box.ReadUintLE(data, pos); pos += 4;
int year = (int)Box.ReadUintLE(data, pos); pos += 4;
int month = (int)Box.ReadUintLE(data, pos); pos += 4;
int day = (int)Box.ReadUintLE(data, pos); pos += 4;
try { gps.Date = new DateTime(2000 + year, month, day, hour, minute, second); }
catch (Exception err) { Debug.WriteLine(err.ToString()); return null; }
//# Coordinate data
char active = (char)data[pos]; pos++;
gps.IsActive = (active == 'A');
gps.Latitude_hemisphere = (char)data[pos]; pos++;
gps.Longtitude_hemisphere = (char)data[pos]; pos++;
gps.Unknown = data[pos]; pos++;
float lat = Box.ReadFloatLE(data, pos); pos += 4;
gps.Latitude = FixCoordinate(lat, gps.Latitude_hemisphere);
float lon = Box.ReadFloatLE(data, pos); pos += 4;
gps.Longtitude = FixCoordinate(lon, gps.Longtitude_hemisphere);
gps.Speed = Box.ReadFloatLE(data, pos); pos += 4;
gps.Bearing = Box.ReadFloatLE(data, pos); pos += 4;
return gps;
}
return null;
}