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