1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/mm/mmlibs/mmfw/Recogniser/src/mmruf.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,310 @@
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 "mmruf.h"
1.20 +#include <e32uid.h>
1.21 +
1.22 +#include "constants.h"
1.23 +#include "parsers.h"
1.24 +
1.25 +#ifdef _DEBUG
1.26 +_LIT(KRUFPanic, "MMRUF");
1.27 +static const TInt KReasonNoFunction = 1;
1.28 +#endif
1.29 +
1.30 +//
1.31 +// A table of recognised file formats.
1.32 +// It should be sorted in order of format popularity.
1.33 +//
1.34 +static const TSignature KSigs[] =
1.35 + {
1.36 + CUSTOM_SIG(KMimeAAC, TAACParser::DoRecognise),
1.37 + CUSTOM_SIG(KMimeMP3, TMP3Parser::DoRecognise),
1.38 + CUSTOM_SIG(KMimeMP4_V, TMPEG4Parser::DoRecognise),
1.39 + CUSTOM_SIG(KMimeWMV, TASFParser::DoRecognise),
1.40 + CUSTOM_SIG(KMimeMPEG2_V, TMPEG2Parser::DoRecognise),
1.41 + CUSTOM_SIG(KMimeRM_V, TRMParser::DoRecognise),
1.42 + CUSTOM_SIG(KMimeRAM, TRAMParser::DoRecognise),
1.43 + CUSTOM_SIG(KMimeSDP, TSDPParser::DoRecognise),
1.44 + CUSTOM_SIG(KMimeXPS, TXPSParser::DoRecognise),
1.45 + HEADER_SIG(KMimeRA, KExtRA, KSigRA),
1.46 + HEADER_SIG(KMimeAIFF, KExtAIFF_1, KSigAIFF),
1.47 + HEADER_SIG(KMimeAIFF, KExtAIFF_2, KSigAIFF),
1.48 + HEADER_SIG(KMimeAIFF, KExtAIFF_3, KSigAIFF),
1.49 + HEADER_SIG(KMimeAMR, KExtAMR, KSigAMR_1),
1.50 + HEADER_SIG(KMimeAMR, KExtAMR, KSigAMR_2),
1.51 + HEADER_SIG(KMimeAMRWB, KExtAMRWB, KSigAMRWB_1),
1.52 + HEADER_SIG(KMimeAMRWB, KExtAMRWB, KSigAMRWB_2),
1.53 + HEADER_SIG(KMimeAU, KExtAU, KSigAU),
1.54 + HEADER_SIG(KMimeAVI, KExtAVI, KSigAVI),
1.55 + HEADER_SIG(KMimeDIVX, KExtDIVX, KSigDIVX_1),
1.56 + HEADER_SIG(KMimeDIVX, KExtDIVX, KSigDIVX_2),
1.57 + HEADER_SIG(KMimeDLS, KExtDLS, KSigDLS),
1.58 + HEADER_SIG(KMimeFLAC, KExtFLAC_1, KSigFLAC),
1.59 + HEADER_SIG(KMimeFLAC, KExtFLAC_2, KSigFLAC),
1.60 + HEADER_SIG(KMimeGSM, KExtGSM, KSigGSM),
1.61 + HEADER_SIG(KMimeM3U, KExtM3U, KSigM3U),
1.62 + HEADER_SIG(KMimeMID, KExtMID, KSigMID),
1.63 + HEADER_SIG(KMimeMLD, KExtMLD, KSigMLD),
1.64 + HEADER_SIG(KMimeMMF, KExtMMF, KSigMMF),
1.65 + HEADER_SIG(KMimeMXMF, KExtMXMF, KSigMXMF),
1.66 + HEADER_SIG(KMimeOGG, KExtOGG, KSigOGG),
1.67 + HEADER_SIG(KMimeBeatnikRMF, KExtBeatnikRMF, KSigBeatnikRMF),
1.68 + HEADER_SIG(KMimeSMF, KExtSMF, KSigSMF),
1.69 + HEADER_SIG(KMimeSND, KExtSND, KSigSND),
1.70 + HEADER_SIG(KMimeWAV, KExtWAV, KSigWAV_1),
1.71 + HEADER_SIG(KMimeWAV, KExtWAV, KSigWAV_2),
1.72 + HEADER_SIG(KMimeXMF, KExtXMF, KSigXMF),
1.73 + CUSTOM_SIG(KMimeMAT_V, TMatroskaParser::DoRecognise),
1.74 + };
1.75 +
1.76 +static const TInt KDataTypesCount = sizeof(KSigs) / sizeof(TSignature);
1.77 +
1.78 +//
1.79 +// Map all combinations of [ext_match][header_match] to confidence levels.
1.80 +//
1.81 +static const TInt KResultToConfidence[] =
1.82 + {
1.83 + KConfNotRecognised,
1.84 + KConfProbable,
1.85 + KConfPossible,
1.86 + KConfCertain
1.87 + };
1.88 +
1.89 +//
1.90 +//
1.91 +//
1.92 +const TImplementationProxy ImplementationTable[] =
1.93 + {
1.94 + // UID taken from Multimedia's UID allocation table.
1.95 + IMPLEMENTATION_PROXY_ENTRY(KRecogniserUID, CMMRUF::NewL)
1.96 + };
1.97 +
1.98 +
1.99 +//
1.100 +//
1.101 +//
1.102 +EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
1.103 + {
1.104 + aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
1.105 + return ImplementationTable;
1.106 + }
1.107 +
1.108 +
1.109 +//
1.110 +//
1.111 +//
1.112 +CMMRUF::CMMRUF()
1.113 + : CApaDataRecognizerType(KMMRUFDLLUid, KRecogniserPriority)
1.114 + {
1.115 + iCountDataTypes = KDataTypesCount;
1.116 + }
1.117 +
1.118 +
1.119 +//
1.120 +//
1.121 +//
1.122 +CMMRUF* CMMRUF::NewL()
1.123 + {
1.124 + return new(ELeave)CMMRUF();
1.125 + }
1.126 +
1.127 +
1.128 +//
1.129 +//
1.130 +//
1.131 +CMMRUF::~CMMRUF()
1.132 + {
1.133 + }
1.134 +
1.135 +
1.136 +//
1.137 +//
1.138 +//
1.139 +TUint CMMRUF::PreferredBufSize()
1.140 + {
1.141 + return KPreferredBufSize;
1.142 + }
1.143 +
1.144 +
1.145 +//
1.146 +// Required for CApaDataRecognizerType parent class.
1.147 +// It creates a mime-type string for the signature at aIndex.
1.148 +//
1.149 +TDataType CMMRUF::SupportedDataTypeL(TInt aIndex) const
1.150 + {
1.151 + if ((aIndex < 0) || (aIndex >= KDataTypesCount))
1.152 + {
1.153 + User::Leave(KErrArgument);
1.154 + }
1.155 +
1.156 + return SupportedDataTypeL(KSigs[aIndex].iMime);
1.157 + }
1.158 +
1.159 +
1.160 +//
1.161 +//
1.162 +//
1.163 +TDataType CMMRUF::SupportedDataTypeL(const TText8* aMime) const
1.164 + {
1.165 + if (aMime == NULL)
1.166 + {
1.167 + User::Leave(KErrArgument);
1.168 + }
1.169 +
1.170 + return TDataType(TPtrC8(aMime));
1.171 + }
1.172 +
1.173 +
1.174 +//
1.175 +// Records the matched data type and the confidence.
1.176 +//
1.177 +void CMMRUF::SetDataTypeL(TInt aConfidence, const TText8* aMime)
1.178 + {
1.179 + iDataType = SupportedDataTypeL(aMime);
1.180 + iConfidence = aConfidence;
1.181 + }
1.182 +
1.183 +
1.184 +//
1.185 +// Utility function for matching file extensions.
1.186 +// Returns 1 if the extensions match, 0 otherwise.
1.187 +//
1.188 +TUint8 CMMRUF::MatchExtension(const TDesC& aFileExt, const TText* aKnownExt) const
1.189 + {
1.190 + if (aFileExt.Length() > 0)
1.191 + {
1.192 + return ((aFileExt.MatchF(TPtrC(aKnownExt)) != KErrNotFound) ? 1 : 0);
1.193 + }
1.194 +
1.195 + return 0;
1.196 + }
1.197 +
1.198 +
1.199 +//
1.200 +// Utility function for matching known header data.
1.201 +// Returns 1 if the buffer contents match the header, 0 otherwise.
1.202 +//
1.203 +TUint8 CMMRUF::MatchHeader(const TDesC8& aBuffer, const TDesC8& aHeader) const
1.204 + {
1.205 + if (aBuffer.Length() > 0)
1.206 + {
1.207 + if (aHeader.Length() <= aBuffer.Length())
1.208 + {
1.209 + return ((aBuffer.Match(aHeader) != KErrNotFound) ? 1 : 0);
1.210 + }
1.211 + }
1.212 +
1.213 + return 0;
1.214 + }
1.215 +
1.216 +
1.217 +//
1.218 +// This function is called by AppArc when something needs recognising.
1.219 +//
1.220 +void CMMRUF::DoRecognizeL(const TDesC& aFileName, const TDesC8& aBuffer)
1.221 + {
1.222 + TMatch match;
1.223 + RArray<TMatch> matches;
1.224 + CleanupClosePushL(matches);
1.225 +
1.226 + // If a handle to the file is available, AppArc prepends "::" to the
1.227 + // aFileName parameter for some reason. This causes TParse to fail
1.228 + // to get the file extension, so we have to fix it.
1.229 + TPtrC fName(aFileName);
1.230 + if (aFileName.Match(_L("::*")) == 0)
1.231 + {
1.232 + fName.Set(aFileName.Mid(2));
1.233 + }
1.234 +
1.235 + TParse parse;
1.236 + User::LeaveIfError(parse.Set(fName, NULL, NULL));
1.237 + const TPtrC& ext = parse.Ext();
1.238 +
1.239 + RFile* pFile = FilePassedByHandleL();
1.240 + CReader* pReader = (pFile ? CFileReader::NewLC(pFile) : CBufferReader::NewLC(aBuffer));
1.241 +
1.242 + // The main recognition loop.
1.243 + TBool certainMatch = EFalse;
1.244 + for (TInt i = 0; (i < KDataTypesCount) && !certainMatch; i++)
1.245 + {
1.246 + // Reset the results for each iteration.
1.247 + pReader->Reset();
1.248 + match.Reset();
1.249 +
1.250 + if (KSigs[i].iHeaderLen == 0)
1.251 + {
1.252 + // Call the custom recognition function.
1.253 + // match contains the results.
1.254 + __ASSERT_DEBUG(KSigs[i].iHeaderOrProc, User::Panic(KRUFPanic, KReasonNoFunction));
1.255 + TCustomProc proc = (TCustomProc)(KSigs[i].iHeaderOrProc);
1.256 + proc(ext, *pReader, match);
1.257 + }
1.258 + else
1.259 + {
1.260 + // This format has a known signature.
1.261 + TPtrC8 header(_S8(KSigs[i].iHeaderOrProc), KSigs[i].iHeaderLen);
1.262 +
1.263 + TUint8 sameHeader = MatchHeader(aBuffer, header);
1.264 + TUint8 sameExt = MatchExtension(ext, KSigs[i].iExt);
1.265 + TUint8 confIndex = MAKE_BYTE2(sameExt, sameHeader);
1.266 +
1.267 + match.iConfidence = KResultToConfidence[confIndex];
1.268 + match.iMime = KSigs[i].iMime;
1.269 + }
1.270 +
1.271 + // Evaluate the result.
1.272 + switch (match.iConfidence)
1.273 + {
1.274 + case KConfNotRecognised:
1.275 + continue;
1.276 +
1.277 + case KConfCertain:
1.278 + certainMatch = ETrue;
1.279 + // Deliberate fall through to add match to array of matches.
1.280 +
1.281 + case KConfProbable:
1.282 + // Add it to the start of the array.
1.283 + User::LeaveIfError(matches.Insert(TMatch(match), 0));
1.284 + break;
1.285 +
1.286 + case KConfPossible:
1.287 + // Add it to the end of the array.
1.288 + if (matches.Count() == 0)
1.289 + {
1.290 + User::LeaveIfError(matches.Append(TMatch(match)));
1.291 + }
1.292 + break;
1.293 +
1.294 + default:
1.295 + // Should never get here.
1.296 + User::Leave(KErrArgument);
1.297 + }
1.298 + } // for (TInt i = 0; i < KDataTypesCount; i++)
1.299 +
1.300 + // We've done looping.
1.301 + if (matches.Count() > 0)
1.302 + {
1.303 + match = matches[0];
1.304 + SetDataTypeL(match.iConfidence, match.iMime);
1.305 + }
1.306 +
1.307 + CleanupStack::PopAndDestroy(pReader);
1.308 + CleanupStack::PopAndDestroy(&matches);
1.309 + }
1.310 +
1.311 +
1.312 +
1.313 +