参考文档 https://juejin.cn/post/7312375896177934399
mp4文件结构
mp4文件是由一个个的box组成,通过读取每个box的前8位数据,可以确定box的长度和类型
main.c文件
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <byteswap.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
printf("hello world! \n");
for (int i = 0; i < argc; i++)
{
printf("%d argv: ", i);
printf("%s \n", argv[i]);
}
// 检查参数数量
if (argc != 2)
{
perror("Usage: ./program <filename>");
exit(1);
}
// 打开文件
int fd = open(argv[1], O_RDONLY);
if (fd == -1)
{
perror("无法打开文件");
exit(1);
}
// 查看文件信息
struct stat fd_stat;
if (fstat(fd, &fd_stat) == -1)
{
perror("获取文件信息失败");
close(fd);
return 1;
}
printf("*******************************\n");
char buffer[1024];
long off_set = 0;
unsigned int ftyp_box_len = 0;
long bytes_read = 0;
while (1)
{
// 4字节看长度,4字节看类型
bytes_read = read(fd, buffer, 4);
if (bytes_read == -1)
{
perror("读取文件失败");
close(fd);
exit(1);
}
else if (!bytes_read == 4)
{
perror("读取不到4字节的box长度");
close(fd);
exit(1);
}
off_set += bytes_read;
// 这里注意cpu的大小端,要做一个转换
unsigned int box_len = bswap_32(*((__uint32_t *)buffer));
printf("box 长度:%u\n", box_len);
// type
bytes_read = read(fd, buffer, 4);
if (bytes_read == -1)
{
perror("读取文件失败");
close(fd);
exit(1);
}
else if (!bytes_read == 4)
{
perror("读取不到足够长度");
close(fd);
exit(1);
}
off_set += bytes_read;
buffer[4] = '\0';
printf("box类型 为 %s\n", buffer);
printf("*******************************\n");
// 下一个box
off_set = off_set + box_len - 8;
//到底了
if((fd_stat.st_size - off_set) < 8)
{
break;
}
// 定位到off_set处
if (lseek(fd, off_set, SEEK_SET) == -1)
{
perror("文件定位失败");
close(fd);
return -1;
}
}
// 关闭文件
close(fd);
return 0;
}
编译
gcc -o mp4info main.c -g
测试
$ ./mp4info ./1.mp4
hello world!
0 argv: ./mp4info
1 argv: ./1.mp4
*******************************
box 长度:32
box类型 为 ftyp
*******************************
box 长度:191922
box类型 为 moov
*******************************
box 长度:8
box类型 为 free
*******************************
box 长度:32174398
box类型 为 mdat
*******************************
$ ./mp4info ./2.mp4
hello world!
0 argv: ./mp4info
1 argv: ./2.mp4
*******************************
box 长度:20
box类型 为 ftyp
*******************************
box 长度:15493
box类型 为 moov
*******************************
box 长度:8
box类型 为 wide
*******************************
box 长度:33572330
box类型 为 mdat
*******************************
$ ./mp4info ./oceans.mp4
hello world!
0 argv: ./mp4info
1 argv: ./oceans.mp4
*******************************
box 长度:24
box类型 为 ftyp
*******************************
box 长度:16310
box类型 为 moov
*******************************
box 长度:22998022
box类型 为 mdat
*******************************
可见mp4文件普遍都含有ftyp, moov, mdat这些box。