Added TagLib (with AUTORS and COPYING files)
[someplayer] / src / taglib / mp4 / mp4properties.cpp
1 /**************************************************************************
2     copyright            : (C) 2007 by Lukáš Lalinský
3     email                : lalinsky@gmail.com
4  **************************************************************************/
5
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.                     *
10  *                                                                         *
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.                       *
15  *                                                                         *
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  *
19  *   USA                                                                   *
20  *                                                                         *
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  ***************************************************************************/
25
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29
30 #ifdef WITH_MP4
31
32 #include <tdebug.h>
33 #include <tstring.h>
34 #include "mp4file.h"
35 #include "mp4atom.h"
36 #include "mp4properties.h"
37
38 using namespace TagLib;
39
40 class MP4::Properties::PropertiesPrivate
41 {
42 public:
43   PropertiesPrivate() : length(0), bitrate(0), sampleRate(0), channels(0), bitsPerSample(0) {}
44
45   int length;
46   int bitrate;
47   int sampleRate;
48   int channels;
49   int bitsPerSample;
50 };
51
52 MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style)
53   : AudioProperties(style)
54 {
55   d = new PropertiesPrivate;
56
57   MP4::Atom *moov = atoms->find("moov");
58   if(!moov) {
59     debug("MP4: Atom 'moov' not found");
60     return;
61   }
62
63   MP4::Atom *trak = 0;
64   ByteVector data;
65
66   MP4::AtomList trakList = moov->findall("trak");
67   for (unsigned int i = 0; i < trakList.size(); i++) {
68     trak = trakList[i];
69     MP4::Atom *hdlr = trak->find("mdia", "hdlr");
70     if(!hdlr) {
71       debug("MP4: Atom 'trak.mdia.hdlr' not found");
72       return;
73     }
74     file->seek(hdlr->offset);
75     data = file->readBlock(hdlr->length);
76     if(data.mid(16, 4) == "soun") {
77       break;
78     }
79     trak = 0;
80   }
81   if (!trak) {
82     debug("MP4: No audio tracks");
83     return;
84   }
85
86   MP4::Atom *mdhd = trak->find("mdia", "mdhd");
87   if(!mdhd) {
88     debug("MP4: Atom 'trak.mdia.mdhd' not found");
89     return;
90   }
91
92   file->seek(mdhd->offset);
93   data = file->readBlock(mdhd->length);
94   if(data[8] == 0) {
95     unsigned int unit = data.mid(20, 4).toUInt();
96     unsigned int length = data.mid(24, 4).toUInt();
97     d->length = length / unit;
98   }
99   else {
100     long long unit = data.mid(28, 8).toLongLong();
101     long long length = data.mid(36, 8).toLongLong();
102     d->length = int(length / unit);
103   }
104
105   MP4::Atom *atom = trak->find("mdia", "minf", "stbl", "stsd");
106   if(!atom) {
107     return;
108   }
109
110   file->seek(atom->offset);
111   data = file->readBlock(atom->length);
112   if(data.mid(20, 4) == "mp4a") {
113     d->channels = data.mid(40, 2).toShort();
114     d->bitsPerSample = data.mid(42, 2).toShort();
115     d->sampleRate = data.mid(46, 4).toUInt();
116     if(data.mid(56, 4) == "esds" && data[64] == 0x03) {
117       long pos = 65;
118       if(data.mid(pos, 3) == "\x80\x80\x80") {
119         pos += 3;
120       }
121       pos += 4;
122       if(data[pos] == 0x04) {
123         pos += 1;
124         if(data.mid(pos, 3) == "\x80\x80\x80") {
125           pos += 3;
126         }
127         pos += 10;
128         d->bitrate = (data.mid(pos, 4).toUInt() + 500) / 1000;
129       }
130     }
131   }
132 }
133
134 MP4::Properties::~Properties()
135 {
136   delete d;
137 }
138
139 int
140 MP4::Properties::channels() const
141 {
142   return d->channels;
143 }
144
145 int
146 MP4::Properties::sampleRate() const
147 {
148   return d->sampleRate;
149 }
150
151 int
152 MP4::Properties::length() const
153 {
154   return d->length;
155 }
156
157 int
158 MP4::Properties::bitrate() const
159 {
160   return d->bitrate;
161 }
162
163 int
164 MP4::Properties::bitsPerSample() const
165 {
166   return d->bitsPerSample;
167 }
168
169 #endif