mmlibs/mmfw/Recogniser/src/mmruf.cpp
changeset 0 40261b775718
equal deleted inserted replaced
-1:000000000000 0:40261b775718
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "mmruf.h"
       
    17 #include <e32uid.h>
       
    18 
       
    19 #include "constants.h"
       
    20 #include "parsers.h"
       
    21 
       
    22 #ifdef _DEBUG
       
    23 _LIT(KRUFPanic, "MMRUF");
       
    24 static const TInt KReasonNoFunction = 1;
       
    25 #endif
       
    26 
       
    27 //
       
    28 // A table of recognised file formats.
       
    29 // It should be sorted in order of format popularity.
       
    30 //
       
    31 static const TSignature KSigs[] =
       
    32 	{
       
    33 	CUSTOM_SIG(KMimeAAC,		TAACParser::DoRecognise),
       
    34 	CUSTOM_SIG(KMimeMP3,		TMP3Parser::DoRecognise),
       
    35 	CUSTOM_SIG(KMimeMP4_V,		TMPEG4Parser::DoRecognise),
       
    36 	CUSTOM_SIG(KMimeWMV,		TASFParser::DoRecognise),
       
    37 	CUSTOM_SIG(KMimeMPEG2_V,	TMPEG2Parser::DoRecognise),
       
    38 	CUSTOM_SIG(KMimeRM_V,		TRMParser::DoRecognise),
       
    39 	CUSTOM_SIG(KMimeRAM,		TRAMParser::DoRecognise),
       
    40 	CUSTOM_SIG(KMimeSDP,		TSDPParser::DoRecognise),
       
    41 	CUSTOM_SIG(KMimeXPS,		TXPSParser::DoRecognise),
       
    42 	HEADER_SIG(KMimeRA,			KExtRA,			KSigRA),
       
    43 	HEADER_SIG(KMimeAIFF,		KExtAIFF_1,		KSigAIFF),
       
    44 	HEADER_SIG(KMimeAIFF,		KExtAIFF_2,		KSigAIFF),
       
    45 	HEADER_SIG(KMimeAIFF,		KExtAIFF_3,		KSigAIFF),
       
    46 	HEADER_SIG(KMimeAMR,		KExtAMR,		KSigAMR_1),
       
    47 	HEADER_SIG(KMimeAMR,		KExtAMR,		KSigAMR_2),
       
    48 	HEADER_SIG(KMimeAMRWB,		KExtAMRWB,		KSigAMRWB_1),
       
    49 	HEADER_SIG(KMimeAMRWB,		KExtAMRWB,		KSigAMRWB_2),
       
    50 	HEADER_SIG(KMimeAU,			KExtAU,			KSigAU),
       
    51 	HEADER_SIG(KMimeAVI,		KExtAVI,		KSigAVI),
       
    52 	HEADER_SIG(KMimeDIVX,		KExtDIVX,		KSigDIVX_1),
       
    53 	HEADER_SIG(KMimeDIVX,		KExtDIVX,		KSigDIVX_2),
       
    54 	HEADER_SIG(KMimeDLS,		KExtDLS,		KSigDLS),
       
    55 	HEADER_SIG(KMimeFLAC,		KExtFLAC_1,		KSigFLAC),
       
    56 	HEADER_SIG(KMimeFLAC,		KExtFLAC_2,		KSigFLAC),
       
    57 	HEADER_SIG(KMimeGSM,		KExtGSM,		KSigGSM),
       
    58 	HEADER_SIG(KMimeM3U,		KExtM3U,		KSigM3U),
       
    59 	HEADER_SIG(KMimeMID,		KExtMID,		KSigMID),
       
    60 	HEADER_SIG(KMimeMLD,		KExtMLD,		KSigMLD),
       
    61 	HEADER_SIG(KMimeMMF,		KExtMMF,		KSigMMF),
       
    62 	HEADER_SIG(KMimeMXMF,		KExtMXMF,		KSigMXMF),
       
    63 	HEADER_SIG(KMimeOGG,		KExtOGG,		KSigOGG),
       
    64 	HEADER_SIG(KMimeBeatnikRMF, KExtBeatnikRMF, KSigBeatnikRMF),
       
    65 	HEADER_SIG(KMimeSMF,		KExtSMF,		KSigSMF),
       
    66 	HEADER_SIG(KMimeSND,		KExtSND,		KSigSND),
       
    67 	HEADER_SIG(KMimeWAV,		KExtWAV,		KSigWAV_1),
       
    68 	HEADER_SIG(KMimeWAV,		KExtWAV,		KSigWAV_2),
       
    69 	HEADER_SIG(KMimeXMF,		KExtXMF,		KSigXMF),
       
    70 	CUSTOM_SIG(KMimeMAT_V,		TMatroskaParser::DoRecognise),
       
    71 	};
       
    72 
       
    73 static const TInt KDataTypesCount = sizeof(KSigs) / sizeof(TSignature);
       
    74 
       
    75 //
       
    76 // Map all combinations of [ext_match][header_match] to confidence levels.
       
    77 //
       
    78 static const TInt KResultToConfidence[] =
       
    79 	{
       
    80 	KConfNotRecognised,
       
    81 	KConfProbable,
       
    82 	KConfPossible,
       
    83 	KConfCertain
       
    84 	};
       
    85 	
       
    86 //
       
    87 //
       
    88 //
       
    89 const TImplementationProxy ImplementationTable[] =
       
    90 	{
       
    91 	// UID taken from Multimedia's UID allocation table.
       
    92 	IMPLEMENTATION_PROXY_ENTRY(KRecogniserUID, CMMRUF::NewL)
       
    93 	};
       
    94 
       
    95 
       
    96 //
       
    97 //
       
    98 //
       
    99 EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
       
   100     {
       
   101     aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
       
   102     return ImplementationTable;
       
   103     }
       
   104 
       
   105 
       
   106 //
       
   107 //
       
   108 //
       
   109 CMMRUF::CMMRUF()
       
   110  : CApaDataRecognizerType(KMMRUFDLLUid, KRecogniserPriority)
       
   111 	{
       
   112 	iCountDataTypes = KDataTypesCount;
       
   113 	}
       
   114 
       
   115 
       
   116 //
       
   117 //
       
   118 //
       
   119 CMMRUF* CMMRUF::NewL()
       
   120 	{
       
   121 	return new(ELeave)CMMRUF();
       
   122 	}
       
   123 
       
   124 
       
   125 //
       
   126 //
       
   127 //
       
   128 CMMRUF::~CMMRUF()
       
   129 	{
       
   130 	}
       
   131 
       
   132 
       
   133 //
       
   134 //
       
   135 //
       
   136 TUint CMMRUF::PreferredBufSize()
       
   137 	{
       
   138 	return KPreferredBufSize;	
       
   139 	}
       
   140 
       
   141 
       
   142 //
       
   143 // Required for CApaDataRecognizerType parent class.
       
   144 // It creates a mime-type string for the signature at aIndex.
       
   145 //
       
   146 TDataType CMMRUF::SupportedDataTypeL(TInt aIndex) const
       
   147 	{
       
   148 	if ((aIndex < 0) || (aIndex >= KDataTypesCount))
       
   149 		{
       
   150 		User::Leave(KErrArgument);
       
   151 		}
       
   152 
       
   153 	return SupportedDataTypeL(KSigs[aIndex].iMime);
       
   154 	}
       
   155 
       
   156 
       
   157 //
       
   158 //
       
   159 //
       
   160 TDataType CMMRUF::SupportedDataTypeL(const TText8* aMime) const
       
   161 	{
       
   162 	if (aMime == NULL)
       
   163 		{
       
   164 		User::Leave(KErrArgument);
       
   165 		}
       
   166 
       
   167 	return TDataType(TPtrC8(aMime));
       
   168 	}
       
   169 
       
   170 
       
   171 //
       
   172 // Records the matched data type and the confidence.
       
   173 //
       
   174 void CMMRUF::SetDataTypeL(TInt aConfidence, const TText8* aMime)
       
   175 	{
       
   176 	iDataType = SupportedDataTypeL(aMime);
       
   177 	iConfidence = aConfidence;
       
   178 	}
       
   179 
       
   180 
       
   181 //
       
   182 // Utility function for matching file extensions.
       
   183 // Returns 1 if the extensions match, 0 otherwise.
       
   184 //
       
   185 TUint8 CMMRUF::MatchExtension(const TDesC& aFileExt, const TText* aKnownExt) const
       
   186 	{
       
   187 	if (aFileExt.Length() > 0)
       
   188 		{
       
   189 		return ((aFileExt.MatchF(TPtrC(aKnownExt)) != KErrNotFound) ? 1 : 0);
       
   190 		}
       
   191 
       
   192 	return 0;
       
   193 	}
       
   194 
       
   195 
       
   196 //
       
   197 // Utility function for matching known header data.
       
   198 // Returns 1 if the buffer contents match the header, 0 otherwise.
       
   199 //
       
   200 TUint8 CMMRUF::MatchHeader(const TDesC8& aBuffer, const TDesC8& aHeader) const
       
   201 	{
       
   202 	if (aBuffer.Length() > 0)
       
   203 		{
       
   204 		if (aHeader.Length() <= aBuffer.Length())
       
   205 			{
       
   206 			return ((aBuffer.Match(aHeader) != KErrNotFound) ? 1 : 0);
       
   207 			}
       
   208 		}
       
   209 
       
   210 	return 0;
       
   211 	}
       
   212 
       
   213 
       
   214 //
       
   215 // This function is called by AppArc when something needs recognising.
       
   216 //
       
   217 void CMMRUF::DoRecognizeL(const TDesC& aFileName, const TDesC8& aBuffer)
       
   218 	{
       
   219 	TMatch match;
       
   220 	RArray<TMatch> matches;
       
   221 	CleanupClosePushL(matches);
       
   222 
       
   223 	// If a handle to the file is available, AppArc prepends "::" to the
       
   224 	// aFileName parameter for some reason. This causes TParse to fail
       
   225 	// to get the file extension, so we have to fix it.
       
   226 	TPtrC fName(aFileName);
       
   227 	if (aFileName.Match(_L("::*")) == 0)
       
   228  		{
       
   229 		fName.Set(aFileName.Mid(2));
       
   230  		}
       
   231  	
       
   232  	TParse parse;
       
   233 	User::LeaveIfError(parse.Set(fName, NULL, NULL));
       
   234 	const TPtrC& ext = parse.Ext();
       
   235 
       
   236 	RFile* pFile = FilePassedByHandleL();
       
   237 	CReader* pReader = (pFile ? CFileReader::NewLC(pFile) : CBufferReader::NewLC(aBuffer));
       
   238 	
       
   239 	// The main recognition loop.
       
   240 	TBool certainMatch = EFalse;
       
   241 	for (TInt i = 0; (i < KDataTypesCount) && !certainMatch; i++)
       
   242 		{
       
   243 		// Reset the results for each iteration.
       
   244 		pReader->Reset();
       
   245 		match.Reset();
       
   246 
       
   247 		if (KSigs[i].iHeaderLen == 0)
       
   248 			{
       
   249 			// Call the custom recognition function.
       
   250 			// match contains the results.
       
   251 			__ASSERT_DEBUG(KSigs[i].iHeaderOrProc, User::Panic(KRUFPanic, KReasonNoFunction));
       
   252 			TCustomProc proc = (TCustomProc)(KSigs[i].iHeaderOrProc);
       
   253 			proc(ext, *pReader, match);
       
   254 			}
       
   255 		else
       
   256 			{
       
   257 			// This format has a known signature.
       
   258 			TPtrC8 header(_S8(KSigs[i].iHeaderOrProc), KSigs[i].iHeaderLen);
       
   259 			
       
   260 			TUint8 sameHeader = MatchHeader(aBuffer, header);
       
   261 			TUint8 sameExt = MatchExtension(ext, KSigs[i].iExt);
       
   262 			TUint8 confIndex = MAKE_BYTE2(sameExt, sameHeader);
       
   263 
       
   264 			match.iConfidence = KResultToConfidence[confIndex];
       
   265 			match.iMime = KSigs[i].iMime; 
       
   266 			}
       
   267 			
       
   268 		// Evaluate the result.
       
   269 		switch (match.iConfidence)
       
   270 			{
       
   271 			case KConfNotRecognised:
       
   272 				continue;
       
   273 				
       
   274 			case KConfCertain:
       
   275 				certainMatch = ETrue;
       
   276 				// Deliberate fall through to add match to array of matches.
       
   277 
       
   278 			case KConfProbable:
       
   279 				// Add it to the start of the array.
       
   280 				User::LeaveIfError(matches.Insert(TMatch(match), 0));
       
   281 				break;
       
   282 
       
   283 			case KConfPossible:
       
   284 				// Add it to the end of the array.
       
   285 				if (matches.Count() == 0)
       
   286 					{
       
   287 					User::LeaveIfError(matches.Append(TMatch(match)));
       
   288 					}
       
   289 				break;
       
   290 				
       
   291 			default:
       
   292 				// Should never get here.
       
   293 				User::Leave(KErrArgument);
       
   294 			}
       
   295 		}	// for (TInt i = 0; i < KDataTypesCount; i++)
       
   296 
       
   297 	// We've done looping.
       
   298 	if (matches.Count() > 0)
       
   299 		{
       
   300 		match = matches[0];
       
   301 		SetDataTypeL(match.iConfidence, match.iMime);
       
   302 		}
       
   303 
       
   304 	CleanupStack::PopAndDestroy(pReader);
       
   305 	CleanupStack::PopAndDestroy(&matches);
       
   306 	}
       
   307 
       
   308 
       
   309 
       
   310