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