mmlibs/mmfw/Recogniser/src/mmruf.cpp
changeset 0 b8ed18f6c07b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmlibs/mmfw/Recogniser/src/mmruf.cpp	Thu Oct 07 22:34:12 2010 +0100
@@ -0,0 +1,310 @@
+// 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 "mmruf.h"
+#include <e32uid.h>
+
+#include "constants.h"
+#include "parsers.h"
+
+#ifdef _DEBUG
+_LIT(KRUFPanic, "MMRUF");
+static const TInt KReasonNoFunction = 1;
+#endif
+
+//
+// A table of recognised file formats.
+// It should be sorted in order of format popularity.
+//
+static const TSignature KSigs[] =
+	{
+	CUSTOM_SIG(KMimeAAC,		TAACParser::DoRecognise),
+	CUSTOM_SIG(KMimeMP3,		TMP3Parser::DoRecognise),
+	CUSTOM_SIG(KMimeMP4_V,		TMPEG4Parser::DoRecognise),
+	CUSTOM_SIG(KMimeWMV,		TASFParser::DoRecognise),
+	CUSTOM_SIG(KMimeMPEG2_V,	TMPEG2Parser::DoRecognise),
+	CUSTOM_SIG(KMimeRM_V,		TRMParser::DoRecognise),
+	CUSTOM_SIG(KMimeRAM,		TRAMParser::DoRecognise),
+	CUSTOM_SIG(KMimeSDP,		TSDPParser::DoRecognise),
+	CUSTOM_SIG(KMimeXPS,		TXPSParser::DoRecognise),
+	HEADER_SIG(KMimeRA,			KExtRA,			KSigRA),
+	HEADER_SIG(KMimeAIFF,		KExtAIFF_1,		KSigAIFF),
+	HEADER_SIG(KMimeAIFF,		KExtAIFF_2,		KSigAIFF),
+	HEADER_SIG(KMimeAIFF,		KExtAIFF_3,		KSigAIFF),
+	HEADER_SIG(KMimeAMR,		KExtAMR,		KSigAMR_1),
+	HEADER_SIG(KMimeAMR,		KExtAMR,		KSigAMR_2),
+	HEADER_SIG(KMimeAMRWB,		KExtAMRWB,		KSigAMRWB_1),
+	HEADER_SIG(KMimeAMRWB,		KExtAMRWB,		KSigAMRWB_2),
+	HEADER_SIG(KMimeAU,			KExtAU,			KSigAU),
+	HEADER_SIG(KMimeAVI,		KExtAVI,		KSigAVI),
+	HEADER_SIG(KMimeDIVX,		KExtDIVX,		KSigDIVX_1),
+	HEADER_SIG(KMimeDIVX,		KExtDIVX,		KSigDIVX_2),
+	HEADER_SIG(KMimeDLS,		KExtDLS,		KSigDLS),
+	HEADER_SIG(KMimeFLAC,		KExtFLAC_1,		KSigFLAC),
+	HEADER_SIG(KMimeFLAC,		KExtFLAC_2,		KSigFLAC),
+	HEADER_SIG(KMimeGSM,		KExtGSM,		KSigGSM),
+	HEADER_SIG(KMimeM3U,		KExtM3U,		KSigM3U),
+	HEADER_SIG(KMimeMID,		KExtMID,		KSigMID),
+	HEADER_SIG(KMimeMLD,		KExtMLD,		KSigMLD),
+	HEADER_SIG(KMimeMMF,		KExtMMF,		KSigMMF),
+	HEADER_SIG(KMimeMXMF,		KExtMXMF,		KSigMXMF),
+	HEADER_SIG(KMimeOGG,		KExtOGG,		KSigOGG),
+	HEADER_SIG(KMimeBeatnikRMF, KExtBeatnikRMF, KSigBeatnikRMF),
+	HEADER_SIG(KMimeSMF,		KExtSMF,		KSigSMF),
+	HEADER_SIG(KMimeSND,		KExtSND,		KSigSND),
+	HEADER_SIG(KMimeWAV,		KExtWAV,		KSigWAV_1),
+	HEADER_SIG(KMimeWAV,		KExtWAV,		KSigWAV_2),
+	HEADER_SIG(KMimeXMF,		KExtXMF,		KSigXMF),
+	CUSTOM_SIG(KMimeMAT_V,		TMatroskaParser::DoRecognise),
+	};
+
+static const TInt KDataTypesCount = sizeof(KSigs) / sizeof(TSignature);
+
+//
+// Map all combinations of [ext_match][header_match] to confidence levels.
+//
+static const TInt KResultToConfidence[] =
+	{
+	KConfNotRecognised,
+	KConfProbable,
+	KConfPossible,
+	KConfCertain
+	};
+	
+//
+//
+//
+const TImplementationProxy ImplementationTable[] =
+	{
+	// UID taken from Multimedia's UID allocation table.
+	IMPLEMENTATION_PROXY_ENTRY(KRecogniserUID, CMMRUF::NewL)
+	};
+
+
+//
+//
+//
+EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
+    {
+    aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
+    return ImplementationTable;
+    }
+
+
+//
+//
+//
+CMMRUF::CMMRUF()
+ : CApaDataRecognizerType(KMMRUFDLLUid, KRecogniserPriority)
+	{
+	iCountDataTypes = KDataTypesCount;
+	}
+
+
+//
+//
+//
+CMMRUF* CMMRUF::NewL()
+	{
+	return new(ELeave)CMMRUF();
+	}
+
+
+//
+//
+//
+CMMRUF::~CMMRUF()
+	{
+	}
+
+
+//
+//
+//
+TUint CMMRUF::PreferredBufSize()
+	{
+	return KPreferredBufSize;	
+	}
+
+
+//
+// Required for CApaDataRecognizerType parent class.
+// It creates a mime-type string for the signature at aIndex.
+//
+TDataType CMMRUF::SupportedDataTypeL(TInt aIndex) const
+	{
+	if ((aIndex < 0) || (aIndex >= KDataTypesCount))
+		{
+		User::Leave(KErrArgument);
+		}
+
+	return SupportedDataTypeL(KSigs[aIndex].iMime);
+	}
+
+
+//
+//
+//
+TDataType CMMRUF::SupportedDataTypeL(const TText8* aMime) const
+	{
+	if (aMime == NULL)
+		{
+		User::Leave(KErrArgument);
+		}
+
+	return TDataType(TPtrC8(aMime));
+	}
+
+
+//
+// Records the matched data type and the confidence.
+//
+void CMMRUF::SetDataTypeL(TInt aConfidence, const TText8* aMime)
+	{
+	iDataType = SupportedDataTypeL(aMime);
+	iConfidence = aConfidence;
+	}
+
+
+//
+// Utility function for matching file extensions.
+// Returns 1 if the extensions match, 0 otherwise.
+//
+TUint8 CMMRUF::MatchExtension(const TDesC& aFileExt, const TText* aKnownExt) const
+	{
+	if (aFileExt.Length() > 0)
+		{
+		return ((aFileExt.MatchF(TPtrC(aKnownExt)) != KErrNotFound) ? 1 : 0);
+		}
+
+	return 0;
+	}
+
+
+//
+// Utility function for matching known header data.
+// Returns 1 if the buffer contents match the header, 0 otherwise.
+//
+TUint8 CMMRUF::MatchHeader(const TDesC8& aBuffer, const TDesC8& aHeader) const
+	{
+	if (aBuffer.Length() > 0)
+		{
+		if (aHeader.Length() <= aBuffer.Length())
+			{
+			return ((aBuffer.Match(aHeader) != KErrNotFound) ? 1 : 0);
+			}
+		}
+
+	return 0;
+	}
+
+
+//
+// This function is called by AppArc when something needs recognising.
+//
+void CMMRUF::DoRecognizeL(const TDesC& aFileName, const TDesC8& aBuffer)
+	{
+	TMatch match;
+	RArray<TMatch> matches;
+	CleanupClosePushL(matches);
+
+	// If a handle to the file is available, AppArc prepends "::" to the
+	// aFileName parameter for some reason. This causes TParse to fail
+	// to get the file extension, so we have to fix it.
+	TPtrC fName(aFileName);
+	if (aFileName.Match(_L("::*")) == 0)
+ 		{
+		fName.Set(aFileName.Mid(2));
+ 		}
+ 	
+ 	TParse parse;
+	User::LeaveIfError(parse.Set(fName, NULL, NULL));
+	const TPtrC& ext = parse.Ext();
+
+	RFile* pFile = FilePassedByHandleL();
+	CReader* pReader = (pFile ? CFileReader::NewLC(pFile) : CBufferReader::NewLC(aBuffer));
+	
+	// The main recognition loop.
+	TBool certainMatch = EFalse;
+	for (TInt i = 0; (i < KDataTypesCount) && !certainMatch; i++)
+		{
+		// Reset the results for each iteration.
+		pReader->Reset();
+		match.Reset();
+
+		if (KSigs[i].iHeaderLen == 0)
+			{
+			// Call the custom recognition function.
+			// match contains the results.
+			__ASSERT_DEBUG(KSigs[i].iHeaderOrProc, User::Panic(KRUFPanic, KReasonNoFunction));
+			TCustomProc proc = (TCustomProc)(KSigs[i].iHeaderOrProc);
+			proc(ext, *pReader, match);
+			}
+		else
+			{
+			// This format has a known signature.
+			TPtrC8 header(_S8(KSigs[i].iHeaderOrProc), KSigs[i].iHeaderLen);
+			
+			TUint8 sameHeader = MatchHeader(aBuffer, header);
+			TUint8 sameExt = MatchExtension(ext, KSigs[i].iExt);
+			TUint8 confIndex = MAKE_BYTE2(sameExt, sameHeader);
+
+			match.iConfidence = KResultToConfidence[confIndex];
+			match.iMime = KSigs[i].iMime; 
+			}
+			
+		// Evaluate the result.
+		switch (match.iConfidence)
+			{
+			case KConfNotRecognised:
+				continue;
+				
+			case KConfCertain:
+				certainMatch = ETrue;
+				// Deliberate fall through to add match to array of matches.
+
+			case KConfProbable:
+				// Add it to the start of the array.
+				User::LeaveIfError(matches.Insert(TMatch(match), 0));
+				break;
+
+			case KConfPossible:
+				// Add it to the end of the array.
+				if (matches.Count() == 0)
+					{
+					User::LeaveIfError(matches.Append(TMatch(match)));
+					}
+				break;
+				
+			default:
+				// Should never get here.
+				User::Leave(KErrArgument);
+			}
+		}	// for (TInt i = 0; i < KDataTypesCount; i++)
+
+	// We've done looping.
+	if (matches.Count() > 0)
+		{
+		match = matches[0];
+		SetDataTypeL(match.iConfidence, match.iMime);
+		}
+
+	CleanupStack::PopAndDestroy(pReader);
+	CleanupStack::PopAndDestroy(&matches);
+	}
+
+
+
+