我正在尝试了解有关AVI结构的更多信息,因此我开始介绍位于此处的Microsoft obtuse文档:
https://msdn.microsoft.com/en-us/library/ms779636.aspx
我希望能够根据未压缩的位图图像编写AVI创建器。但是我发现如果不尝试分解现有的AVI,很难理解这种格式。所以,我抓住了一个躺在我的硬盘上并开始从文件中提取字节。这是构建的代码和命令:
// Read an unsigned
//
static unsigned get_dword(FILE *fp)
{
unsigned tmp;
unsigned char buf[4];
unsigned char *p;
p = (unsigned char *) &tmp;
if (fread(&buf, 1, sizeof(buf), fp) != sizeof(buf)) {
printf("Error: Unexpected EOF\n");
exit(1);
}
p[0] = buf[0];
p[1] = buf[1];
p[2] = buf[2];
p[3] = buf[3];
return tmp;
}
static unsigned short get_word(FILE *fp)
{
unsigned short tmp;
unsigned char buf[2];
unsigned char *p;
p = (unsigned char *) &tmp;
if (fread(&buf, 1, sizeof(buf), fp) != sizeof(buf)) {
printf("Error: Unexpected EOF\n");
exit(1);
}
p[0] = buf[0];
p[1] = buf[1];
return tmp;
}
static char *get_fourcc(char *str, FILE *fp)
{
if (fread(str, 1, 4, fp) != 4) {
printf("Error: Unexpected EOF\n");
exit(1);
}
return str;
}
//
//
int main(int argc, char *argv[])
{
if (argc > 1) {
FILE *fp = fopen(argv[1], "rb");
if (fp) {
char buf[5] = { 0 };
printf("%s (\n", get_fourcc(buf, fp));
printf("fileSize=%u\n", get_dword(fp));
printf("fileType='%s'\n", get_fourcc(buf, fp));
printf("'%s'\n", get_fourcc(buf, fp));
printf("listSize=%u\n", get_dword(fp));
printf("listType='%s'\n", get_fourcc(buf, fp));
// avih
printf("listData='%s'\n", get_fourcc(buf, fp));
printf("cb=%u\n", get_dword(fp));
printf("dwMicroSecPerFrame=%u\n", get_dword(fp));
printf("dwMaxBytesPerSec=%u\n", get_dword(fp));
printf("dwPaddingGranularity=%u\n", get_dword(fp));
printf("dwFlags=0x%x\n", get_dword(fp));
printf("dwTotalFrames=%u\n", get_dword(fp));
printf("dwInitialFrames=%u\n", get_dword(fp));
printf("dwStreams=%u\n", get_dword(fp));
printf("dwSuggestedBufferSize=%u\n", get_dword(fp));
printf("dwWidth=%u\n", get_dword(fp));
printf("dwHeight=%u\n", get_dword(fp));
printf("dwReserved = { %u, %u, %u, %u }\n", get_dword(fp),
get_dword(fp), get_dword(fp), get_dword(fp));
printf("'%s'\n", get_fourcc(buf, fp));
printf("listSize=%u\n", get_dword(fp));
printf("listType='%s'\n", get_fourcc(buf, fp));
// strh
printf("listData='%s'\n", get_fourcc(buf, fp));
printf("cb=%u\n", get_dword(fp));
printf("fccType='%s'\n", get_fourcc(buf, fp));
printf("fccHandler='%s'\n", get_fourcc(buf, fp));
printf("dwFlags=0x%x\n", get_dword(fp));
printf("wPriority=%d\n", get_word(fp));
printf("wLanguage=%d\n", get_word(fp));
printf("dwInitialFrames=%u\n", get_dword(fp));
printf("dwScale=%u\n", get_dword(fp));
printf("dwRate=%u\n", get_dword(fp));
printf("dwStart=%u\n", get_dword(fp));
printf("dwLength=%u\n", get_dword(fp));
printf("dwSuggestedBufferSize=%u\n", get_dword(fp));
printf("dwQuality=%u\n", get_dword(fp));
printf("dwSampleSize=%u\n", get_dword(fp));
printf("rcFrame={ %u, %u, %u, %u }\n", get_word(fp),
get_word(fp), get_word(fp), get_word(fp));
// strf
printf("'%s'\n", get_fourcc(buf, fp));
printf("biSize=%u\n", get_dword(fp));
printf("?=%d\n", get_dword(fp));
printf("biWidth=%d\n", get_dword(fp));
printf("biHeight=%d\n", get_dword(fp));
printf("biPlanes=%d\n", get_word(fp));
printf("biBitCount=%d\n", get_word(fp));
printf("biCompression=0x%x\n", get_dword(fp));
printf("biSizeImage=%u\n", get_dword(fp));
printf("biXPelsPerMeter=%d\n", get_dword(fp));
printf("biYPelsPerMeter=%d\n", get_dword(fp));
printf("biClrUsed=%u\n", get_dword(fp));
printf("biClrImportant=%u\n", get_dword(fp));
printf("%s\n", get_fourcc(buf, fp));
fclose(fp);
} else {
printf("Unable to open '%s'\n", argv[1]);
}
}
}
$ g++ -g -o avi -Wall -ansi avi.cc
$ ./avi avifile.avi
RIFF (
fileSize=68054008
fileType='AVI '
'LIST'
listSize=796
listType='hdrl'
listData='avih'
cb=56
dwMicroSecPerFrame=33367
dwMaxBytesPerSec=3724404
dwPaddingGranularity=512
dwFlags=0x810
dwTotalFrames=545
dwInitialFrames=0
dwStreams=2
dwSuggestedBufferSize=120008
dwWidth=720
dwHeight=480
dwReserved = { 0, 0, 0, 0 }
'LIST'
listSize=228
listType='strl'
listData='strh'
cb=56
fccType='vids'
fccHandler='dvsd'
dwFlags=0x0
wPriority=0
wLanguage=0
dwInitialFrames=0
dwScale=1001
dwRate=30000
dwStart=0
dwLength=545
dwSuggestedBufferSize=120008
dwQuality=4294967295
dwSampleSize=0
rcFrame={ 0, 0, 720, 480 }
'strf'
biSize=40
?=40
biWidth=720
biHeight=480
biPlanes=1
biBitCount=24
biCompression=0x64737664
biSizeImage=120000
biXPelsPerMeter=0
biYPelsPerMeter=0
biClrUsed=0
biClrImportant=0
indx
我担心的是'?'的具体条目通过它。对于标题大小,40个字节应该是正确的,但是在进入位图帧的宽度和高度之前,第二次重复40个字节。我运行了hexdump,这不是代码中的错误。我看了两次。我试图理解这是否只是我对格式的解释中的错误,或者这是否是其他的。
这里记录了BITMAPINFOHEADER结构:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd183376(v=vs.85).aspx
如果有人有任何指示,那就太棒了......
答案 0 :(得分:2)
第一个数字40不是第二个40的biBytes
。第一个数字实际上是strf
块中包含的数据的大小。对于这个块,这两个数字恰好相同。
AVI文件基于微软的RIFF format(反过来基于电子艺界的IFF format)。在RIFF格式中,所有内容都以块的形式存储。每个块以4个字节开始,用于标识块的类型,紧接着是4个字节,指定块中数据的长度为32位无符号小端整数。我建议重写你的程序来单独处理每个块,而不是假设一个固定的块序列。这样你就可以跳过你不感兴趣的块,或者还没弄明白如何完全解码。