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 ***************************************************************************/
36 using namespace TagLib;
38 const char *MP4::Atom::containers[10] = {
39 "moov", "udta", "mdia", "meta", "ilst",
40 "stbl", "minf", "moof", "traf", "trak",
43 MP4::Atom::Atom(File *file)
45 offset = file->tell();
46 ByteVector header = file->readBlock(8);
47 if (header.size() != 8) {
48 // The atom header must be 8 bytes long, otherwise there is either
49 // trailing garbage or the file is truncated
50 debug("MP4: Couldn't read 8 bytes of data for atom header");
52 file->seek(0, File::End);
56 length = header.mid(0, 4).toUInt();
59 long long longLength = file->readBlock(8).toLongLong();
60 if (longLength >= 8 && longLength <= 0xFFFFFFFF) {
61 // The atom has a 64-bit length, but it's actually a 32-bit value
62 length = (long)longLength;
65 debug("MP4: 64-bit atoms are not supported");
67 file->seek(0, File::End);
72 debug("MP4: Invalid atom size");
74 file->seek(0, File::End);
78 name = header.mid(4, 4);
80 for(int i = 0; i < numContainers; i++) {
81 if(name == containers[i]) {
83 file->seek(4, File::Current);
85 while(file->tell() < offset + length) {
86 MP4::Atom *child = new MP4::Atom(file);
87 children.append(child);
88 if (child->length == 0)
95 file->seek(offset + length);
100 for(unsigned int i = 0; i < children.size(); i++) {
107 MP4::Atom::find(const char *name1, const char *name2, const char *name3, const char *name4)
112 for(unsigned int i = 0; i < children.size(); i++) {
113 if(children[i]->name == name1) {
114 return children[i]->find(name2, name3, name4);
121 MP4::Atom::findall(const char *name, bool recursive)
123 MP4::AtomList result;
124 for(unsigned int i = 0; i < children.size(); i++) {
125 if(children[i]->name == name) {
126 result.append(children[i]);
129 result.append(children[i]->findall(name, recursive));
136 MP4::Atom::path(MP4::AtomList &path, const char *name1, const char *name2, const char *name3)
142 for(unsigned int i = 0; i < children.size(); i++) {
143 if(children[i]->name == name1) {
144 return children[i]->path(path, name2, name3);
150 MP4::Atoms::Atoms(File *file)
152 file->seek(0, File::End);
153 long end = file->tell();
155 while(file->tell() + 8 <= end) {
156 MP4::Atom *atom = new MP4::Atom(file);
158 if (atom->length == 0)
165 for(unsigned int i = 0; i < atoms.size(); i++) {
172 MP4::Atoms::find(const char *name1, const char *name2, const char *name3, const char *name4)
174 for(unsigned int i = 0; i < atoms.size(); i++) {
175 if(atoms[i]->name == name1) {
176 return atoms[i]->find(name2, name3, name4);
183 MP4::Atoms::path(const char *name1, const char *name2, const char *name3, const char *name4)
186 for(unsigned int i = 0; i < atoms.size(); i++) {
187 if(atoms[i]->name == name1) {
188 if(!atoms[i]->path(path, name2, name3, name4)) {