moov box的解析
常见的MP4结构图
moov box是个container box,读取box头部之后就开始读取子box了
moov box的定义
/*
** moov box的定义,包含:
** mvhd、trak(cmov无意义)
*/
static mp4_atom_handler mp4_moov_atoms[] = {
{ "mvhd", &Mp4Meta::mp4_read_mvhd_atom },
{ "trak", &Mp4Meta::mp4_read_trak_atom },
{ "cmov", &Mp4Meta::mp4_read_cmov_atom },
{ NULL, NULL }
};
读取moov box
// 读取moov box
int
Mp4Meta::mp4_read_moov_atom(int64_t atom_header_size, int64_t atom_data_size)
{
int64_t atom_size;
int ret;
if (mdat_atom.buffer != NULL) // not reasonable for streaming media
return -1;
atom_size = atom_header_size + atom_data_size;
if (atom_data_size >= MP4_MAX_BUFFER_SIZE)
return -1;
if (meta_avail < atom_size) { // data unsufficient, wait
return 0;
}
moov_atom.buffer = TSIOBufferCreate();
moov_atom.reader = TSIOBufferReaderAlloc(moov_atom.buffer);
TSIOBufferCopy(moov_atom.buffer, meta_reader, atom_header_size, 0);
mp4_meta_consume(atom_header_size);
// 读取box,注意第一个参数是函数指针数组
ret = mp4_read_atom(mp4_moov_atoms, atom_data_size);
return ret;
}
读取moov box的子box
读取子box,根据子box的名字分别调用:
1、mp4_read_mvhd_atom处理mvhd box
2、mp4_read_trak_atom处理trak box
3、mp4_read_cmov_atom处理cmov box
int
Mp4Meta::mp4_read_atom(mp4_atom_handler *atom, int64_t size)
{
int i, ret, rc;
int64_t atom_size, atom_header_size;
char buf[32];
char *atom_header, *atom_name;
if (meta_avail < size) // data insufficient, not reasonable for internal atom box.
return -1;
while (size > 0) {
if (meta_avail < (int64_t)sizeof(uint32_t)) // data insufficient, not reasonable for internal atom box.
return -1;
IOBufferReaderCopy(meta_reader, buf, sizeof(mp4_atom_header64));
atom_size = mp4_get_32value(buf);
if (atom_size == 0) {
return 1;
}
atom_header = buf;
if (atom_size < (int64_t)sizeof(mp4_atom_header)) {
if (atom_size == 1) {
if (meta_avail < (int64_t)sizeof(mp4_atom_header64)) {
return -1;
}
} else {
return -1;
}
atom_size = mp4_get_64value(atom_header + 8);
atom_header_size = sizeof(mp4_atom_header64);
} else { // regular atom
if (meta_avail < (int64_t)sizeof(mp4_atom_header))
return -1;
atom_header_size = sizeof(mp4_atom_header);
}
atom_name = atom_header + 4;
if (atom_size + this->passed > this->cl) {
return -1;
}
// 根据mp4_moov_atoms的定义,下面会调用:
// mp4_read_mvhd_atom处理mvhd、mp4_read_trak_atom处理trak、mp4_read_cmov_atom处理cmov
for (i = 0; atom[i].name; i++) {
if (memcmp(atom_name, atom[i].name, 4) == 0) {
if (meta_avail < atom_size)
return -1;
ret = (this->*atom[i].handler)(atom_header_size, atom_size - atom_header_size); // -1: error, 0: success.
if (ret < 0) {
return ret;
}
goto next;
}
}
// insignificant atom box
rc = mp4_atom_next(atom_size, false);
if (rc < 0) {
return rc;
}
next:
size -= atom_size;
continue;
}
return 1;
}