--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmlibs/mmfw/Recogniser/src/rmparser.cpp Tue Feb 02 01:56:55 2010 +0200
@@ -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<KRMMaxMimeTypeLen> 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;
+ }
+