diff -r 000000000000 -r b8ed18f6c07b mmlibs/mmfw/Recogniser/src/rmparser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mmlibs/mmfw/Recogniser/src/rmparser.cpp Thu Oct 07 22:34:12 2010 +0100 @@ -0,0 +1,238 @@ +// Copyright (c) 2006-2009 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: +// + +#include "parsers.h" + +static const TUint32 KRMFileHeaderId = MAKE_INT32('.', 'R', 'M', 'F'); +static const TUint32 KRMMediaPropertiesId = MAKE_INT32('M', 'D', 'P', 'R'); +static const TInt KRMMaxMimeTypeLen = 255; // Specified by an 8-bit field + +#define KRMExtensionBit KBit0 +#define KRMFileHeaderBit KBit1 +#define KRMMediaPropertiesBit KBit2 +#define KRMVideoBit KBit3 + +#define KRMVideoMask 0x08 // 0000 1000 +#define KRMConfidenceMask 0x07 // 0000 0111 + +// +// This truth table maps the following flags to a confidence level. +// ----------------------------------------------------------------- +// A: MediaProperties chunk found +// B: FileHeader signature found +// C: Extension recognised. +// +// A B C -> Confidence +// =================== +// 0 0 0 -> ENotRecognized +// 0 0 1 -> EPossible +// 0 1 0 -> EPossible (EPossible beacuse the header is ASCII and may match plaintext) +// 0 1 1 -> ECertain +// 1 0 0 -> ENotRecognised (Can't have MediaProperties without FileHeader) +// 1 0 1 -> ENotRecognised (Can't have MediaProperties without FileHeader) +// 1 1 0 -> EProbable +// 1 1 1 -> ECertain +// +static const TInt KRMFlagsToConfidence[] = + { + KConfNotRecognised, + KConfPossible, + KConfPossible, + KConfCertain, + KConfNotRecognised, + KConfNotRecognised, + KConfProbable, + KConfCertain + }; + + +// +// Constructor. +// +TRMParser::TRMParser(CReader& aReader, TFlags& aFlags) + : iReader(aReader), + iFlags(aFlags) + { + } + + +// +// The main RealMedia parsing function. +// +void TRMParser::DoRecognise(const TDesC& aFileExt, CReader& aReader, TMatch& aMatch) + { + TFlags flags; + TRMParser parser(aReader, flags); + + parser.MatchExtension(aFileExt); + + TRAP_IGNORE(parser.ParseL()); + + TInt confIndex = flags.GetBitField(KRMConfidenceMask); + aMatch.iConfidence = KRMFlagsToConfidence[confIndex]; + + if (aMatch.iConfidence != KConfNotRecognised) + { + aMatch.iMime = (flags.GetBitField(KRMVideoMask) ? KMimeRM_V : KMimeRM_A); + } + } + + +// +// Match the file extension given by AppArc against known +// extensions for this format. +// +void TRMParser::MatchExtension(const TDesC& aFileExt) + { + TBool match; + + match = (aFileExt.MatchF(TPtrC(KExtRMF)) != KErrNotFound); + match |= (aFileExt.MatchF(TPtrC(KExtRM)) != KErrNotFound); + + if (match) + { + iFlags.SetExtensionFlag(); + } + } + +// +// RealMedia files are divided into chunks. Chunks begins with a 32-bit identifier +// which is followed by a 32-bit unsigned field that specifies the size of the chunk +// in bytes. Since the size field is unsigned, it must be cast to a TInt64 in order +// for SeekL() to work reliably. The size field also includes the length of the chunk +// identifier and the length of the size field itself, so these must be subtracted +// from any seek operation. +// +void TRMParser::ParseL() + { + TUint32 objectId; + TUint32 size; + const TInt KChunkHeaderSize = sizeof(TUint32) * 2; // sizeof objectId and size fields. + + // The first chunk must be the FileHeader. + ReadChunkHeaderL(objectId, size, ETrue); + + // Assume there's video content if we only have buffer data. + if (iReader.Type() == CReader::EBuffer) + { + iFlags.SetBit(KRMVideoBit); + } + + iReader.SeekL(TInt64(size - KChunkHeaderSize)); + + // The other chunks can occur in any order. + TBool complete = EFalse; + do + { + ReadChunkHeaderL(objectId, size); + + if (objectId == KRMMediaPropertiesId) + { + iFlags.SetBit(KRMMediaPropertiesBit); + if (ReadMediaPropertiesL()) + { + // Exit early if the video flag has been set by ReadMediaPropertiesL. + complete = ETrue; + } + } + else + { + // Skip over the unneeded chunk. + iReader.SeekL(TInt64(size - KChunkHeaderSize)); + } + } + while (!complete); + } + + +// +// Reads the chunk identifier and size. +// +void TRMParser::ReadChunkHeaderL(TUint32& aObjectId, TUint32& aSize, TBool aFirstChunk) + { + iReader.Read32L(aObjectId); + + if (aFirstChunk) + { + if (aObjectId == KRMFileHeaderId) + { + iFlags.SetBit(KRMFileHeaderBit); + } + else + { + User::Leave(KErrCorrupt); + } + } + + iReader.Read32L(aSize); + if (aSize == 0) + { + User::Leave(KErrCorrupt); + } + } + + +// +// The MediaProperties chunk describes a stream in the RM file. There +// may be several MediaProperties chunks in one file. In order to determine +// if video content is present we must look at the MIME-type that may +// be present in each MediaProperties chunk. +// Return ETrue if this function set the video bit. +// +TBool TRMParser::ReadMediaPropertiesL() + { + const TInt KBytesToFieldSize = 30; + + // ObjectId and size fields have already been read. + TBool setVideo = EFalse; + TUint16 objectVersion; + + iReader.Read16L(objectVersion); + + if (objectVersion == 0) + { + TUint8 fieldSize; + TBuf8 mimeType; + _LIT8(KVideoStar, "video/*"); + + // Skip unneeded information. + iReader.SeekL(KBytesToFieldSize); + + // Read stream_name_size so we can skip over it. + iReader.ReadByteL(fieldSize); + iReader.SeekL(fieldSize); + + // Read the mime_type_size. Because it's 8-bit, it has a max length of 256 bytes. + iReader.ReadByteL(fieldSize); + + mimeType.SetLength(fieldSize); + iReader.ReadBytesL(mimeType); + + // Now check if the mime-type field indicates video content. + if (mimeType.MatchF(KVideoStar) != KErrNotFound) + { + iFlags.SetBit(KRMVideoBit); + setVideo = ETrue; + } + + // Read the type_specific_len so we can skip over it. + TUint32 typeSpecificLen; + iReader.Read32L(typeSpecificLen); + iReader.SeekL(TInt64(typeSpecificLen)); + } + + return setVideo; + } +