mmserv/metadatautility/3GPExtParserLib/src/3GPExtParser.cpp
changeset 55 e267340986c9
equal deleted inserted replaced
52:4ce423f34688 55:e267340986c9
       
     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