mmlibs/mmfw/Recogniser/src/aacparser.cpp
changeset 0 40261b775718
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmlibs/mmfw/Recogniser/src/aacparser.cpp	Tue Feb 02 01:56:55 2010 +0200
@@ -0,0 +1,226 @@
+// 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 "constants.h"
+#include "parsers.h"
+
+// The length of the frame in written directly into the header.
+// It is 13 bits in length and spans 3 bytes.
+
+#define AAC_SYNC1_MASK				0xff	// 11111111
+#define AAC_SYNC2_MASK				0xf0	// 11110000
+#define AAC_FRAME_LENGTH_MASK1		0x03	// 00000011
+#define AAC_FRAME_LENGTH_MASK2		0xff	// 11111111
+#define AAC_FRAME_LENGTH_MASK3		0xe0	// 11100000
+#define AAC_LAYER_MASK				0x06	// 00000110
+
+#define AAC_GET_SYNC1(d)	(d)
+#define AAC_GET_SYNC2(d)	((d & AAC_SYNC2_MASK) >> 4)
+#define AAC_GET_LAYER(d)	(((d) & AAC_LAYER_MASK) >> 1)
+#define AAC_GET_FRAME_LENGTH(a, b, c) \
+							(((a) & AAC_FRAME_LENGTH_MASK1) << 11) | \
+							(((b) & AAC_FRAME_LENGTH_MASK2) << 03) | \
+							(((c) & AAC_FRAME_LENGTH_MASK3) >> 05)
+							
+
+#define AAC_IS_BAD_SYNC1(s)			((s) != 0xff)
+#define AAC_IS_BAD_SYNC2(s)			((s) != 0x0f)
+#define AAC_IS_BAD_LAYER(l)			((l) != 0x00)
+#define AAC_IS_BAD_FRAME_LENGTH(l)	((l) < KAACFrameHeaderSize)
+
+//
+// The various states the recognition process goes through.
+//
+typedef enum
+	{
+	ESearchFrame1,
+	ESearchFrame2
+	}
+TAACState;
+
+//
+// This truth table maps the following flags to a confidence level.
+//
+// A: Extension identified.
+// B: Frame1 found.
+// C: Frame2 found.
+//
+// C B A -> Confidence
+// ===================
+// 0 0 0 -> ENotRecognised
+// 0 0 1 -> EPossible
+// 0 1 0 -> EProbable
+// 0 1 1 -> ECertain
+// 1 0 0 -> ENotRecognised (Can't have f2 without f1)
+// 1 0 1 -> ENotRecognised (Can't have f2 without f1)
+// 1 1 0 -> EProbable
+// 1 1 1 -> ECertain
+//
+static const TInt KAACFlagsToConfidence[8] =
+	{
+	KConfNotRecognised,
+	KConfPossible,
+	KConfProbable,
+	KConfCertain,
+	KConfNotRecognised,
+	KConfNotRecognised,
+	KConfProbable,
+	KConfCertain
+	};
+	
+#define KAACConfidenceMask	0x07	// [0000 0111]
+#define KAACFrame1Bit		KBit1
+#define KAACFrame2Bit		KBit2
+
+
+
+//
+// Constructs a TAACParser on the stack.
+//
+TAACParser::TAACParser(CReader& aReader, TFlags& aFlags)
+ :	iReader(aReader),
+ 	iFlags(aFlags)
+	{
+	}
+
+
+//
+//
+//
+void TAACParser::DoRecognise(const TDesC& aFileExt, CReader& aReader, TMatch& aMatch)
+	{
+	TFlags flags;
+	TBool extMatch;
+	
+	// See if the extension is recognised.
+	extMatch = (aFileExt.MatchF(TPtrC(KExtAAC)) != KErrNotFound);
+	
+	// Try to match a known header.
+	if (aReader.Match(TPtrC8(_S8("ADIF*"))))
+		{
+		aMatch.iConfidence = (extMatch ? KConfCertain : KConfProbable);
+		aMatch.iMime = KMimeAAC;
+		return;
+		}
+	
+	// No known header so try to parse it.
+	// Parsing uses flags to track what has been identified.
+	if (extMatch)
+		{
+		flags.SetExtensionFlag();
+		}
+	
+	TAACParser parser(aReader, flags);
+	TRAP_IGNORE(parser.ParseL());
+	
+	TInt confIndex = flags.GetBitField(KAACConfidenceMask);
+	aMatch.iConfidence = KAACFlagsToConfidence[confIndex];
+	if (aMatch.iConfidence != KConfNotRecognised)
+		{
+		aMatch.iMime = KMimeAAC;
+		}
+	}
+
+
+//
+// Looks for valid AAC frame headers; at the current position
+// and immediately after (if one found).
+//
+void TAACParser::ParseL()
+	{
+	TInt frameLength;
+	TAACState state = ESearchFrame1;
+	
+	// Check if it's an ADTS (raw) format AAC file.
+	// There's no known metadata tag for AAC so the
+	// first frame header should be at the start of the buffer.
+	
+	FOREVER
+		{
+		TID3Parser::ReadAndSkipID3L(iReader);
+		
+		TInt err = CheckForFrameHeaderL(frameLength);
+		if (err == KErrNotFound)
+			{
+			return;
+			}
+			
+		switch (state)
+			{
+			case ESearchFrame1:
+				iFlags.SetBit(KAACFrame1Bit);
+				state = ESearchFrame2;
+				break;
+					
+			case ESearchFrame2:
+				iFlags.SetBit(KAACFrame2Bit);
+				return;
+			}
+		
+		// Skip over the audio frame.
+		// This should be done after flags have been set.
+		iReader.SeekL(frameLength - KAACFrameHeaderSize);
+		};
+	}
+
+
+//
+// Looks for valid AAC frame header bit patterns.
+// If one is not found KErrNotFound is returned and aFrameLength
+// remains unchanged. If one is found KErrNone is retured and
+// aFrameLength is set to the length of the frame.
+//
+TInt TAACParser::CheckForFrameHeaderL(TInt& aFrameLength)
+	{
+	TBuf8<KAACFrameHeaderSize> header;
+	
+	header.SetLength(KAACFrameHeaderSize);
+	iReader.ReadBytesL(header);
+	
+	do
+		{
+		if (AAC_IS_BAD_SYNC1(AAC_GET_SYNC1(header[0])))
+			{
+			break;
+			}
+			
+		if (AAC_IS_BAD_SYNC2(AAC_GET_SYNC2(header[1])))
+			{
+			break;
+			}
+			
+		if (AAC_IS_BAD_LAYER(AAC_GET_LAYER(header[1])))
+			{
+			break;
+			}
+			
+		TInt frameLength = AAC_GET_FRAME_LENGTH(header[3], header[4], header[5]);
+		if (AAC_IS_BAD_FRAME_LENGTH(frameLength))
+			{
+			break;
+			}
+		// All is ok.
+		aFrameLength = frameLength;
+		return KErrNone;
+		}
+	while (EFalse);
+	
+	// No frame header was found.
+	aFrameLength = 0;
+	iReader.SeekL(-KAACFrameHeaderSize);
+	return KErrNotFound;
+	}
+	
+