Gps与时间信息的提取
2007-12-04 11:09
281 查看
大家在跟踪定位的系统中,可能碰到这样的问题:视频采集之后形成的文件,在此文件中包括 gps数据信息,然后将根据该文件中的gps信息提取出来,然后然后根据这些信息在平面上将轨迹绘制出来,在这里,我主要讲解 mpeg文件的基本格式以及gps信息的提取,关于绘制,将gps信息转换的坐标的问题,读者可以自己查阅相关的资料 。
先看看文件序列头饰如何的定义 ,我也是从大网上搜索到的,不再进行翻译,我想对于任何一个开发者来说这点英文不算什么,你自己翻译。
sequence header
this contains information related to one or more "group-of-pictures"
byte# data details
==================================================================
1-4 sequence header in hex 000001b3
code
12 bits horizontal size in pixels
12 bits vertical size in pixels
4 bits pel aspect ratio see below
18 bits picture rate see below
1 bit marker bit always 1
10 bits vbv buffer size minimum buffer needed to decode this
sequence of pictures; in 16kb units
1 bit constrained
parameter flag
1 bit load intra 0: false; 1: true (matrix follows)
quantizer matrix
64 bytes intra quantizer optional
matrix
1 bit load nonintra 0: false; 1: true (matrix follows)
quantizer matrix
64 bytes nonintra quantizer optional
matrix
- squence extension optional
data
- user data optional application-dependent data
===================================================================
aspect raios are defined by a code which represents the height and
width of the video image.
picture rates are also defined by a code that represents the number
of pictures that may be displayed each second.
each group of pictures has a header that contains one "i picture"
and zero or more b and p pictures. the header is concerned with
the time synchronisation for the first picture in this group, and
the closeness of the previous group to this one.
/*****************************************************************/
for picture rate:
1 = 23.976 frames/sec
2 = 24
3 = 25
4 = 29.97
5 = 30
6 = 50
7 = 59.94
8 = 60
here gives an example. below is hex dump of first 256 bytes of
the first video frame of test.mpg from xingmpeg.
00 00 01 b3 16 00 f0 c4 02 a3 20 a5 10 12 12 14
14 14 16 16 16 16 18 18 19 18 18 1a 1b 1b 1b 1b
1a 1c 1d 1e 1e 1e 1d 1c 1e 1f 20 21 21 20 1f 1e
21 23 23 24 23 23 21 25 26 27 27 26 25 29 2a 2a
2a 29 2d 2d 2d 2d 30 31 30 34 34 38 16 00 f0 c4
00 00 01 b8 00 08 00 00 00 00 01 00 00 0a 72 00
00 00 01 01 13 f9 50 02 bc b2 b8 be 68 8b a4 9f
c5 b5 ca 00 56 76 39 65 f2 30 8b a6 9d 50 69 e7
da fe 13 cf b7 ff 8f f4 ce 7b fa 0e f0 66 ae 1c
5d e7 00 c8 0a 92 b9 29 3c 21 23 f1 d6 40 13 06
f0 10 10 c6 27 80 a0 34 e1 c8 e4 0f 74 91 da c4
03 a0 dc 03 12 60 18 49 27 1d d4 bc 67 0e 54 8c
96 fc 5d c0 06 e0 1a 72 11 7c 9a 8d c9 45 89 6d
cd c4 0b 63 dc 90 18 24 00 ec 84 90 18 10 c9 3b
1e a7 60 3c 9d 74 80 76 05 0b 02 81 a9 29 39 68
53 8f 59 f1 bf 93 fb a0 04 01 bc b0 ce 18 e1 25
sequence header = (hex) 00 00 01 b3
horizontal size = 0x160 = 352
vertical size = 0x0f0 = 240
pel aspect ratio = [i don't know]
picture rate = 4 = 29.97 frames/sec
marker bit = 1
如果你连这个都看不懂,那建议你不用往下看,因为下面连这样的清楚的讲解都没有。当我们知道了文件的头以及连续动画图片的数据信息,(在例子代码中有视频与音频数据的分解提取)。
理解上面的上面头文件格式之后,让我们来实现测定 MPEG Stream Type
关于DWORD_SWAP 与NextStartCode 在源码中都有,你只要明白这么做,具体为什么这么做,似乎也是你自己该研究的问题,或许你有更好的方法,抛砖引玉 (这样你会更深刻的理解与操作mpeg文件)。
int CheckMPEGStreamType (const char * mpgfile)
{
char sDataBuf [32768];
char *sPtr;
DWORD dwLeft, dwPackStartCode;
FILE * fp;
int iRet = -1;
BOOL bMP4 = false;
fp = fopen (mpgfile, "rb");
if (!fp)
return iRet;
dwLeft = fread (sDataBuf, 1, 32768, fp);
fclose (fp);
sPtr = sDataBuf;
if (DWORD_SWAP(*(UNALIGNED DWORD *)sPtr) == 0x000001BA)
{ // MPEG-1 Syatem, MPEG-2 program or MPEG-4 Program
// check if MPEG-1 or MPEG-2(MPEG-4)
if ((*(PBYTE)(sPtr+4) & 0x40) == 0x0) { // MPEG-1 Syatem
iRet = 1;
} else { // Check if MPEG-2 or MPEG-4
bMP4 = false;
while (dwLeft >= 4)
{
NextStartCode ((const BYTE **)&sPtr, &dwLeft);
dwPackStartCode = DWORD_SWAP(*(UNALIGNED DWORD *)sPtr);
if (dwPackStartCode == 0x000001b6) { // MPEG-4 stuff
bMP4 = true;
break;
}
dwLeft --;
sPtr ++;
}
if (bMP4)
iRet = 4;
else
iRet = 2;
}
} else if (*sPtr == 0x47)
{ // MPEG-2 Transport or MPEG-4 Transport
while (dwLeft >= 188 && *(char *)sPtr == 0x47)
{
DWORD dwSubLeft;
char * sSubPtr;
dwSubLeft = dwLeft;
sSubPtr = sPtr;
while (dwSubLeft >= 4) {
NextStartCode ((const BYTE **)&sSubPtr, &dwSubLeft);
dwPackStartCode = DWORD_SWAP(*(UNALIGNED DWORD *)sSubPtr);
if (dwPackStartCode == 0x000001b6) { // MPEG-4 stuff
bMP4 = true;
break;
}
dwSubLeft --;
sSubPtr ++;
}
if (bMP4) {
iRet = 5;
break;
}
dwLeft -= 188;
sPtr += 188;;
}
if (iRet == -1) // Can not find MPEG-4 Stuff, so MPEG-2
iRet = 3;
} else // We ignore ES checking in this code
iRet = -1;
return iRet;
}
检测完文件之后,后面将进行 gps与时间的信息提取。在mpeg文件中,是允许添加用户自定义信息的,这部分信息,你可以写gps、时间、还有其它的相关的你关注的东西,在播放软件中将跳过这些信息,并不影响视频的正常播放(前题,你写进去之后,能确保信息的正确性,就是数据块要自己控制大小,否则在解析的时候会有问题)。
看看一般的厂家都是怎么写这个用户自定义信息的。
Sector description
文件开始头为 000001bf 这个是 自定义数据的开始头
然后后面紧跟的两个字 为当前自定义数据的长度
譬如 00 00 01 bf 07 d4 ( 在察看mpeg文件的时候建议使用16进制文件编辑器)
00 00 01 bf 为标志 07 d4 为 当前的自定义的字节长度 包括 开始的标志头
在下面紧跟的就是自定义的数据
第一个字为标示如果是11 那么代表的是 记录的时间
紧跟的一个字是代表的当前块的长度
譬如 下面的
1. Record time block (0x11)
譬如下面的时间信息 11 06 07 06 16 0d 2c 22
分表代表的是 0x11 –时间标志
06 当前时间块的长度
07 年份 –基准2000(不同的厂家不一样的设定)
06 月份
16 日期
0d 小时 24进制
2c 分钟
22 秒
不做详细的讲解,你需要到什么自己就分析什么,不需要的就忽略掉。如何的分析? 上面已经有例子。
User data block
2. Record time block (0x11)
3. User ID block (0x12)
4. Vehicle ID block (0x13)
5. Event information block(0x14)
6. Data block index block
7. Route ID block (0x16)
8. Speed information block (0x17)
9. Display Information block (0x18)
10. GPS data information (0x19)
11. Route ID block (0x1a)
下面我们将进行 时间与gps信息的提取
while (curPos<dwLen)
{
DWORD curid = pbData[curPos];
switch (curid)
{
case 0x11: //2. Record time block
{
DWORD curBlock = pbData[curPos+1];
int m_nYear = pbData[curPos+2]+2000;
int m_nMonth = pbData[curPos+3];
int m_nDate = pbData[curPos+4];
int m_nHour = pbData[curPos+5];
int m_nMin = pbData[curPos+6];
int m_nSec = pbData[curPos+7];
curPos += curBlock+2;
CString m_str;
m_str.Format(_T("%d-%d-%d %d:%d:%d/n/t"),m_nYear,m_nMonth,m_nDate,m_nHour,m_nMin,m_nSec);
COleDateTime datB;
datB.ParseDateTime(m_str);
m_str= datB.Format(_T("%Y-%m-%d ")) +datB.Format(_T("%H:%M:%S"));
if(m_strTimeInfo != _T(""))
{
m_strTimeInfo+=_T("$");
}
m_strTimeInfo+=m_str;
}
break;
case 0x12://User ID block
{
DWORD curBlock = pbData[curPos+1];
curPos += curBlock+2;
}
break;
case 0x13://Vehicle ID block
{
DWORD curBlock = pbData[curPos+1];
curPos += curBlock+2;
}
break;
case 0x14://Event information block
{
DWORD curBlock = pbData[curPos+1];
curPos += curBlock+2;
}
break;
case 0x15://Data block index block
{
DWORD curBlock = pbData[curPos+1];
curPos += curBlock*5+2;
}
break;
case 0x16://Route ID block
{
DWORD curBlock = pbData[curPos+1];
curPos += curBlock+2;
}
break;
case 0x17://Speed information block
{
DWORD curBlock = pbData[curPos+1];
curPos += curBlock+2;
}
break;
case 0x18://Display Information block
{
DWORD curBlock = pbData[curPos+1];
curPos += curBlock+2;
}
break;
case 0x19://GPS data information
{
//块长度
DWORD curBlock = pbData[curPos+1];
//数据长度
DWORD m_infolength = pbData[curPos+2];
//应该根据信息的长度来提取GPRMC数据
CString m_stInfo;
BYTE sGpsBuf[32768*2];
CopyMemory (sGpsBuf, pbData+curPos+3, m_infolength);
sGpsBuf[m_infolength+1]='/0';
//将提取的数据转换场字符串准备下一步的分割操作
m_stInfo = sGpsBuf;
m_strGpsInfo +=m_stInfo;
//解析gprms
curPos += curBlock+2+1;
}
break;
case 0x1a://Route ID block
{
DWORD curBlock = pbData[curPos+1];
curPos += curBlock+2;
}
break;
default:
goto enblockid;
break;
}
关于 gps信息的 是按照国际通用的 gprmc格式 ,
格式如下:
$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh<CR><LF>
<1> UTC时间,hhmmss(时分秒)格式
<2> 定位状态,A=有效定位,V=无效定位
<3> 纬度ddmm.mmmm(度分)格式(前面的0也将被传输)
<4> 纬度半球N(北半球)或S(南半球)
<5> 经度dddmm.mmmm(度分)格式(前面的0也将被传输)
<6> 经度半球E(东经)或W(西经)
<7> 地面速率(000.0~999.9节,前面的0也将被传输)
<8> 地面航向(000.0~359.9度,以真北为参考基准,前面的0也将被传输)
<9> UTC日期,ddmmyy(日月年)格式
<10> 磁偏角(000.0~180.0度,前面的0也将被传输)
<11> 磁偏角方向,E(东)或W(西)
<12> 模式指示(仅NMEA0183 3.00版本输出,A=自主定位,D=差分,E=估算,N=数据无效)
数据提取显示如下:
我们使用$符号来分割时间信息 : "2007-07-03 14:13:46$2007-07-03 14:13:47$2007-07-03 14:13:48$2007-07-03 14:13:49$2007-07-03 14:13:50$2007-07-03 14:13:51$2007-07-03 14:13:52$2007-07-03 14:13:53$2007-07-03 14:13:54$2007-07-03 14:13 ……
同样使用$符号来分割gps 信息
GPRMC,093001.100,A,2232.9689,N,11356.2107,E,8.56,269.56,300306,,,A*6C$ GPRMC,093020.095,A,2232.9674,N,11356.2021,E,9.62,265.79,300306,,,A*62 …
在代码中没有全部作非法的检查,仅仅是为了完成了功能。在使用中引起任何的问题与本人无关 。
如何 使用源码? 很简单,看下面的例子
CParseMpegData m_parse ( m_str );
m_parse . ParseMPEGStream ();
CString m_strTime = m_parse . GetTimeString ();
CString m_strGps = m_parse . GetGpsData ();
先看看文件序列头饰如何的定义 ,我也是从大网上搜索到的,不再进行翻译,我想对于任何一个开发者来说这点英文不算什么,你自己翻译。
sequence header
this contains information related to one or more "group-of-pictures"
byte# data details
==================================================================
1-4 sequence header in hex 000001b3
code
12 bits horizontal size in pixels
12 bits vertical size in pixels
4 bits pel aspect ratio see below
18 bits picture rate see below
1 bit marker bit always 1
10 bits vbv buffer size minimum buffer needed to decode this
sequence of pictures; in 16kb units
1 bit constrained
parameter flag
1 bit load intra 0: false; 1: true (matrix follows)
quantizer matrix
64 bytes intra quantizer optional
matrix
1 bit load nonintra 0: false; 1: true (matrix follows)
quantizer matrix
64 bytes nonintra quantizer optional
matrix
- squence extension optional
data
- user data optional application-dependent data
===================================================================
aspect raios are defined by a code which represents the height and
width of the video image.
picture rates are also defined by a code that represents the number
of pictures that may be displayed each second.
each group of pictures has a header that contains one "i picture"
and zero or more b and p pictures. the header is concerned with
the time synchronisation for the first picture in this group, and
the closeness of the previous group to this one.
/*****************************************************************/
for picture rate:
1 = 23.976 frames/sec
2 = 24
3 = 25
4 = 29.97
5 = 30
6 = 50
7 = 59.94
8 = 60
here gives an example. below is hex dump of first 256 bytes of
the first video frame of test.mpg from xingmpeg.
00 00 01 b3 16 00 f0 c4 02 a3 20 a5 10 12 12 14
14 14 16 16 16 16 18 18 19 18 18 1a 1b 1b 1b 1b
1a 1c 1d 1e 1e 1e 1d 1c 1e 1f 20 21 21 20 1f 1e
21 23 23 24 23 23 21 25 26 27 27 26 25 29 2a 2a
2a 29 2d 2d 2d 2d 30 31 30 34 34 38 16 00 f0 c4
00 00 01 b8 00 08 00 00 00 00 01 00 00 0a 72 00
00 00 01 01 13 f9 50 02 bc b2 b8 be 68 8b a4 9f
c5 b5 ca 00 56 76 39 65 f2 30 8b a6 9d 50 69 e7
da fe 13 cf b7 ff 8f f4 ce 7b fa 0e f0 66 ae 1c
5d e7 00 c8 0a 92 b9 29 3c 21 23 f1 d6 40 13 06
f0 10 10 c6 27 80 a0 34 e1 c8 e4 0f 74 91 da c4
03 a0 dc 03 12 60 18 49 27 1d d4 bc 67 0e 54 8c
96 fc 5d c0 06 e0 1a 72 11 7c 9a 8d c9 45 89 6d
cd c4 0b 63 dc 90 18 24 00 ec 84 90 18 10 c9 3b
1e a7 60 3c 9d 74 80 76 05 0b 02 81 a9 29 39 68
53 8f 59 f1 bf 93 fb a0 04 01 bc b0 ce 18 e1 25
sequence header = (hex) 00 00 01 b3
horizontal size = 0x160 = 352
vertical size = 0x0f0 = 240
pel aspect ratio = [i don't know]
picture rate = 4 = 29.97 frames/sec
marker bit = 1
如果你连这个都看不懂,那建议你不用往下看,因为下面连这样的清楚的讲解都没有。当我们知道了文件的头以及连续动画图片的数据信息,(在例子代码中有视频与音频数据的分解提取)。
理解上面的上面头文件格式之后,让我们来实现测定 MPEG Stream Type
关于DWORD_SWAP 与NextStartCode 在源码中都有,你只要明白这么做,具体为什么这么做,似乎也是你自己该研究的问题,或许你有更好的方法,抛砖引玉 (这样你会更深刻的理解与操作mpeg文件)。
int CheckMPEGStreamType (const char * mpgfile)
{
char sDataBuf [32768];
char *sPtr;
DWORD dwLeft, dwPackStartCode;
FILE * fp;
int iRet = -1;
BOOL bMP4 = false;
fp = fopen (mpgfile, "rb");
if (!fp)
return iRet;
dwLeft = fread (sDataBuf, 1, 32768, fp);
fclose (fp);
sPtr = sDataBuf;
if (DWORD_SWAP(*(UNALIGNED DWORD *)sPtr) == 0x000001BA)
{ // MPEG-1 Syatem, MPEG-2 program or MPEG-4 Program
// check if MPEG-1 or MPEG-2(MPEG-4)
if ((*(PBYTE)(sPtr+4) & 0x40) == 0x0) { // MPEG-1 Syatem
iRet = 1;
} else { // Check if MPEG-2 or MPEG-4
bMP4 = false;
while (dwLeft >= 4)
{
NextStartCode ((const BYTE **)&sPtr, &dwLeft);
dwPackStartCode = DWORD_SWAP(*(UNALIGNED DWORD *)sPtr);
if (dwPackStartCode == 0x000001b6) { // MPEG-4 stuff
bMP4 = true;
break;
}
dwLeft --;
sPtr ++;
}
if (bMP4)
iRet = 4;
else
iRet = 2;
}
} else if (*sPtr == 0x47)
{ // MPEG-2 Transport or MPEG-4 Transport
while (dwLeft >= 188 && *(char *)sPtr == 0x47)
{
DWORD dwSubLeft;
char * sSubPtr;
dwSubLeft = dwLeft;
sSubPtr = sPtr;
while (dwSubLeft >= 4) {
NextStartCode ((const BYTE **)&sSubPtr, &dwSubLeft);
dwPackStartCode = DWORD_SWAP(*(UNALIGNED DWORD *)sSubPtr);
if (dwPackStartCode == 0x000001b6) { // MPEG-4 stuff
bMP4 = true;
break;
}
dwSubLeft --;
sSubPtr ++;
}
if (bMP4) {
iRet = 5;
break;
}
dwLeft -= 188;
sPtr += 188;;
}
if (iRet == -1) // Can not find MPEG-4 Stuff, so MPEG-2
iRet = 3;
} else // We ignore ES checking in this code
iRet = -1;
return iRet;
}
检测完文件之后,后面将进行 gps与时间的信息提取。在mpeg文件中,是允许添加用户自定义信息的,这部分信息,你可以写gps、时间、还有其它的相关的你关注的东西,在播放软件中将跳过这些信息,并不影响视频的正常播放(前题,你写进去之后,能确保信息的正确性,就是数据块要自己控制大小,否则在解析的时候会有问题)。
看看一般的厂家都是怎么写这个用户自定义信息的。
Sector description
Offset | Size | Description |
0x26 | 4 | 0x00, 0x00, 0x01, 0xbf – private stream header |
0x2a | 2 | 0x08, 0xe8 – data length |
0x2c | 2280 | User data block |
然后后面紧跟的两个字 为当前自定义数据的长度
譬如 00 00 01 bf 07 d4 ( 在察看mpeg文件的时候建议使用16进制文件编辑器)
00 00 01 bf 为标志 07 d4 为 当前的自定义的字节长度 包括 开始的标志头
在下面紧跟的就是自定义的数据
第一个字为标示如果是11 那么代表的是 记录的时间
紧跟的一个字是代表的当前块的长度
譬如 下面的
1. Record time block (0x11)
Offset | Size | Description |
0x00 | 1 | 0x11 – Block ID |
0x01 | 1 | 0x06 – block length |
0x02 | 1 | year, offset from year 2000 |
0x03 | 1 | month |
0x04 | 1 | date |
0x05 | 1 | hour |
0x06 | 1 | minute |
0x07 | 1 | second |
分表代表的是 0x11 –时间标志
06 当前时间块的长度
07 年份 –基准2000(不同的厂家不一样的设定)
06 月份
16 日期
0d 小时 24进制
2c 分钟
22 秒
不做详细的讲解,你需要到什么自己就分析什么,不需要的就忽略掉。如何的分析? 上面已经有例子。
User data block
Offset | Size | Description |
0x00 | 1 | Block ID, from 0x11 to 0xf0 |
0x01 | 1 | Block size in bytes |
0x02 | Block size | Block data |
Offset | Size | Description |
0x00 | 1 | 0x11 – Block ID |
0x01 | 1 | 0x06 – block length |
0x02 | 1 | year, offset from year 2000 |
0x03 | 1 | month |
0x04 | 1 | date |
0x05 | 1 | hour |
0x06 | 1 | minute |
0x07 | 1 | second |
Offset | Size | Description |
0x00 | 1 | 0x12 – Block ID |
0x01 | 1 | 0x40 – block length |
0x02 | 64 | User ID |
Offset | Size | Description |
0x00 | 1 | 0x13 – Block ID |
0x01 | 1 | 0x40 – block length |
0x02 | 64 | Vehicle ID |
Offset | Size | Description |
0x00 | 1 | 0x14 – Block ID |
0x01 | 1 | 0x44 – block length |
0x02 | 4 | Event status |
0x06 | 40 | Event information |
Offset | Size | Description |
0x00 | 1 | 0x15 – Block ID |
0x01 | 1 | N*5 – block length |
0x02 | 1 | Block1 type |
0x03 | 4 | Block1 offset |
0x07 | 1 | Block2 type |
0x08 | 4 | Block2 offset |
… | … | … |
2+N*5 | 1 | Block N type |
3+N*5 | 4 | Block N offset |
Offset | Size | Description |
0x00 | 1 | 0x16 – Block ID |
0x01 | 1 | 0x40 – block length |
0x02 | 64 | Vehicle ID |
Offset | Size | Description |
0x00 | 1 | 0x17 – Block ID |
0x01 | 1 | 0x03 – block length |
0x02 | 1 | Speed low byte |
0x03 | 1 | Speed hi byte |
0x04 | 1 | 0: KM/H 1: MPH |
Offset | Size | Description |
0x00 | 1 | 0x18 – Block ID |
0x01 | 1 | 0x45 – block length |
0x02 | 1 | Information ID, 0~31 |
0x03 | 2 | X position |
0x05 | 2 | Y position |
0x07 | 64 | Information |
Offset | Size | Description |
0x00 | 1 | 0x19 – Block ID |
0x01 | 1 | 0x80 – block length |
0x02 | 1 | Information data length |
0x03 | 128 | Information |
Offset | Size | Description |
0x00 | 1 | 0x1a – Block ID |
0x01 | 1 | 0x40 – block length |
0x02 | 64 | Vehicle ID |
while (curPos<dwLen)
{
DWORD curid = pbData[curPos];
switch (curid)
{
case 0x11: //2. Record time block
{
DWORD curBlock = pbData[curPos+1];
int m_nYear = pbData[curPos+2]+2000;
int m_nMonth = pbData[curPos+3];
int m_nDate = pbData[curPos+4];
int m_nHour = pbData[curPos+5];
int m_nMin = pbData[curPos+6];
int m_nSec = pbData[curPos+7];
curPos += curBlock+2;
CString m_str;
m_str.Format(_T("%d-%d-%d %d:%d:%d/n/t"),m_nYear,m_nMonth,m_nDate,m_nHour,m_nMin,m_nSec);
COleDateTime datB;
datB.ParseDateTime(m_str);
m_str= datB.Format(_T("%Y-%m-%d ")) +datB.Format(_T("%H:%M:%S"));
if(m_strTimeInfo != _T(""))
{
m_strTimeInfo+=_T("$");
}
m_strTimeInfo+=m_str;
}
break;
case 0x12://User ID block
{
DWORD curBlock = pbData[curPos+1];
curPos += curBlock+2;
}
break;
case 0x13://Vehicle ID block
{
DWORD curBlock = pbData[curPos+1];
curPos += curBlock+2;
}
break;
case 0x14://Event information block
{
DWORD curBlock = pbData[curPos+1];
curPos += curBlock+2;
}
break;
case 0x15://Data block index block
{
DWORD curBlock = pbData[curPos+1];
curPos += curBlock*5+2;
}
break;
case 0x16://Route ID block
{
DWORD curBlock = pbData[curPos+1];
curPos += curBlock+2;
}
break;
case 0x17://Speed information block
{
DWORD curBlock = pbData[curPos+1];
curPos += curBlock+2;
}
break;
case 0x18://Display Information block
{
DWORD curBlock = pbData[curPos+1];
curPos += curBlock+2;
}
break;
case 0x19://GPS data information
{
//块长度
DWORD curBlock = pbData[curPos+1];
//数据长度
DWORD m_infolength = pbData[curPos+2];
//应该根据信息的长度来提取GPRMC数据
CString m_stInfo;
BYTE sGpsBuf[32768*2];
CopyMemory (sGpsBuf, pbData+curPos+3, m_infolength);
sGpsBuf[m_infolength+1]='/0';
//将提取的数据转换场字符串准备下一步的分割操作
m_stInfo = sGpsBuf;
m_strGpsInfo +=m_stInfo;
//解析gprms
curPos += curBlock+2+1;
}
break;
case 0x1a://Route ID block
{
DWORD curBlock = pbData[curPos+1];
curPos += curBlock+2;
}
break;
default:
goto enblockid;
break;
}
关于 gps信息的 是按照国际通用的 gprmc格式 ,
格式如下:
$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh<CR><LF>
<1> UTC时间,hhmmss(时分秒)格式
<2> 定位状态,A=有效定位,V=无效定位
<3> 纬度ddmm.mmmm(度分)格式(前面的0也将被传输)
<4> 纬度半球N(北半球)或S(南半球)
<5> 经度dddmm.mmmm(度分)格式(前面的0也将被传输)
<6> 经度半球E(东经)或W(西经)
<7> 地面速率(000.0~999.9节,前面的0也将被传输)
<8> 地面航向(000.0~359.9度,以真北为参考基准,前面的0也将被传输)
<9> UTC日期,ddmmyy(日月年)格式
<10> 磁偏角(000.0~180.0度,前面的0也将被传输)
<11> 磁偏角方向,E(东)或W(西)
<12> 模式指示(仅NMEA0183 3.00版本输出,A=自主定位,D=差分,E=估算,N=数据无效)
数据提取显示如下:
我们使用$符号来分割时间信息 : "2007-07-03 14:13:46$2007-07-03 14:13:47$2007-07-03 14:13:48$2007-07-03 14:13:49$2007-07-03 14:13:50$2007-07-03 14:13:51$2007-07-03 14:13:52$2007-07-03 14:13:53$2007-07-03 14:13:54$2007-07-03 14:13 ……
同样使用$符号来分割gps 信息
GPRMC,093001.100,A,2232.9689,N,11356.2107,E,8.56,269.56,300306,,,A*6C$ GPRMC,093020.095,A,2232.9674,N,11356.2021,E,9.62,265.79,300306,,,A*62 …
在代码中没有全部作非法的检查,仅仅是为了完成了功能。在使用中引起任何的问题与本人无关 。
如何 使用源码? 很简单,看下面的例子
CParseMpegData m_parse ( m_str );
m_parse . ParseMPEGStream ();
CString m_strTime = m_parse . GetTimeString ();
CString m_strGps = m_parse . GetGpsData ();
相关文章推荐
- 纯洁MM教你提取相片中的详细参数:相机品牌,色彩编码,拍摄时间,GPS等等近50项信息。
- 人工智能:python 实现 第十一章,从时间序列数据中提取统计信息
- Android开发,GPS获取实时时间并转为北京时间,定位信息,海拔高度,并进行显示
- 从EXIF JPEG图片中提取GPS位置信息
- 提取Exif信息中GPS经纬度,转化为double方法
- 简单网络管理协议(SNMP)通过第三方API SNMP++ 提取系统时间信息,并根据时间信息计算系统开机时间与运行时间
- 根据时间提取介于某个时间段的信息 分类: python基础学习 2013-08-16 17:26 311人阅读 评论(0) 收藏
- GPS信息中提取经纬度坐标信息
- opencv 提取视频信息(提取每帧 VS 按照时间提取)
- 根据时间提取介于某个时间段的信息
- 修改时间格式 gps 移动网络位置信息默认 音量设置
- 用perl 提取时间信息并处理数据--实例。
- MYSQL 提取时间中的信息的 4 方法
- python——博客园首页信息提取与分析
- 爬虫实战---正则表达式提取信息
- HM编码器端提取PU分割模式及CU深度信息
- 查询某段时间用户登录信息,并且当前版本不是1.72
- 响应事件示例:同时在按钮上和状态栏中显示当前时间,如果单击按钮,会显示信息框
- 函数分别提取日期和时间
- 在PDA中获取GPS信息。