MP4也是一个容器
/* ** MP4容器定义,包含:** ftyp、moov、mdat*/static mp4_atom_handler mp4_atoms[] = { { "ftyp", &Mp4Meta::mp4_read_ftyp_atom }, { "moov", &Mp4Meta::mp4_read_moov_atom }, { "mdat", &Mp4Meta::mp4_read_mdat_atom }, { NULL, NULL }};MP4的解析步骤
解析步骤如下: 1、读取mp4文件 2、读取box的size字段 3、如果box的size字段的值是1,表示真实的长度需要用64位来表示,需要继续读取 4、读取box的名字,根据名字来调用mp4 box中的函数指针:
(1)mp4_read_ftyp_atom,读取ftyp box
(2)mp4_read_moov_atom,读取moov box
(3)mp4_read_mdat_atom,读取mdat box
代码实现
intMp4Meta::parse_root_atoms(){ int i, ret, rc; int64_t atom_size, atom_header_size; char buf[64]; char *atom_header, *atom_name; memset(buf, 0, sizeof(buf)); for (;;) { if (meta_avail < (int64_t)sizeof(uint32_t)) return 0; IOBufferReaderCopy(meta_reader, buf, sizeof(mp4_atom_header64)); // 读取box的size atom_size = mp4_get_32value(buf); if (atom_size == 0) { return 1; } atom_header = buf; if (atom_size < (int64_t)sizeof(mp4_atom_header)) { // 如果size等于1,表示真实的size需要64位表示,需要继续读取 if (atom_size == 1) { if (meta_avail < (int64_t)sizeof(mp4_atom_header64)) { return 0; } } 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)) // not enough for atom header return 0; atom_header_size = sizeof(mp4_atom_header); } // 读取box的名字 atom_name = atom_header + 4; if (atom_size + this->passed > this->cl) { return -1; } // 调用MP4容器的处理函数 for (i = 0; mp4_atoms[i].name; i++) { // 根据名字进行调用mp4_read_ftyp_atom、mp4_read_moov_atom、mp4_read_mdat_atom if (memcmp(atom_name, mp4_atoms[i].name, 4) == 0) { ret = (this->*mp4_atoms[i].handler)(atom_header_size, atom_size - atom_header_size); // -1: error, 0: unfinished, 1: success if (ret <= 0) { return ret; } else if (meta_complete) { // success return 1; } goto next; } } // nonsignificant atom box rc = mp4_atom_next(atom_size, true); // 0: unfinished, 1: success if (rc == 0) { return rc; }next: continue; } return 1;}
新闻热点
疑难解答