|
1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 |
|
17 #include "parsers.h" |
|
18 |
|
19 // |
|
20 // Masks used for reading bits. |
|
21 // |
|
22 static const TInt KMP3Sync1Mask = 0xff; // 11111111 |
|
23 static const TInt KMP3Sync2Mask = 0xe0; // 11100000 |
|
24 static const TInt KMP3VersionMask = 0x18; // 00011000 |
|
25 static const TInt KMP3LayerMask = 0x06; // 00000110 |
|
26 static const TInt KMP3BitrateMask = 0xf0; // 11110000 |
|
27 static const TInt KMP3SampleRateMask = 0x0c; // 00001100 |
|
28 static const TInt KMP3PaddingMask = 0x02; // 00000010 |
|
29 |
|
30 static const TInt KBitsPerByte = 8; |
|
31 |
|
32 // |
|
33 // Macros for retrieving the values. |
|
34 // |
|
35 #define MP3_GET_SYNC1(d) (d & KMP3Sync1Mask) |
|
36 #define MP3_GET_SYNC2(d) ((d & KMP3Sync2Mask) >> 5) |
|
37 #define MP3_GET_VERSION(d) ((d & KMP3VersionMask) >> 3) |
|
38 #define MP3_GET_LAYER(d) ((d & KMP3LayerMask) >> 1) |
|
39 #define MP3_GET_BITRATE(d) ((d & KMP3BitrateMask) >> 4) |
|
40 #define MP3_GET_SAMPLE_RATE(d) ((d & KMP3SampleRateMask) >> 2) |
|
41 #define MP3_GET_PADDING(d) ((d & KMP3PaddingMask) >> 1) |
|
42 |
|
43 |
|
44 // |
|
45 // Macros used for checking various bitfields. |
|
46 // |
|
47 #define IS_BAD_MP3_FRAME_SYNC1(s) ((s) != 0xff) |
|
48 #define IS_BAD_MP3_FRAME_SYNC2(s) ((s) != 0x07) |
|
49 #define IS_BAD_MP3_VERSION(v) ((v) < 0x02) |
|
50 #define IS_BAD_MP3_LAYER(l) ((l) == 0x00) |
|
51 #define IS_BAD_MP3_BITRATE(b) ((b) == 0x0f) |
|
52 #define IS_BAD_MP3_SAMPLE_RATE(s) ((s) == 0x03) |
|
53 |
|
54 |
|
55 // |
|
56 // Meanings of the 'Version' field. |
|
57 // -------------------------------- |
|
58 // 00 - MPEG Version 2.5 (Unofficial standard. We don't support it.) |
|
59 // 01 - Reserved |
|
60 // 10 - MPEG Version 2 |
|
61 // 11 - MPEG Version 1 |
|
62 // |
|
63 static const TInt8 KMP3Version2 = 2; |
|
64 static const TInt8 KMP3Version1 = 3; |
|
65 |
|
66 |
|
67 // |
|
68 // Meanings of the 'Layer' field. |
|
69 // ------------------------------ |
|
70 // 00 - Reserved |
|
71 // 01 - Layer III |
|
72 // 10 - Layer II |
|
73 // 11 - Layer I |
|
74 // |
|
75 |
|
76 static const TUint16 KBad = 0; |
|
77 static const TUint16 KFree = 0; |
|
78 |
|
79 // |
|
80 // MPEG Version 1 bitrates. Measured in kilobits per second. |
|
81 // |
|
82 static const TUint16 KBitrateVersion1[4][16] = |
|
83 { |
|
84 { KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad}, // Reserved layer |
|
85 {KFree, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, KBad}, // Layer III |
|
86 {KFree, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, KBad}, // Layer II |
|
87 {KFree, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, KBad} // Layer I |
|
88 }; |
|
89 |
|
90 // |
|
91 // MPEG Version 2 bitrates. Measured in kilobits per second. |
|
92 // |
|
93 static const TUint16 KBitrateVersion2[4][16] = |
|
94 { |
|
95 { KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad, KBad}, // Reserved layer |
|
96 {KFree, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, KBad}, // Layer III |
|
97 {KFree, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, KBad}, // Layer II |
|
98 {KFree, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, KBad} // Layer I |
|
99 }; |
|
100 |
|
101 // |
|
102 // Sample rates for the MPEG versions. |
|
103 // |
|
104 static const TUint16 KSampleRate[4][4] = |
|
105 { |
|
106 {11025, 12000, 8000, KBad}, // Version 2.5 |
|
107 { KBad, KBad, KBad, KBad}, // Reserved |
|
108 {22050, 24000, 16000, KBad}, // Version 2 |
|
109 {44100, 48000, 32000, KBad} // Version 1 |
|
110 }; |
|
111 |
|
112 // |
|
113 // Sample rates per frame for the MPEG layers. |
|
114 // |
|
115 static const TUint16 KSamplesPerFrame[4][4] = |
|
116 { |
|
117 {KBad, KBad, KBad, KBad}, // Reserved layer |
|
118 { 576, KBad, 576, 1152}, // Layer III |
|
119 {1152, KBad, 1152, 1152}, // Layer II |
|
120 { 384, KBad, 384, 384} // Layer I |
|
121 }; |
|
122 |
|
123 // |
|
124 // The various states the recognition process goes through. |
|
125 // |
|
126 typedef enum |
|
127 { |
|
128 ESearchFrame1, |
|
129 ESearchFrame2 |
|
130 } |
|
131 TMP3State; |
|
132 |
|
133 // |
|
134 // This truth table maps the following flags to a confidence level. |
|
135 // ----------------------------------------------------------------- |
|
136 // A: Frame2 found. |
|
137 // B: Frame1 found. |
|
138 // C: Extension recognised. |
|
139 // |
|
140 // A B C -> Confidence |
|
141 // =================== |
|
142 // 0 0 0 -> ENotRecognized |
|
143 // 0 0 1 -> EPossible |
|
144 // 0 1 0 -> ENotRecognized |
|
145 // 0 1 1 -> ECertain |
|
146 // 1 0 0 -> EPossible |
|
147 // 1 0 1 -> EProbable |
|
148 // 1 1 0 -> EProbable |
|
149 // 1 1 1 -> ECertain |
|
150 // |
|
151 // In the case where two consecutive mp3 frames |
|
152 // are found, ECertain is automatically returned. |
|
153 // |
|
154 static const TInt KMP3FlagsToConfidence[8] = |
|
155 { |
|
156 KConfNotRecognised, |
|
157 KConfPossible, |
|
158 KConfNotRecognised, |
|
159 KConfCertain, |
|
160 KConfPossible, |
|
161 KConfProbable, |
|
162 KConfProbable, |
|
163 KConfCertain |
|
164 }; |
|
165 |
|
166 #define KMP3ConfidenceMask 0x07 // 00000111 |
|
167 #define KMP3Frame1Bit KBit1 |
|
168 #define KMP3Frame2Bit KBit2 |
|
169 |
|
170 // |
|
171 // |
|
172 // |
|
173 TMP3Parser::TMP3Parser(CReader& aReader, TFlags& aFlags) |
|
174 : iReader(aReader), |
|
175 iFlags(aFlags) |
|
176 { |
|
177 } |
|
178 |
|
179 |
|
180 // |
|
181 // MP3 recogition function. |
|
182 // |
|
183 void TMP3Parser::DoRecognise(const TDesC& aExt, CReader& aReader, TMatch& aMatch) |
|
184 { |
|
185 TFlags flags; |
|
186 |
|
187 // Try to match the extension. |
|
188 if (aExt.MatchF(TPtrC(KExtMP3)) != KErrNotFound) |
|
189 { |
|
190 flags.SetExtensionFlag(); |
|
191 } |
|
192 |
|
193 // Parse the data. |
|
194 TMP3Parser parser(aReader, flags); |
|
195 TRAP_IGNORE(parser.ParseL()); |
|
196 |
|
197 TInt confIndex = flags.GetBitField(KMP3ConfidenceMask); |
|
198 aMatch.iConfidence = KMP3FlagsToConfidence[confIndex]; |
|
199 if (aMatch.iConfidence != KConfNotRecognised) |
|
200 { |
|
201 aMatch.iMime = KMimeMP3; |
|
202 } |
|
203 } |
|
204 |
|
205 |
|
206 // |
|
207 // Attempts to parse an mp3 file. |
|
208 // First of all it checks if there is an ID3 metadata header |
|
209 // present at the current reader position. Then it checks for up to |
|
210 // two consecutive mp3 audio frames. |
|
211 // |
|
212 void TMP3Parser::ParseL() |
|
213 { |
|
214 TInt length; |
|
215 TMP3State state = ESearchFrame1; |
|
216 |
|
217 FOREVER |
|
218 { |
|
219 TID3Parser::ReadAndSkipID3L(iReader); |
|
220 |
|
221 TInt err = CheckForFrameHeaderL(length); |
|
222 if (err == KErrNotFound) |
|
223 { |
|
224 return; |
|
225 } |
|
226 |
|
227 switch (state) |
|
228 { |
|
229 case ESearchFrame1: |
|
230 iFlags.SetBit(KMP3Frame1Bit); |
|
231 state = ESearchFrame2; |
|
232 break; |
|
233 |
|
234 case ESearchFrame2: |
|
235 iFlags.SetBit(KMP3Frame2Bit); |
|
236 return; |
|
237 } |
|
238 |
|
239 // Skip over the audio frame. |
|
240 // This should be done after flags have been set. |
|
241 iReader.SeekL(length - KMP3FrameHeaderSize); |
|
242 } |
|
243 } |
|
244 |
|
245 |
|
246 // |
|
247 // Checks for an MP3 frame header at the current reader position. |
|
248 // If one is not found KErrNotFound is returned and aFrameLength |
|
249 // remains unchanged. If one is found KErrNone is retured and |
|
250 // aFrameLength is set to the length of the frame. |
|
251 // |
|
252 TInt TMP3Parser::CheckForFrameHeaderL(TInt& aFrameLength) |
|
253 { |
|
254 TBuf8<KMP3FrameHeaderSize> data; |
|
255 TUint8 versionIndex; |
|
256 TUint8 layerIndex; |
|
257 TUint8 bitrateIndex; |
|
258 TUint8 sampleRateIndex; |
|
259 TUint8 padding; |
|
260 TUint8 sync; |
|
261 |
|
262 data.SetLength(KMP3FrameHeaderSize); |
|
263 iReader.ReadBytesL(data); |
|
264 |
|
265 do |
|
266 { |
|
267 sync = MP3_GET_SYNC1(data[0]); |
|
268 if (IS_BAD_MP3_FRAME_SYNC1(sync)) |
|
269 { |
|
270 break; |
|
271 } |
|
272 |
|
273 sync = MP3_GET_SYNC2(data[1]); |
|
274 if (IS_BAD_MP3_FRAME_SYNC2(sync)) |
|
275 { |
|
276 break; |
|
277 } |
|
278 |
|
279 versionIndex = MP3_GET_VERSION(data[1]); |
|
280 if (IS_BAD_MP3_VERSION(versionIndex)) |
|
281 { |
|
282 break; |
|
283 } |
|
284 |
|
285 layerIndex = MP3_GET_LAYER(data[1]); |
|
286 if (IS_BAD_MP3_LAYER(layerIndex)) |
|
287 { |
|
288 break; |
|
289 } |
|
290 |
|
291 bitrateIndex = MP3_GET_BITRATE(data[2]); |
|
292 if (IS_BAD_MP3_BITRATE(bitrateIndex)) |
|
293 { |
|
294 break; |
|
295 } |
|
296 |
|
297 sampleRateIndex = MP3_GET_SAMPLE_RATE(data[2]); |
|
298 if (IS_BAD_MP3_SAMPLE_RATE(sampleRateIndex)) |
|
299 { |
|
300 break; |
|
301 } |
|
302 |
|
303 padding = MP3_GET_PADDING(data[2]); |
|
304 |
|
305 // All the data is valid. |
|
306 // Compute the audio data length. |
|
307 TUint32 bitRate = KBad; |
|
308 TUint16 sampleRate = KBad; |
|
309 TUint16 samplesPerFrame = KBad; |
|
310 |
|
311 if (versionIndex == KMP3Version1) |
|
312 { |
|
313 bitRate = KBitrateVersion1[layerIndex][bitrateIndex]; |
|
314 } |
|
315 else if (versionIndex == KMP3Version2) |
|
316 { |
|
317 bitRate = KBitrateVersion2[layerIndex][bitrateIndex]; |
|
318 } |
|
319 else |
|
320 { |
|
321 // Version 2.5 is not supported. |
|
322 break; |
|
323 } |
|
324 |
|
325 sampleRate = KSampleRate[versionIndex][sampleRateIndex]; |
|
326 samplesPerFrame = KSamplesPerFrame[layerIndex][versionIndex]; |
|
327 |
|
328 // Check we have valid values. |
|
329 if ((bitRate == KBad) || (sampleRate == KBad) || (samplesPerFrame == KBad)) |
|
330 { |
|
331 break; |
|
332 } |
|
333 |
|
334 bitRate *= 1000; // Convert to kilobits. |
|
335 aFrameLength = (((samplesPerFrame / KBitsPerByte) * bitRate) / sampleRate) + padding; |
|
336 return KErrNone; |
|
337 } |
|
338 while (EFalse); |
|
339 |
|
340 // No valid frame header was found. |
|
341 aFrameLength = 0; |
|
342 iReader.SeekL(-KMP3FrameHeaderSize); |
|
343 return KErrNotFound; |
|
344 } |
|
345 |
|
346 |
|
347 |
|
348 |