os/mm/mmlibs/mmfw/Recogniser/src/mmruf.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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