1 /**************************************************************************
2 copyright : (C) 2007 by Lukáš Lalinský
3 email : lalinsky@gmail.com
4 **************************************************************************/
6 /***************************************************************************
7 * This library is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU Lesser General Public License version *
9 * 2.1 as published by the Free Software Foundation. *
11 * This library is distributed in the hope that it will be useful, but *
12 * WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14 * Lesser General Public License for more details. *
16 * You should have received a copy of the GNU Lesser General Public *
17 * License along with this library; if not, write to the Free Software *
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
21 * Alternatively, this file is available under the Mozilla Public *
22 * License Version 1.1. You may obtain a copy of the License at *
23 * http://www.mozilla.org/MPL/ *
24 ***************************************************************************/
34 using namespace TagLib;
36 const char *MP4::Atom::containers[10] = {
37 "moov", "udta", "mdia", "meta", "ilst",
38 "stbl", "minf", "moof", "traf", "trak",
41 MP4::Atom::Atom(File *file)
43 offset = file->tell();
44 ByteVector header = file->readBlock(8);
45 if (header.size() != 8) {
46 // The atom header must be 8 bytes long, otherwise there is either
47 // trailing garbage or the file is truncated
48 debug("MP4: Couldn't read 8 bytes of data for atom header");
50 file->seek(0, File::End);
54 length = header.mid(0, 4).toUInt();
57 long long longLength = file->readBlock(8).toLongLong();
58 if (longLength >= 8 && longLength <= 0xFFFFFFFF) {
59 // The atom has a 64-bit length, but it's actually a 32-bit value
60 length = (long)longLength;
63 debug("MP4: 64-bit atoms are not supported");
65 file->seek(0, File::End);
70 debug("MP4: Invalid atom size");
72 file->seek(0, File::End);
76 name = header.mid(4, 4);
78 for(int i = 0; i < numContainers; i++) {
79 if(name == containers[i]) {
81 file->seek(4, File::Current);
83 while(file->tell() < offset + length) {
84 MP4::Atom *child = new MP4::Atom(file);
85 children.append(child);
86 if (child->length == 0)
93 file->seek(offset + length);
98 for(unsigned int i = 0; i < children.size(); i++) {
105 MP4::Atom::find(const char *name1, const char *name2, const char *name3, const char *name4)
110 for(unsigned int i = 0; i < children.size(); i++) {
111 if(children[i]->name == name1) {
112 return children[i]->find(name2, name3, name4);
119 MP4::Atom::findall(const char *name, bool recursive)
121 MP4::AtomList result;
122 for(unsigned int i = 0; i < children.size(); i++) {
123 if(children[i]->name == name) {
124 result.append(children[i]);
127 result.append(children[i]->findall(name, recursive));
134 MP4::Atom::path(MP4::AtomList &path, const char *name1, const char *name2, const char *name3)
140 for(unsigned int i = 0; i < children.size(); i++) {
141 if(children[i]->name == name1) {
142 return children[i]->path(path, name2, name3);
148 MP4::Atoms::Atoms(File *file)
150 file->seek(0, File::End);
151 long end = file->tell();
153 while(file->tell() + 8 <= end) {
154 MP4::Atom *atom = new MP4::Atom(file);
156 if (atom->length == 0)
163 for(unsigned int i = 0; i < atoms.size(); i++) {
170 MP4::Atoms::find(const char *name1, const char *name2, const char *name3, const char *name4)
172 for(unsigned int i = 0; i < atoms.size(); i++) {
173 if(atoms[i]->name == name1) {
174 return atoms[i]->find(name2, name3, name4);
181 MP4::Atoms::path(const char *name1, const char *name2, const char *name3, const char *name4)
184 for(unsigned int i = 0; i < atoms.size(); i++) {
185 if(atoms[i]->name == name1) {
186 if(!atoms[i]->path(path, name2, name3, name4)) {