os/mm/mmlibs/mmfw/Recogniser/src/rmparser.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/mm/mmlibs/mmfw/Recogniser/src/rmparser.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,238 @@
     1.4 +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +#include "parsers.h"
    1.20 +
    1.21 +static const TUint32 KRMFileHeaderId = MAKE_INT32('.', 'R', 'M', 'F');
    1.22 +static const TUint32 KRMMediaPropertiesId = MAKE_INT32('M', 'D', 'P', 'R');
    1.23 +static const TInt KRMMaxMimeTypeLen = 255;	// Specified by an 8-bit field
    1.24 +
    1.25 +#define KRMExtensionBit			KBit0
    1.26 +#define KRMFileHeaderBit		KBit1
    1.27 +#define KRMMediaPropertiesBit	KBit2
    1.28 +#define KRMVideoBit				KBit3
    1.29 +
    1.30 +#define KRMVideoMask			0x08	// 0000 1000
    1.31 +#define KRMConfidenceMask 		0x07	// 0000 0111
    1.32 +
    1.33 +//
    1.34 +// This truth table maps the following flags to a confidence level.
    1.35 +// -----------------------------------------------------------------
    1.36 +// A: MediaProperties chunk found
    1.37 +// B: FileHeader signature found
    1.38 +// C: Extension recognised.
    1.39 +//
    1.40 +// A B C -> Confidence
    1.41 +// ===================
    1.42 +// 0 0 0 -> ENotRecognized
    1.43 +// 0 0 1 -> EPossible
    1.44 +// 0 1 0 -> EPossible (EPossible beacuse the header is ASCII and may match plaintext)
    1.45 +// 0 1 1 -> ECertain
    1.46 +// 1 0 0 -> ENotRecognised (Can't have MediaProperties without FileHeader)
    1.47 +// 1 0 1 -> ENotRecognised (Can't have MediaProperties without FileHeader)
    1.48 +// 1 1 0 -> EProbable
    1.49 +// 1 1 1 -> ECertain
    1.50 +//
    1.51 +static const TInt KRMFlagsToConfidence[] =
    1.52 +	{
    1.53 +	KConfNotRecognised,
    1.54 +	KConfPossible,
    1.55 +	KConfPossible,
    1.56 +	KConfCertain,
    1.57 +	KConfNotRecognised,
    1.58 +	KConfNotRecognised,
    1.59 +	KConfProbable,
    1.60 +	KConfCertain
    1.61 +	};
    1.62 +
    1.63 +
    1.64 +//
    1.65 +// Constructor.
    1.66 +//
    1.67 +TRMParser::TRMParser(CReader& aReader, TFlags& aFlags)
    1.68 + :	iReader(aReader),
    1.69 +	iFlags(aFlags)
    1.70 +	{
    1.71 +	}
    1.72 +
    1.73 +
    1.74 +//
    1.75 +// The main RealMedia parsing function.
    1.76 +//
    1.77 +void TRMParser::DoRecognise(const TDesC& aFileExt, CReader& aReader, TMatch& aMatch)
    1.78 +	{
    1.79 +	TFlags flags;
    1.80 +	TRMParser parser(aReader, flags);
    1.81 +
    1.82 +	parser.MatchExtension(aFileExt);
    1.83 +
    1.84 +	TRAP_IGNORE(parser.ParseL());
    1.85 +
    1.86 +	TInt confIndex = flags.GetBitField(KRMConfidenceMask);
    1.87 +	aMatch.iConfidence = KRMFlagsToConfidence[confIndex];
    1.88 +
    1.89 +	if (aMatch.iConfidence != KConfNotRecognised)
    1.90 +		{
    1.91 +		aMatch.iMime = (flags.GetBitField(KRMVideoMask) ? KMimeRM_V : KMimeRM_A);
    1.92 +		}
    1.93 +	}
    1.94 +
    1.95 +
    1.96 +//
    1.97 +// Match the file extension given by AppArc against known
    1.98 +// extensions for this format.
    1.99 +//
   1.100 +void TRMParser::MatchExtension(const TDesC& aFileExt)
   1.101 +	{
   1.102 +	TBool match;
   1.103 +
   1.104 +	match = (aFileExt.MatchF(TPtrC(KExtRMF)) != KErrNotFound);
   1.105 +	match |= (aFileExt.MatchF(TPtrC(KExtRM)) != KErrNotFound);
   1.106 +
   1.107 +	if (match)
   1.108 +		{
   1.109 +		iFlags.SetExtensionFlag();
   1.110 +		}
   1.111 +	}
   1.112 +
   1.113 +//
   1.114 +// RealMedia files are divided into chunks. Chunks begins with a 32-bit identifier
   1.115 +// which is followed by a 32-bit unsigned field that specifies the size of the chunk
   1.116 +// in bytes. Since the size field is unsigned, it must be cast to a TInt64 in order
   1.117 +// for SeekL() to work reliably. The size field also includes the length of the chunk
   1.118 +// identifier and the length of the size field itself, so these must be subtracted
   1.119 +// from any seek operation.
   1.120 +//
   1.121 +void TRMParser::ParseL()
   1.122 +	{
   1.123 +	TUint32 objectId;
   1.124 +	TUint32 size;
   1.125 +	const TInt KChunkHeaderSize = sizeof(TUint32) * 2; // sizeof objectId and size fields.
   1.126 +
   1.127 +	// The first chunk must be the FileHeader.
   1.128 +	ReadChunkHeaderL(objectId, size, ETrue);
   1.129 +
   1.130 +	// Assume there's video content if we only have buffer data.
   1.131 +	if (iReader.Type() == CReader::EBuffer)
   1.132 +		{
   1.133 +		iFlags.SetBit(KRMVideoBit);
   1.134 +		}
   1.135 +
   1.136 +	iReader.SeekL(TInt64(size - KChunkHeaderSize));
   1.137 +
   1.138 +	// The other chunks can occur in any order.
   1.139 +	TBool complete = EFalse;
   1.140 +	do
   1.141 +		{
   1.142 +		ReadChunkHeaderL(objectId, size);
   1.143 +
   1.144 +		if (objectId == KRMMediaPropertiesId)
   1.145 +			{
   1.146 +			iFlags.SetBit(KRMMediaPropertiesBit);
   1.147 +			if (ReadMediaPropertiesL())
   1.148 +				{
   1.149 +				// Exit early if the video flag has been set by ReadMediaPropertiesL.
   1.150 +				complete = ETrue;
   1.151 +				}
   1.152 +			}
   1.153 +		else
   1.154 +			{
   1.155 +			// Skip over the unneeded chunk.
   1.156 +			iReader.SeekL(TInt64(size - KChunkHeaderSize));
   1.157 +			}
   1.158 +		}
   1.159 +	while (!complete);
   1.160 +	}
   1.161 +
   1.162 +
   1.163 +//
   1.164 +// Reads the chunk identifier and size.
   1.165 +//
   1.166 +void TRMParser::ReadChunkHeaderL(TUint32& aObjectId, TUint32& aSize, TBool aFirstChunk)
   1.167 +	{
   1.168 +	iReader.Read32L(aObjectId);
   1.169 +
   1.170 +	if (aFirstChunk)
   1.171 +		{
   1.172 +		if (aObjectId == KRMFileHeaderId)
   1.173 +			{
   1.174 +			iFlags.SetBit(KRMFileHeaderBit);
   1.175 +			}
   1.176 +		else
   1.177 +			{
   1.178 +			User::Leave(KErrCorrupt);
   1.179 +			}
   1.180 +		}
   1.181 +
   1.182 +	iReader.Read32L(aSize);
   1.183 +	if (aSize == 0)
   1.184 +		{
   1.185 +		User::Leave(KErrCorrupt);
   1.186 +		}
   1.187 +	}
   1.188 +
   1.189 +
   1.190 +//
   1.191 +// The MediaProperties chunk describes a stream in the RM file. There
   1.192 +// may be several MediaProperties chunks in one file. In order to determine
   1.193 +// if video content is present we must look at the MIME-type that may
   1.194 +// be present in each MediaProperties chunk.
   1.195 +// Return ETrue if this function set the video bit.
   1.196 +//
   1.197 +TBool TRMParser::ReadMediaPropertiesL()
   1.198 +	{
   1.199 +	const TInt KBytesToFieldSize = 30;
   1.200 +	
   1.201 +	// ObjectId and size fields have already been read.
   1.202 +	TBool setVideo = EFalse;
   1.203 +	TUint16 objectVersion;
   1.204 +
   1.205 +	iReader.Read16L(objectVersion);
   1.206 +
   1.207 +	if (objectVersion == 0)
   1.208 +		{
   1.209 +		TUint8 fieldSize;
   1.210 +		TBuf8<KRMMaxMimeTypeLen> mimeType;
   1.211 +		_LIT8(KVideoStar, "video/*");
   1.212 +
   1.213 +		// Skip unneeded information.
   1.214 +		iReader.SeekL(KBytesToFieldSize);
   1.215 +
   1.216 +		// Read stream_name_size so we can skip over it.
   1.217 +		iReader.ReadByteL(fieldSize);
   1.218 +		iReader.SeekL(fieldSize);
   1.219 +
   1.220 +		// Read the mime_type_size. Because it's 8-bit, it has a max length of 256 bytes.
   1.221 +		iReader.ReadByteL(fieldSize);
   1.222 +
   1.223 +		mimeType.SetLength(fieldSize);
   1.224 +		iReader.ReadBytesL(mimeType);
   1.225 +
   1.226 +		// Now check if the mime-type field indicates video content.
   1.227 +		if (mimeType.MatchF(KVideoStar) != KErrNotFound)
   1.228 +			{
   1.229 +			iFlags.SetBit(KRMVideoBit);
   1.230 +			setVideo = ETrue;
   1.231 +			}
   1.232 +
   1.233 +		// Read the type_specific_len so we can skip over it.
   1.234 +		TUint32 typeSpecificLen;
   1.235 +		iReader.Read32L(typeSpecificLen);
   1.236 +		iReader.SeekL(TInt64(typeSpecificLen));
   1.237 +		}
   1.238 +
   1.239 +	return setVideo;
   1.240 +	}
   1.241 +