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 +