大家在跟踪定位的系统中,可能碰到这样的问题:视频采集之后形成的文件,在此文件中包括 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 f 0 c 4 02 a 3 20 a 5 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 f 0 c 4
00 00 01 b8 00 08 00 00 00 00 01 00 00 0a 72 00
00 00 01 01 13 f 9 50 02 bc b2 b8 be 68 8b a4 9f
c5 b5 ca 00 56 76 39 65 f 2 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 c 8 0a 92 b9 29 3c 21 23 f 1 d6 40 13 06
f0 10 10 c 6 27 80 a 0 34 e 1 c 8 e4 0f 74 91 da c4
03 a 0 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 c 9 3b
1e a7 60 3c 9d 74 80 76 05 0b 02 81 a 9 29 39 68
53 8f 59 f 1 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 = 0x 0f 0 = 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;