1 /***************************************************************************
2 copyright : (C) 2003 by Ismael Orenstein
3 email : orenstein@kde.org
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., 51 Franklin Street, Fifth Floor, Boston, MA *
19 * 02110-1301 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 #include <tbytevector.h>
27 #include <tstring.h>
28 #include <tdebug.h>
29
30 #include "xingheader.h"
31 #include "mpegfile.h"
32
33 using namespace TagLib;
34
35 class MPEG::XingHeader::XingHeaderPrivate
36 {
37 public:
XingHeaderPrivate()38 XingHeaderPrivate() :
39 frames(0),
40 size(0),
41 type(MPEG::XingHeader::Invalid) {}
42
43 unsigned int frames;
44 unsigned int size;
45
46 MPEG::XingHeader::HeaderType type;
47 };
48
49 ////////////////////////////////////////////////////////////////////////////////
50 // public members
51 ////////////////////////////////////////////////////////////////////////////////
52
XingHeader(const ByteVector & data)53 MPEG::XingHeader::XingHeader(const ByteVector &data) :
54 d(new XingHeaderPrivate())
55 {
56 parse(data);
57 }
58
~XingHeader()59 MPEG::XingHeader::~XingHeader()
60 {
61 delete d;
62 }
63
isValid() const64 bool MPEG::XingHeader::isValid() const
65 {
66 return (d->type != Invalid && d->frames > 0 && d->size > 0);
67 }
68
totalFrames() const69 unsigned int MPEG::XingHeader::totalFrames() const
70 {
71 return d->frames;
72 }
73
totalSize() const74 unsigned int MPEG::XingHeader::totalSize() const
75 {
76 return d->size;
77 }
78
type() const79 MPEG::XingHeader::HeaderType MPEG::XingHeader::type() const
80 {
81 return d->type;
82 }
83
xingHeaderOffset(TagLib::MPEG::Header::Version,TagLib::MPEG::Header::ChannelMode)84 int MPEG::XingHeader::xingHeaderOffset(TagLib::MPEG::Header::Version /*v*/,
85 TagLib::MPEG::Header::ChannelMode /*c*/)
86 {
87 return 0;
88 }
89
90 ////////////////////////////////////////////////////////////////////////////////
91 // private members
92 ////////////////////////////////////////////////////////////////////////////////
93
parse(const ByteVector & data)94 void MPEG::XingHeader::parse(const ByteVector &data)
95 {
96 // Look for a Xing header.
97
98 long offset = data.find("Xing");
99 if(offset < 0)
100 offset = data.find("Info");
101
102 if(offset >= 0) {
103
104 // Xing header found.
105
106 if(data.size() < static_cast<unsigned long>(offset + 16)) {
107 debug("MPEG::XingHeader::parse() -- Xing header found but too short.");
108 return;
109 }
110
111 if((data[offset + 7] & 0x03) != 0x03) {
112 debug("MPEG::XingHeader::parse() -- Xing header doesn't contain the required information.");
113 return;
114 }
115
116 d->frames = data.toUInt(offset + 8, true);
117 d->size = data.toUInt(offset + 12, true);
118 d->type = Xing;
119 }
120 else {
121
122 // Xing header not found. Then look for a VBRI header.
123
124 offset = data.find("VBRI");
125
126 if(offset >= 0) {
127
128 // VBRI header found.
129
130 if(data.size() < static_cast<unsigned long>(offset + 32)) {
131 debug("MPEG::XingHeader::parse() -- VBRI header found but too short.");
132 return;
133 }
134
135 d->frames = data.toUInt(offset + 14, true);
136 d->size = data.toUInt(offset + 10, true);
137 d->type = VBRI;
138 }
139 }
140 }
141