|
1 /* ============================================================================== |
|
2 * Name : 3GPExtParser.cpp |
|
3 * Part of : MetaDataUtility |
|
4 * Description : This class implements an 3GPExt metadata parser |
|
5 * Version : 9 |
|
6 * |
|
7 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
8 * All rights reserved. |
|
9 * This component and the accompanying materials are made available |
|
10 * under the terms of "Eclipse Public License v1.0" |
|
11 * which accompanies this distribution, and is available |
|
12 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
13 * |
|
14 * Initial Contributors: |
|
15 * Nokia Corporation - initial contribution. |
|
16 * ============================================================================== |
|
17 */ |
|
18 |
|
19 |
|
20 // INCLUDE FILES |
|
21 #include "3GPExtParser.h" |
|
22 #include "MetaDataID3v1Genre.h" |
|
23 #ifdef _DEBUG |
|
24 #include <e32svr.h> |
|
25 #endif |
|
26 |
|
27 // CONSTANTS |
|
28 |
|
29 const TUint32 K3gpMetaMeta = 0x6d657461; // 'meta' |
|
30 const TInt K3gpMetaLength = 1; |
|
31 |
|
32 |
|
33 // ============================ MEMBER FUNCTIONS =============================== |
|
34 |
|
35 // ----------------------------------------------------------------------------- |
|
36 // C3GPExtParser::C3GPExtParser |
|
37 // C++ default constructor can NOT contain any code, that |
|
38 // might leave. |
|
39 // ----------------------------------------------------------------------------- |
|
40 // |
|
41 C3GPExtParser::C3GPExtParser(MP4Handle& aMP4Handle): iMP4Handle(aMP4Handle), ilst(NULL, 0) |
|
42 { |
|
43 } |
|
44 |
|
45 // ----------------------------------------------------------------------------- |
|
46 // C3GPExtParser::ConstructL |
|
47 // Symbian 2nd phase constructor can leave. |
|
48 // ----------------------------------------------------------------------------- |
|
49 // |
|
50 void C3GPExtParser::ConstructL() |
|
51 { |
|
52 K3GPExtMetaTitle.Format(K3GPExtMetaTitleFormat, 0xA9); |
|
53 K3GPExtMetaArtist.Format(K3GPExtMetaArtistFormat, 0xA9); |
|
54 K3GPExtMetaComposer.Format(K3GPExtMetaComposerFormat, 0xA9); |
|
55 K3GPExtMetaAlbum.Format(K3GPExtMetaAlbumFormat, 0xA9); |
|
56 K3GPExtMetaComment.Format(K3GPExtMetaCommentFormat, 0xA9); |
|
57 K3GPExtMetaCustomGenre.Format(K3GPExtMetaCustomGenreFormat, 0xA9); |
|
58 K3GPExtMetaYear.Format(K3GPExtMetaYearFormat, 0xA9); |
|
59 } |
|
60 |
|
61 // ----------------------------------------------------------------------------- |
|
62 // C3GPExtParser::NewL |
|
63 // Two-phased constructor. |
|
64 // ----------------------------------------------------------------------------- |
|
65 // |
|
66 EXPORT_C C3GPExtParser* C3GPExtParser::NewL(MP4Handle& aMP4Handle) |
|
67 { |
|
68 #ifdef _DEBUG |
|
69 RDebug::Print(_L("C3GPExtParser::NewL")); |
|
70 #endif |
|
71 C3GPExtParser* self = new( ELeave ) C3GPExtParser (aMP4Handle); |
|
72 CleanupStack::PushL( self ); |
|
73 self->ConstructL(); |
|
74 CleanupStack::Pop(); |
|
75 return self; |
|
76 } |
|
77 |
|
78 // Destructor |
|
79 EXPORT_C C3GPExtParser::~C3GPExtParser() |
|
80 { |
|
81 if(iChunkStatus) |
|
82 { |
|
83 iChunk.Close(); |
|
84 } |
|
85 } |
|
86 |
|
87 // ----------------------------------------------------------------------------- |
|
88 // 3GPExtParser::GetilstBoxesL |
|
89 // ----------------------------------------------------------------------------- |
|
90 // |
|
91 EXPORT_C void C3GPExtParser::GetilstBoxesL(const TDesC8 &/*aBox*/, TMetaDataFieldId aFieldId, HBufC** aBuf) |
|
92 { |
|
93 #ifdef _DEBUG |
|
94 RDebug::Print(_L("C3GPExtParser::GetilstBoxesL")); |
|
95 #endif |
|
96 TUint32 offset = 0; |
|
97 TUint32 size = 0; |
|
98 switch(aFieldId) |
|
99 { |
|
100 case EMetaDataSongTitle: |
|
101 offset = iTitleOffset; |
|
102 size = iTitleSize; |
|
103 break; |
|
104 case EMetaDataArtist: |
|
105 offset = iArtistOffset; |
|
106 size = iArtistSize; |
|
107 break; |
|
108 case EMetaDataAlbum: |
|
109 offset = iAlbumOffset; |
|
110 size = iAlbumSize; |
|
111 break; |
|
112 case EMetaDataComposer: |
|
113 offset = iComposerOffset; |
|
114 size = iComposerSize; |
|
115 break; |
|
116 case EMetaDataComment: |
|
117 offset = iCommentOffset; |
|
118 size = iCommentSize; |
|
119 break; |
|
120 case EMetaDataRating: |
|
121 offset = iCustomGenreOffset; |
|
122 size = iCustomGenreSize; |
|
123 break; |
|
124 case EMetaDataYear: |
|
125 offset = iYearOffset; |
|
126 size = iYearSize; |
|
127 break; |
|
128 case EMetaDataGenre: |
|
129 offset = iGenreOffset; |
|
130 size = iGenreSize; |
|
131 break; |
|
132 case EMetaDataAlbumTrack: |
|
133 offset = iTrackNumberOffset; |
|
134 size = iTrackNumberSize; |
|
135 break; |
|
136 case EMetaDataJpeg: |
|
137 offset = iCoverOffset; |
|
138 size = iCoverSize; |
|
139 break; |
|
140 default: |
|
141 break; |
|
142 |
|
143 } |
|
144 |
|
145 if(size <= 0 || size >= (KMaxTInt/2)) |
|
146 { |
|
147 User::Leave(KErrNotFound); // no data |
|
148 } |
|
149 |
|
150 TInt length = ilst.Length(); |
|
151 if (length < 0 || length < (offset + size)) |
|
152 { |
|
153 User::Leave(KErrNotFound); // no data |
|
154 } |
|
155 |
|
156 // actual data ptr |
|
157 TPtrC8 data = ilst.Mid(offset, size); |
|
158 if(aFieldId != EMetaDataGenre && aFieldId != EMetaDataAlbumTrack && aFieldId != EMetaDataJpeg) |
|
159 { // string meta data |
|
160 *aBuf = HBufC::NewL(size); |
|
161 TPtr data16Ptr( (*aBuf)->Des() ); |
|
162 data16Ptr.Copy(data); |
|
163 } |
|
164 else if(aFieldId == EMetaDataGenre) |
|
165 { // 0x XXXX ID3v1 Genre + 1 |
|
166 TInt16 num = 0; |
|
167 for(TInt i = 0 ; i <= 1; i++) |
|
168 { |
|
169 num <<= 8; |
|
170 num |= data[i]; |
|
171 } |
|
172 num -= 1; // getting it to ID3 |
|
173 if((num >= 0 && num <= 125) || num == 199) |
|
174 { |
|
175 *aBuf = HBufC::NewL(KMaxGenreSize); |
|
176 TPtr genrePtr = (*aBuf)->Des(); |
|
177 MapID3GenreToString(num, genrePtr); |
|
178 } |
|
179 } |
|
180 else if(aFieldId == EMetaDataAlbumTrack) |
|
181 { |
|
182 *aBuf = HBufC::NewL(6); |
|
183 TUint num = 0; |
|
184 for(TInt i = 0 ; i <= 1; i++) |
|
185 { |
|
186 num <<= 8; |
|
187 num |= data[i+2]; |
|
188 } |
|
189 TBuf<6> data16; |
|
190 data16.NumUC(num); |
|
191 (**aBuf) = data16; |
|
192 } |
|
193 else if(aFieldId == EMetaDataJpeg) |
|
194 { |
|
195 TPtrC8 imageMime1 = data.Mid(6, 4); |
|
196 TPtrC8 imageMime2 = data.Mid(1, 3); |
|
197 _LIT8(KJFIF, "JFIF"); |
|
198 _LIT8(KPNG, "PNG"); |
|
199 if(imageMime1.Compare(KJFIF) != 0 && imageMime2.Compare(KPNG) != 0) |
|
200 { |
|
201 // only JPEG and PNG supported |
|
202 User::Leave(KErrNotFound); // no data |
|
203 } |
|
204 if(imageMime1.Compare(KJFIF) == 0) |
|
205 { |
|
206 TPtrC8 pic = data.Mid(0, size); |
|
207 TInt length = pic.Length(); |
|
208 if ( length ) |
|
209 { |
|
210 *aBuf = HBufC::NewL( length ); |
|
211 TPtr unicode( (*aBuf)->Des() ); |
|
212 unicode.Copy( pic ); |
|
213 } |
|
214 } |
|
215 else if(imageMime2.Compare(KPNG) == 0) |
|
216 { |
|
217 TPtrC8 pic = data.Mid(0, size); |
|
218 TInt length = pic.Length(); |
|
219 if ( length ) |
|
220 { |
|
221 *aBuf = HBufC::NewL( length ); |
|
222 TPtr unicode( (*aBuf)->Des() ); |
|
223 unicode.Copy( pic ); |
|
224 } |
|
225 } |
|
226 } |
|
227 } |
|
228 // ----------------------------------------------------------------------------- |
|
229 // 3GPExtParser::GetilstBoxesL for 8-bit descriptor fields |
|
230 // ----------------------------------------------------------------------------- |
|
231 // |
|
232 EXPORT_C void C3GPExtParser::GetilstBoxesL(const TDesC8 &/*aBox*/, TMetaDataFieldId aFieldId, HBufC8** aBuf) |
|
233 { |
|
234 #ifdef _DEBUG |
|
235 RDebug::Print(_L("C3GPExtParser::GetilstBoxesL 8 bit version")); |
|
236 #endif |
|
237 TUint32 offset = 0; |
|
238 TUint32 size = 0; |
|
239 switch(aFieldId) |
|
240 { |
|
241 case EMetaDataSongTitle: |
|
242 offset = iTitleOffset; |
|
243 size = iTitleSize; |
|
244 break; |
|
245 case EMetaDataArtist: |
|
246 offset = iArtistOffset; |
|
247 size = iArtistSize; |
|
248 break; |
|
249 case EMetaDataAlbum: |
|
250 offset = iAlbumOffset; |
|
251 size = iAlbumSize; |
|
252 break; |
|
253 case EMetaDataComposer: |
|
254 offset = iComposerOffset; |
|
255 size = iComposerSize; |
|
256 break; |
|
257 case EMetaDataComment: |
|
258 offset = iCommentOffset; |
|
259 size = iCommentSize; |
|
260 break; |
|
261 case EMetaDataRating: |
|
262 offset = iCustomGenreOffset; |
|
263 size = iCustomGenreSize; |
|
264 break; |
|
265 case EMetaDataYear: |
|
266 offset = iYearOffset; |
|
267 size = iYearSize; |
|
268 break; |
|
269 case EMetaDataGenre: |
|
270 offset = iGenreOffset; |
|
271 size = iGenreSize; |
|
272 break; |
|
273 case EMetaDataAlbumTrack: |
|
274 offset = iTrackNumberOffset; |
|
275 size = iTrackNumberSize; |
|
276 break; |
|
277 case EMetaDataJpeg: |
|
278 offset = iCoverOffset; |
|
279 size = iCoverSize; |
|
280 break; |
|
281 default: |
|
282 break; |
|
283 |
|
284 } |
|
285 |
|
286 if(size <= 0 || size >= (KMaxTInt/2)) |
|
287 { |
|
288 User::Leave(KErrNotFound); // no data |
|
289 } |
|
290 |
|
291 TInt length = ilst.Length(); |
|
292 if (length < 0 || length < (offset + size)) |
|
293 { |
|
294 User::Leave(KErrNotFound); // no data |
|
295 } |
|
296 |
|
297 // actual data ptr |
|
298 TPtrC8 data = ilst.Mid(offset, size); |
|
299 if(aFieldId != EMetaDataGenre && aFieldId != EMetaDataAlbumTrack && aFieldId != EMetaDataJpeg) |
|
300 { // string meta data |
|
301 *aBuf = HBufC8::NewL(size); |
|
302 TPtr8 unicode( (*aBuf)->Des() ); |
|
303 unicode.Copy(data); |
|
304 } |
|
305 if(aFieldId == EMetaDataJpeg) |
|
306 { |
|
307 TPtrC8 imageMime1 = data.Mid(6, 4); |
|
308 TPtrC8 imageMime2 = data.Mid(1, 3); |
|
309 _LIT8(KJFIF, "JFIF"); |
|
310 _LIT8(KPNG, "PNG"); |
|
311 if(imageMime1.Compare(KJFIF) != 0 && imageMime2.Compare(KPNG) != 0) |
|
312 { |
|
313 // only JPEG and PNG supported |
|
314 User::Leave(KErrNotFound); // no data |
|
315 } |
|
316 if(imageMime1.Compare(KJFIF) == 0) |
|
317 { |
|
318 TPtrC8 pic = data.Mid(0, size); |
|
319 TInt length = pic.Length(); |
|
320 if ( length ) |
|
321 { |
|
322 *aBuf = HBufC8::NewL( length ); |
|
323 TPtr8 unicode( (*aBuf)->Des() ); |
|
324 unicode.Copy( pic ); |
|
325 } |
|
326 } |
|
327 else if(imageMime2.Compare(KPNG) == 0) |
|
328 { |
|
329 TPtrC8 pic = data.Mid(0, size); |
|
330 TInt length = pic.Length(); |
|
331 if ( length ) |
|
332 { |
|
333 *aBuf = HBufC8::NewL( length ); |
|
334 TPtr8 unicode( (*aBuf)->Des() ); |
|
335 unicode.Copy( pic ); |
|
336 } |
|
337 } |
|
338 } |
|
339 } |
|
340 |
|
341 // ----------------------------------------------------------------------------- |
|
342 // C3GPExtParser::Is3GPExtMetadataL |
|
343 // ----------------------------------------------------------------------------- |
|
344 // |
|
345 EXPORT_C TBool C3GPExtParser::Is3GPExtMetadataL() |
|
346 { |
|
347 #ifdef _DEBUG |
|
348 RDebug::Print(_L("C3GPExtParser::3GPExtMetadataL")); |
|
349 #endif |
|
350 HBufC8* frame = HBufC8::NewLC( K3gpMetaLength ); |
|
351 TUint8* buffer = CONST_CAST(TUint8*, frame->Ptr()); |
|
352 |
|
353 MP4Err err; |
|
354 mp4_u8 udtaLocation = MP4_UDTA_MOOV; |
|
355 mp4_u32 bufferSize = K3gpMetaLength; |
|
356 mp4_u32 atomIndex = 0; |
|
357 |
|
358 err = MP4ParseGetUserDataAtom(iMP4Handle, udtaLocation, K3gpMetaMeta, buffer, |
|
359 bufferSize, atomIndex); |
|
360 if (bufferSize > (KMaxTInt / 2)) |
|
361 { |
|
362 User::Leave(KErrNotFound); // no data |
|
363 } |
|
364 |
|
365 if ( err == MP4_UDTA_NOT_FOUND ) |
|
366 { |
|
367 if ( udtaLocation == MP4_UDTA_NONE || udtaLocation == MP4_UDTA_MOOV ) |
|
368 { |
|
369 #ifdef _DEBUG |
|
370 RDebug::Print(_L("3GPExtParser::Parse3GPExtL - NotFound")); |
|
371 #endif |
|
372 CleanupStack::PopAndDestroy(); // frame |
|
373 return EFalse; |
|
374 } |
|
375 else |
|
376 { |
|
377 if ( udtaLocation & MP4_UDTA_AUDIOTRAK ) |
|
378 { |
|
379 udtaLocation = MP4_UDTA_AUDIOTRAK; |
|
380 } |
|
381 else // MP4_UDTA_VIDEOTRAK |
|
382 { |
|
383 udtaLocation = MP4_UDTA_VIDEOTRAK; |
|
384 } |
|
385 } |
|
386 #ifdef _DEBUG |
|
387 RDebug::Print(_L("3GPExtParser::Parse3GPExtL - New Location [%d]"), udtaLocation); |
|
388 #endif |
|
389 err = MP4ParseGetUserDataAtom(iMP4Handle, udtaLocation, K3gpMetaMeta, buffer, |
|
390 bufferSize, atomIndex); |
|
391 } |
|
392 |
|
393 if ( err != MP4_OK ) |
|
394 { |
|
395 if ( err == MP4_OUTPUT_BUFFER_TOO_SMALL ) |
|
396 { |
|
397 iChunk.Close(); |
|
398 |
|
399 User::LeaveIfError(iChunk.CreateLocal(bufferSize, bufferSize, EOwnerProcess)); |
|
400 iChunkStatus = ETrue; |
|
401 buffer = iChunk.Base(); |
|
402 err = MP4ParseGetUserDataAtom(iMP4Handle, udtaLocation, K3gpMetaMeta, buffer, bufferSize, atomIndex); |
|
403 if(err != MP4_OK) |
|
404 { |
|
405 CleanupStack::PopAndDestroy(); // frame |
|
406 return EFalse; |
|
407 } |
|
408 } |
|
409 else |
|
410 { |
|
411 CleanupStack::PopAndDestroy(); // frame |
|
412 return EFalse; |
|
413 //User::Leave( TranslateMP4Err(err) ); |
|
414 } |
|
415 } |
|
416 |
|
417 TPtr8 des(buffer, bufferSize, bufferSize); |
|
418 |
|
419 // HDLR BOX |
|
420 _LIT8(KHdlr, "hdlr"); |
|
421 TInt hdlrOffset = 16; // header box at constant offset |
|
422 TPtrC8 hdlrCheck = des.MidTPtr(hdlrOffset, 4); |
|
423 if(hdlrCheck != KHdlr) |
|
424 { |
|
425 CleanupStack::PopAndDestroy(); // frame |
|
426 return EFalse; // not 3GPExt |
|
427 } |
|
428 hdlrOffset -= 4; // hdlr box begins at size, 4 bytes back |
|
429 |
|
430 // get hdlr size |
|
431 TPtrC8 sizeHdlrDesc = des.Mid(hdlrOffset, 4); |
|
432 TInt32 sizeHdlr = 0; |
|
433 for(TInt i = 0 ; i <= 3; i++) |
|
434 { |
|
435 sizeHdlr <<= 8; |
|
436 sizeHdlr |= sizeHdlrDesc[i]; |
|
437 } |
|
438 if(sizeHdlr <= 0) |
|
439 { |
|
440 CleanupStack::PopAndDestroy(); // frame |
|
441 return EFalse; // not 3GPExt |
|
442 } |
|
443 |
|
444 // hdlr ptr |
|
445 if (des.Length() < (hdlrOffset + sizeHdlr)) |
|
446 { |
|
447 CleanupStack::PopAndDestroy(); // frame |
|
448 return EFalse; // data corrupted |
|
449 } |
|
450 TPtrC8 hdlr = des.Mid(hdlrOffset, sizeHdlr); |
|
451 |
|
452 // match mdirappl |
|
453 /**** Comment out the following lines - no need to test for "mdirappl" string |
|
454 TPtrC8 text = hdlr.Mid(16, 8); // at 16 bytes from hdlr box |
|
455 _LIT8(KMdirappl, "mdirappl"); |
|
456 if(text.Compare(KMdirappl) != 0) |
|
457 { |
|
458 CleanupStack::PopAndDestroy(); // frame |
|
459 return EFalse; // not 3GPExt |
|
460 } |
|
461 *****/ // End comment out "mdirappl" |
|
462 |
|
463 // iLST BOX |
|
464 _LIT8(KIlst, "ilst"); |
|
465 TInt ilstOffset = hdlrOffset + sizeHdlr + 4; |
|
466 if (ilstOffset > bufferSize) |
|
467 { |
|
468 CleanupStack::PopAndDestroy(); // frame |
|
469 return EFalse; // not 3GPExt |
|
470 } |
|
471 |
|
472 TPtrC8 ilstCheck = des.MidTPtr(ilstOffset, 4); |
|
473 if(ilstCheck != KIlst) |
|
474 { |
|
475 ilstOffset = des.Find(KIlst); |
|
476 if(ilstOffset == KErrNotFound) |
|
477 { |
|
478 CleanupStack::PopAndDestroy(); // frame |
|
479 return EFalse; // no list box |
|
480 } |
|
481 } |
|
482 ilstOffset -=4; // ilst box begins at size, 4 bytes back |
|
483 |
|
484 // get ilst size |
|
485 TPtrC8 sizeIlstDesc = des.Mid(ilstOffset, 4); |
|
486 TUint32 sizeIlst = 0; |
|
487 for(TInt i = 0 ; i <= 3; i++) |
|
488 { |
|
489 sizeIlst <<= 8; |
|
490 sizeIlst |= sizeIlstDesc[i]; |
|
491 } |
|
492 if(sizeIlst <= 0 || sizeIlst > bufferSize - ilstOffset) |
|
493 { |
|
494 CleanupStack::PopAndDestroy(); // frame |
|
495 return EFalse; // no list box |
|
496 } |
|
497 |
|
498 // ilst |
|
499 TPtrC8 tmp = des.Mid(ilstOffset, sizeIlst); |
|
500 const TUint8* tmpPtr = tmp.Ptr(); |
|
501 ilst.Set(tmpPtr, sizeIlst); |
|
502 iExists = ETrue; |
|
503 |
|
504 ParseIlstBoxesL(); |
|
505 CleanupStack::PopAndDestroy(); // frame |
|
506 return ETrue; |
|
507 } |
|
508 |
|
509 // ----------------------------------------------------------------------------- |
|
510 // 3GPExtParser::MapID3v1GenreToString() |
|
511 // ----------------------------------------------------------------------------- |
|
512 // |
|
513 void C3GPExtParser::ParseIlstBoxesL() |
|
514 { |
|
515 #ifdef _DEBUG |
|
516 RDebug::Print(_L("C3GPExtParser::ParseIlstBoxesL")); |
|
517 #endif |
|
518 |
|
519 TUint32 sizeIlst = ilst.Length(); |
|
520 TUint32 offset = 8; // first tag |
|
521 while (offset < sizeIlst) |
|
522 { |
|
523 TUint32 tagSize = 0; |
|
524 TPtrC8 tagSizeDes = ilst.Mid(offset, 4); |
|
525 for(TInt i = 0 ; i <= 3; i++) |
|
526 { |
|
527 tagSize <<= 8; |
|
528 tagSize |= tagSizeDes[i]; |
|
529 } |
|
530 TPtrC8 tagName = ilst.Mid(offset + 4, 4); |
|
531 TUint32 dataSize = 0; |
|
532 TPtrC8 dataSizeDesc = ilst.Mid(offset + 8, 4); |
|
533 for(TInt i = 0 ; i <= 3; i++) |
|
534 { |
|
535 dataSize <<= 8; |
|
536 dataSize |= dataSizeDesc[i]; |
|
537 } |
|
538 if(dataSize > 16) |
|
539 { |
|
540 if(!tagName.Compare(K3GPExtMetaTitle)) |
|
541 { |
|
542 iTitleOffset = offset + 8 + 16; |
|
543 iTitleSize = dataSize - 16; |
|
544 } |
|
545 else if(!tagName.Compare(K3GPExtMetaArtist)) |
|
546 { |
|
547 iArtistOffset = offset + 8 + 16; |
|
548 iArtistSize = dataSize - 16; |
|
549 } |
|
550 else if(!tagName.Compare(K3GPExtMetaComposer)) |
|
551 { |
|
552 iComposerOffset = offset + 8 + 16; |
|
553 iComposerSize = dataSize - 16; |
|
554 } |
|
555 else if(!tagName.Compare(K3GPExtMetaAlbum)) |
|
556 { |
|
557 iAlbumOffset = offset + 8 + 16; |
|
558 iAlbumSize = dataSize - 16; |
|
559 } |
|
560 else if(!tagName.Compare(K3GPExtMetaComment)) |
|
561 { |
|
562 iCommentOffset = offset + 8 + 16; |
|
563 iCommentSize = dataSize - 16; |
|
564 } |
|
565 else if(!tagName.Compare(K3GPExtMetaYear)) |
|
566 { |
|
567 iYearOffset = offset + 8 + 16; |
|
568 iYearSize = dataSize - 16; |
|
569 } |
|
570 else if(!tagName.Compare(K3GPExtMetaCustomGenre)) |
|
571 { |
|
572 iCustomGenreOffset = offset + 8 + 16; |
|
573 iCustomGenreSize = dataSize - 16; |
|
574 } |
|
575 else if(!tagName.Compare(K3GPExtMetaGenre)) |
|
576 { |
|
577 iGenreOffset = offset + 8 + 16; |
|
578 iGenreSize = dataSize - 16; |
|
579 } |
|
580 else if(!tagName.Compare(K3GPExtMetaTrack)) |
|
581 { |
|
582 iTrackNumberOffset = offset + 8 + 16; |
|
583 iTrackNumberSize = dataSize - 16; |
|
584 } |
|
585 else if(!tagName.Compare(K3GPExtMetaJpeg)) |
|
586 { |
|
587 iCoverOffset = offset + 8 + 16; |
|
588 iCoverSize = dataSize - 16; |
|
589 } |
|
590 else // default |
|
591 { |
|
592 // unwanted tag, ignore |
|
593 } |
|
594 } |
|
595 if (tagSize <= 0) |
|
596 { |
|
597 #ifdef _DEBUG |
|
598 RDebug::Print(_L("C3GPExtParser::ParseIlstBoxesL - break")); |
|
599 #endif |
|
600 |
|
601 break; |
|
602 } |
|
603 else |
|
604 { |
|
605 offset += tagSize; |
|
606 } |
|
607 } |
|
608 } |
|
609 |
|
610 // ----------------------------------------------------------------------------- |
|
611 // 3GPExtParser::MapID3v1GenreToString() |
|
612 // ----------------------------------------------------------------------------- |
|
613 // |
|
614 void C3GPExtParser::MapID3GenreToString(TInt aNum, TDes& aGenrePtr) |
|
615 { |
|
616 #ifdef _DEBUG |
|
617 RDebug::Print(_L("C3GPExtParser::MapID3GenreToString")); |
|
618 #endif |
|
619 |
|
620 switch(aNum) |
|
621 { |
|
622 case 0: |
|
623 aGenrePtr.Append(KGenreBlues); |
|
624 break; |
|
625 case 1: |
|
626 aGenrePtr.Append(KGenreClassicRock); |
|
627 break; |
|
628 case 2: |
|
629 aGenrePtr.Append(KGenreCountry); |
|
630 break; |
|
631 case 3: |
|
632 aGenrePtr.Append(KGenreDance); |
|
633 break; |
|
634 case 4: |
|
635 aGenrePtr.Append(KGenreDisco); |
|
636 break; |
|
637 case 5: |
|
638 aGenrePtr.Append(KGenreFunk); |
|
639 break; |
|
640 case 6: |
|
641 aGenrePtr.Append(KGenreGrunge); |
|
642 break; |
|
643 case 7: |
|
644 aGenrePtr.Append(KGenreHipHop); |
|
645 break; |
|
646 case 8: |
|
647 aGenrePtr.Append(KGenreJazz); |
|
648 break; |
|
649 case 9: |
|
650 aGenrePtr.Append(KGenreMetal); |
|
651 break; |
|
652 case 10: |
|
653 aGenrePtr.Append(KGenreNewAge); |
|
654 break; |
|
655 case 11: |
|
656 aGenrePtr.Append(KGenreOldies); |
|
657 break; |
|
658 case 12: |
|
659 aGenrePtr.Append(KGenreOther); |
|
660 break; |
|
661 case 13: |
|
662 aGenrePtr.Append(KGenrePop); |
|
663 break; |
|
664 case 14: |
|
665 aGenrePtr.Append(KGenreRB); |
|
666 break; |
|
667 case 15: |
|
668 aGenrePtr.Append(KGenreRap); |
|
669 break; |
|
670 case 16: |
|
671 aGenrePtr.Append(KGenreReggae); |
|
672 break; |
|
673 case 17: |
|
674 aGenrePtr.Append(KGenreRock); |
|
675 break; |
|
676 case 18: |
|
677 aGenrePtr.Append(KGenreTechno); |
|
678 break; |
|
679 case 19: |
|
680 aGenrePtr.Append(KGenreIndustrial); |
|
681 break; |
|
682 case 20: |
|
683 aGenrePtr.Append(KGenreAlternative); |
|
684 break; |
|
685 case 21: |
|
686 aGenrePtr.Append(KGenreSka); |
|
687 break; |
|
688 case 22: |
|
689 aGenrePtr.Append(KGenreDeathMetal); |
|
690 break; |
|
691 case 23: |
|
692 aGenrePtr.Append(KGenrePranks); |
|
693 break; |
|
694 case 24: |
|
695 aGenrePtr.Append(KGenreSoundtrack); |
|
696 break; |
|
697 case 25: |
|
698 aGenrePtr.Append(KGenreEuroTechno); |
|
699 break; |
|
700 case 26: |
|
701 aGenrePtr.Append(KGenreAmbient); |
|
702 break; |
|
703 case 27: |
|
704 aGenrePtr.Append(KGenreTripHop); |
|
705 break; |
|
706 case 28: |
|
707 aGenrePtr.Append(KGenreVocal); |
|
708 break; |
|
709 case 29: |
|
710 aGenrePtr.Append(KGenreJazzFunk); |
|
711 break; |
|
712 case 30: |
|
713 aGenrePtr.Append(KGenreFusion); |
|
714 break; |
|
715 case 31: |
|
716 aGenrePtr.Append(KGenreTrance); |
|
717 break; |
|
718 case 32: |
|
719 aGenrePtr.Append(KGenreClassical); |
|
720 break; |
|
721 case 33: |
|
722 aGenrePtr.Append(KGenreInstrumental); |
|
723 break; |
|
724 case 34: |
|
725 aGenrePtr.Append(KGenreAcid); |
|
726 break; |
|
727 case 35: |
|
728 aGenrePtr.Append(KGenreHouse); |
|
729 break; |
|
730 case 36: |
|
731 aGenrePtr.Append(KGenreGame); |
|
732 break; |
|
733 case 37: |
|
734 aGenrePtr.Append(KGenreSoundClip); |
|
735 break; |
|
736 case 38: |
|
737 aGenrePtr.Append(KGenreGospel); |
|
738 break; |
|
739 case 39: |
|
740 aGenrePtr.Append(KGenreNoise); |
|
741 break; |
|
742 case 40: |
|
743 aGenrePtr.Append(KGenreAlternRock); |
|
744 break; |
|
745 case 41: |
|
746 aGenrePtr.Append(KGenreBass); |
|
747 break; |
|
748 case 42: |
|
749 aGenrePtr.Append(KGenreSoul); |
|
750 break; |
|
751 case 43: |
|
752 aGenrePtr.Append(KGenrePunk); |
|
753 break; |
|
754 case 44: |
|
755 aGenrePtr.Append(KGenreSpace); |
|
756 break; |
|
757 case 45: |
|
758 aGenrePtr.Append(KGenreMeditative); |
|
759 break; |
|
760 case 46: |
|
761 aGenrePtr.Append(KGenreInstrumentalPop); |
|
762 break; |
|
763 case 47: |
|
764 aGenrePtr.Append(KGenreInstrumentalRock); |
|
765 break; |
|
766 case 48: |
|
767 aGenrePtr.Append(KGenreEthnic); |
|
768 break; |
|
769 case 49: |
|
770 aGenrePtr.Append(KGenreGothic); |
|
771 break; |
|
772 case 50: |
|
773 aGenrePtr.Append(KGenreDarkwave); |
|
774 break; |
|
775 case 51: |
|
776 aGenrePtr.Append(KGenreTechnoIndustrial); |
|
777 break; |
|
778 case 52: |
|
779 aGenrePtr.Append(KGenreElectronic); |
|
780 break; |
|
781 case 53: |
|
782 aGenrePtr.Append(KGenrePopFolk); |
|
783 break; |
|
784 case 54: |
|
785 aGenrePtr.Append(KGenreEurodance); |
|
786 break; |
|
787 case 55: |
|
788 aGenrePtr.Append(KGenreDream); |
|
789 break; |
|
790 case 56: |
|
791 aGenrePtr.Append(KGenreSouthernRock); |
|
792 break; |
|
793 case 57: |
|
794 aGenrePtr.Append(KGenreComedy); |
|
795 break; |
|
796 case 58: |
|
797 aGenrePtr.Append(KGenreCult); |
|
798 break; |
|
799 case 59: |
|
800 aGenrePtr.Append(KGenreGangsta); |
|
801 break; |
|
802 case 60: |
|
803 aGenrePtr.Append(KGenreTop40); |
|
804 break; |
|
805 case 61: |
|
806 aGenrePtr.Append(KGenreChristianRap); |
|
807 break; |
|
808 case 62: |
|
809 aGenrePtr.Append(KGenrePopFunk); |
|
810 break; |
|
811 case 63: |
|
812 aGenrePtr.Append(KGenreJungle); |
|
813 break; |
|
814 case 64: |
|
815 aGenrePtr.Append(KGenreNativeAmerican); |
|
816 break; |
|
817 case 65: |
|
818 aGenrePtr.Append(KGenreCabaret); |
|
819 break; |
|
820 case 66: |
|
821 aGenrePtr.Append(KGenreNewWave); |
|
822 break; |
|
823 case 67: |
|
824 aGenrePtr.Append(KGenrePsychadelic); |
|
825 break; |
|
826 case 68: |
|
827 aGenrePtr.Append(KGenreRave); |
|
828 break; |
|
829 case 69: |
|
830 aGenrePtr.Append(KGenreShowtunes); |
|
831 break; |
|
832 case 70: |
|
833 aGenrePtr.Append(KGenreTrailer); |
|
834 break; |
|
835 case 71: |
|
836 aGenrePtr.Append(KGenreLoFi); |
|
837 break; |
|
838 case 72: |
|
839 aGenrePtr.Append(KGenreTribal); |
|
840 break; |
|
841 case 73: |
|
842 aGenrePtr.Append(KGenreAcidPunk); |
|
843 break; |
|
844 case 74: |
|
845 aGenrePtr.Append(KGenreAcidJazz); |
|
846 break; |
|
847 case 75: |
|
848 aGenrePtr.Append(KGenrePolka); |
|
849 break; |
|
850 case 76: |
|
851 aGenrePtr.Append(KGenreRetro); |
|
852 break; |
|
853 case 77: |
|
854 aGenrePtr.Append(KGenreMusical); |
|
855 break; |
|
856 case 78: |
|
857 aGenrePtr.Append(KGenreRockRoll); |
|
858 break; |
|
859 case 79: |
|
860 aGenrePtr.Append(KGenreHardRock); |
|
861 break; |
|
862 case 80: |
|
863 aGenrePtr.Append(KGenreFolk); |
|
864 break; |
|
865 case 81: |
|
866 aGenrePtr.Append(KGenreFolkRock); |
|
867 break; |
|
868 case 82: |
|
869 aGenrePtr.Append(KGenreNationalFolk); |
|
870 break; |
|
871 case 83: |
|
872 aGenrePtr.Append(KGenreSwing); |
|
873 break; |
|
874 case 84: |
|
875 aGenrePtr.Append(KGenreFastFusion); |
|
876 break; |
|
877 case 85: |
|
878 aGenrePtr.Append(KGenreBebob); |
|
879 break; |
|
880 case 86: |
|
881 aGenrePtr.Append(KGenreLatin); |
|
882 break; |
|
883 case 87: |
|
884 aGenrePtr.Append(KGenreRevival); |
|
885 break; |
|
886 case 88: |
|
887 aGenrePtr.Append(KGenreCeltic); |
|
888 break; |
|
889 case 89: |
|
890 aGenrePtr.Append(KGenreBluegrass); |
|
891 break; |
|
892 case 90: |
|
893 aGenrePtr.Append(KGenreAvantgarde); |
|
894 break; |
|
895 case 91: |
|
896 aGenrePtr.Append(KGenreGothicRock); |
|
897 break; |
|
898 case 92: |
|
899 aGenrePtr.Append(KGenreProgressiveRock); |
|
900 break; |
|
901 case 93: |
|
902 aGenrePtr.Append(KGenrePsychedelicRock); |
|
903 break; |
|
904 case 94: |
|
905 aGenrePtr.Append(KGenreSymphonicRock); |
|
906 break; |
|
907 case 95: |
|
908 aGenrePtr.Append(KGenreSlowRock); |
|
909 break; |
|
910 case 96: |
|
911 aGenrePtr.Append(KGenreBigBand); |
|
912 break; |
|
913 case 97: |
|
914 aGenrePtr.Append(KGenreChorus); |
|
915 break; |
|
916 case 98: |
|
917 aGenrePtr.Append(KGenreEasyListening); |
|
918 break; |
|
919 case 99: |
|
920 aGenrePtr.Append(KGenreAcoustic); |
|
921 break; |
|
922 case 100: |
|
923 aGenrePtr.Append(KGenreHumour); |
|
924 break; |
|
925 case 101: |
|
926 aGenrePtr.Append(KGenreSpeech); |
|
927 break; |
|
928 case 102: |
|
929 aGenrePtr.Append(KGenreChanson); |
|
930 break; |
|
931 case 103: |
|
932 aGenrePtr.Append(KGenreOpera); |
|
933 break; |
|
934 case 104: |
|
935 aGenrePtr.Append(KGenreChamberMusic); |
|
936 break; |
|
937 case 105: |
|
938 aGenrePtr.Append(KGenreSonata); |
|
939 break; |
|
940 case 106: |
|
941 aGenrePtr.Append(KGenreSymphony); |
|
942 break; |
|
943 case 107: |
|
944 aGenrePtr.Append(KGenreBootyBass); |
|
945 break; |
|
946 case 108: |
|
947 aGenrePtr.Append(KGenrePrimus); |
|
948 break; |
|
949 case 109: |
|
950 aGenrePtr.Append(KGenrePornGroove); |
|
951 break; |
|
952 case 110: |
|
953 aGenrePtr.Append(KGenreSatire); |
|
954 break; |
|
955 case 111: |
|
956 aGenrePtr.Append(KGenreSlowJam); |
|
957 break; |
|
958 case 112: |
|
959 aGenrePtr.Append(KGenreClub); |
|
960 break; |
|
961 case 113: |
|
962 aGenrePtr.Append(KGenreTango); |
|
963 break; |
|
964 case 114: |
|
965 aGenrePtr.Append(KGenreSamba); |
|
966 break; |
|
967 case 115: |
|
968 aGenrePtr.Append(KGenreFolklore); |
|
969 break; |
|
970 case 116: |
|
971 aGenrePtr.Append(KGenreBallad); |
|
972 break; |
|
973 case 117: |
|
974 aGenrePtr.Append(KGenrePowerBallad); |
|
975 break; |
|
976 case 118: |
|
977 aGenrePtr.Append(KGenreRhythmicSoul); |
|
978 break; |
|
979 case 119: |
|
980 aGenrePtr.Append(KGenreFreestyle); |
|
981 break; |
|
982 case 120: |
|
983 aGenrePtr.Append(KGenreDuet); |
|
984 break; |
|
985 case 121: |
|
986 aGenrePtr.Append(KGenrePunkRock); |
|
987 break; |
|
988 case 122: |
|
989 aGenrePtr.Append(KGenreDrumSolo); |
|
990 break; |
|
991 case 123: |
|
992 aGenrePtr.Append(KGenreAcapella); |
|
993 break; |
|
994 case 124: |
|
995 aGenrePtr.Append(KGenreEuroHouse); |
|
996 break; |
|
997 case 125: |
|
998 aGenrePtr.Append(KGenreDanceHall); |
|
999 break; |
|
1000 case 199: |
|
1001 aGenrePtr.Append(KGenrePodcast); |
|
1002 break; |
|
1003 default: |
|
1004 break; |
|
1005 } |
|
1006 } |
|
1007 |
|
1008 |
|
1009 // ----------------------------------------------------------------------------- |
|
1010 // 3GPExtParser::TranslateMP4Err |
|
1011 // ----------------------------------------------------------------------------- |
|
1012 // |
|
1013 TInt C3GPExtParser::TranslateMP4Err(MP4Err aError) |
|
1014 { |
|
1015 #ifdef _DEBUG |
|
1016 RDebug::Print(_L("CMetaDataParserMP4::TranslateMP4Err [%d]"), aError); |
|
1017 #endif |
|
1018 TInt err; |
|
1019 switch ( aError ) |
|
1020 { |
|
1021 case MP4_OK: |
|
1022 err = KErrNone; |
|
1023 break; |
|
1024 case MP4_OUT_OF_MEMORY: |
|
1025 err = KErrNoMemory; |
|
1026 break; |
|
1027 case MP4_NOT_AVAILABLE: |
|
1028 err = KErrNotReady; |
|
1029 break; |
|
1030 case MP4_FILE_ERROR: |
|
1031 err = KErrBadHandle; |
|
1032 break; |
|
1033 case MP4_INVALID_TYPE: |
|
1034 err = KErrNotSupported; |
|
1035 break; |
|
1036 case MP4_TIMESCALE_NOT_SET: |
|
1037 err = KErrNotReady; |
|
1038 break; |
|
1039 case MP4_NOT_STREAMABLE: |
|
1040 case MP4_NO_REQUESTED_FRAME: |
|
1041 case MP4_CANT_SEEK: |
|
1042 case MP4_INVALID_INPUT_STREAM: |
|
1043 case MP4_NO_FRAME: |
|
1044 err = KErrArgument; |
|
1045 break; |
|
1046 case MP4_ERROR: |
|
1047 case MP4_FILE_MODE: |
|
1048 case MP4_BUFFER_TOO_SMALL: |
|
1049 case MP4_END_OF_VIDEO: |
|
1050 case MP4_METADATA_ERROR: |
|
1051 case MP4_NO_VIDEO: |
|
1052 case MP4_NO_AUDIO: |
|
1053 err = KErrGeneral; |
|
1054 break; |
|
1055 default: |
|
1056 err = KErrGeneral; |
|
1057 break; |
|
1058 } |
|
1059 return err; |
|
1060 } |
|
1061 // End of File |