参考文档 https://juejin.cn/post/7312375896177934399
ftyp box结构
ftyp box是mp4 文件的第一个box,结构如下
名称 | 字节数 | 数据类型 |
---|---|---|
长度 | 4字节 | int |
box类型 | 4字节 | 字符 |
major brand | 4字节 | 字符 |
版本 | 4字节 | int |
compatible brands | 剩下的 | 字符 |
测试代码
main.c
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <byteswap.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);
}
// ftyp
// 4字节 长度 注意要做大小端变换
// 4字节 type 字符
// 4字节 major brand 字符
// 4字节版本 整形注意要做大小端变换
// 剩下的为compatible brands
// 读取前4字节
// 文件头4个字节是ftyp box的长度
char buffer[1024];
long off_set = 0;
unsigned int ftyp_box_len = 0;
long 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的大小端,要做一个转换
ftyp_box_len = bswap_32(*((__uint32_t *)buffer));
printf("ftyp_box 长度:%u\n", ftyp_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);
// major brand
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("major brand 为 %s\n", buffer);
//
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;
// 这里注意cpu的大小端,要做一个转换
unsigned int minor_version = bswap_32(*((__uint32_t *)buffer));
printf("minor_version:%u\n", minor_version);
int rest_byte = ftyp_box_len - off_set;
if (rest_byte > 0)
{
bytes_read = read(fd, buffer, rest_byte);
if (bytes_read == -1)
{
perror("读取文件失败");
close(fd);
exit(1);
}
else if (!bytes_read == rest_byte)
{
perror("读取不到足够长度");
close(fd);
exit(1);
}
off_set += bytes_read;
buffer[rest_byte] = '\0';
printf("compatible brand 为 %s\n", buffer);
}
// 关闭文件
close(fd);
return 0;
}
测试
gcc -o mp4info main.c -g
编译
$ ./mp4info ./oceans.mp4
hello world!
0 argv: ./mp4info
1 argv: ./oceans.mp4
ftyp_box 长度:24
box类型 为 ftyp
major brand 为 isom
minor_version:1
compatible brand 为 isomavc1
查看oceans.mp4得到信息
$ ./mp4info ./1.mp4
hello world!
0 argv: ./mp4info
1 argv: ./1.mp4
ftyp_box 长度:32
box类型 为 ftyp
major brand 为 isom
minor_version:512
compatible brand 为 isomiso2avc1mp41
查看./1.mp4得到信息