/*
* Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: This class implements an MP4 metadata parser
*
*/
// INCLUDE FILES
#include "MetaDataParserMP4.h"
#ifdef _DEBUG
#include <e32svr.h>
#endif
const TUint KCustomFileBufferSize = 10*1024;
// ============================ MEMBER FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// CMetaDataParserMP4::CMetaDataParserMP4
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CMetaDataParserMP4::CMetaDataParserMP4()
: iMP4Handle(NULL)
{
}
// Destructor
CMetaDataParserMP4::~CMetaDataParserMP4()
{
MP4ParseClose(iMP4Handle);
if ( iExists )
{
delete iCharacterSet;
iFs.Close();
}
}
// -----------------------------------------------------------------------------
// CMetaDataParserMP4::InitializeFileL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CMetaDataParserMP4::InitializeFileL(
ContentAccess::CData *aData )
{
MP4Err err;
//TBuf<256> name(aFileName);
err = MP4ParseOpenCAF(&iMP4Handle, aData);
#ifdef _DEBUG
RDebug::Print(_L("CMetaDataParserMP4::InitializeFileL - MP4ParseOpen err = %d"), err);
#endif
User::LeaveIfError(TranslateMP4Err(err));
MP4SetCustomFileBufferSizes( iMP4Handle, 0, 0, KCustomFileBufferSize);
if ( ValidateL() )
{
User::LeaveIfError(iFs.Connect());
// Get list of charconv supported character sets
iCharacterSet = CCnvCharacterSetConverter::CreateArrayOfCharacterSetsAvailableL(iFs);
}
#ifdef _DEBUG
RDebug::Print(_L("CMetaDataParserMP4::InitializeFileL - Done"));
#endif
}
// -----------------------------------------------------------------------------
// CMetaDataParserMP4::InitializeDesL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CMetaDataParserMP4::InitializeDesL(
const TDesC8& aDes )
{
MP4Err err;
err = MP4ParseOpen(&iMP4Handle, NULL);
#ifdef _DEBUG
RDebug::Print(_L("CMetaDataParserMP4::InitializeDesL - MP4ParseOpen err = %d"), err);
#endif
User::LeaveIfError(TranslateMP4Err(err));
TUint8* buffer = CONST_CAST(TUint8*, aDes.Ptr());
err = MP4ParseWriteData(iMP4Handle, buffer, aDes.Size());
User::LeaveIfError(TranslateMP4Err(err));
// This call with empty buffer indicates to the MP4 library that this is the last buffer.
err = MP4ParseWriteData(iMP4Handle, NULL, 0);
User::LeaveIfError(TranslateMP4Err(err));
if ( ValidateL() )
{
User::LeaveIfError(iFs.Connect());
// Get list of charconv supported character sets
iCharacterSet = CCnvCharacterSetConverter::CreateArrayOfCharacterSetsAvailableL(iFs);
}
#ifdef _DEBUG
RDebug::Print(_L("CMetaDataParserMP4::InitializeDesL - Done"));
#endif
}
// -----------------------------------------------------------------------------
// CMetaDataParserMP4::TranslateMP4Err
// -----------------------------------------------------------------------------
//
TInt CMetaDataParserMP4::TranslateMP4Err(
MP4Err aError )
{
#ifdef _DEBUG
RDebug::Print(_L("CMetaDataParserMP4::TranslateMP4Err [%d]"), aError);
#endif
TInt err;
switch ( aError )
{
case MP4_OK:
err = KErrNone;
break;
case MP4_OUT_OF_MEMORY:
err = KErrNoMemory;
break;
case MP4_NOT_AVAILABLE:
case MP4_UDTA_NOT_FOUND:
err = KErrNotReady;
break;
case MP4_FILE_ERROR:
err = KErrBadHandle;
break;
case MP4_INVALID_TYPE:
err = KErrNotSupported;
break;
case MP4_TIMESCALE_NOT_SET:
err = KErrNotReady;
break;
case MP4_NOT_STREAMABLE:
case MP4_NO_REQUESTED_FRAME:
case MP4_CANT_SEEK:
case MP4_INVALID_INPUT_STREAM:
case MP4_NO_FRAME:
err = KErrArgument;
break;
case MP4_ERROR:
case MP4_FILE_MODE:
case MP4_BUFFER_TOO_SMALL:
case MP4_END_OF_VIDEO:
case MP4_METADATA_ERROR:
case MP4_NO_VIDEO:
case MP4_NO_AUDIO:
err = KErrGeneral;
break;
default:
err = KErrGeneral;
break;
}
return err;
}
// -----------------------------------------------------------------------------
// CMetaDataParserMP4::GetDurationL
// -----------------------------------------------------------------------------
//
void CMetaDataParserMP4::GetDurationL(
TMetaDataFieldId aFieldId )
{
#ifdef _DEBUG
RDebug::Print(_L("CMetaDataParser3gp::GetDurationL"));
#endif
MP4Err err;
mp4_u32 audiolength = 0;
mp4_u32 audiotype = 0;
mp4_u8 framespersample = 0;
mp4_u32 timescale = 0;
mp4_u32 averagebitrate = 0;
err = MP4ParseRequestAudioDescription(iMP4Handle, &audiolength, &audiotype, &framespersample, ×cale, &averagebitrate);
if(err == MP4_OK)
{
TBuf16<10> data16;
TReal duration = (TReal)audiolength / 1000; // seconds
TRealFormat realFormat(9, 3);
data16.AppendNum(duration, realFormat);
iContainer->AppendL( aFieldId, data16);
}
}
// -----------------------------------------------------------------------------
// CMetaDataParserMP4::ConvertToUnicodeL
// -----------------------------------------------------------------------------
//
TInt CMetaDataParserMP4::ConvertToUnicodeL(
const TDesC8& aDesc,
TDes16& aUnicode )
{
TPtrC8 unicodeData;
TUint characterSetId = 0;
CCnvCharacterSetConverter* charSetConv = CCnvCharacterSetConverter::NewLC();
TInt state = CCnvCharacterSetConverter::KStateDefault;
TInt bom = UnicodeBOM(aDesc);
if ( bom == KUnicodeBOMBigEndian )
{
// UTF-16 Big Endian with BOM
// characterSetId = KCharacterSetIdentifierUcs2;
TPtrC8 text = StripTrailingZeroes(aDesc, 1);
characterSetId = KCharacterSetIdentifierUnicodeBig;
// Skip BOM & Terminate marks
unicodeData.Set( text.Mid(2) );
}
else if ( bom == KUnicodeBOMLittleEndian )
{
// UTF-16 Big Endian with BOM
characterSetId = KCharacterSetIdentifierUnicodeLittle;
TPtrC8 text = StripTrailingZeroes(aDesc, 1);
// Skip BOM & Terminate marks
unicodeData.Set( text.Mid( 2) );
}
else // KUnicodeBOMNotFound
{
// UTF-8
TPtrC8 text = StripTrailingZeroes(aDesc, 0);
characterSetId = KCharacterSetIdentifierUtf8;
unicodeData.Set( text );
}
charSetConv->PrepareToConvertToOrFromL(characterSetId, *iCharacterSet, iFs);
TInt err = charSetConv->ConvertToUnicode(aUnicode, unicodeData, state);
#ifdef _DEBUG
RDebug::Print(_L("CMetaDataParserID3v24::ConvertToUnicode :-> Tag Size[%d] Unicode Tag Size[%d]Bytes Unconverted[%d]"),
unicodeData.Length(), aUnicode.Length(), err);
#endif
CleanupStack::PopAndDestroy(); // charSetConv
return err;
}
// End of File