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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 #include "constants.h"
20 // Matroska 'XML' tags.
22 static const TUint32 KEBML = 0x1A45DFA3;
23 static const TUint32 KSegment = 0x18538067;
24 static const TUint32 KTracks = 0x1654AE6B;
25 static const TUint32 KTrackEntry = 0xAE;
26 static const TUint32 KTrackType = 0x83;
27 static const TUint32 KVoid = 0xEC;
28 static const TUint32 KSeekHead = 0x114D9B74;
29 static const TUint32 KSegmentInfo = 0x1549A966;
30 static const TUint32 KCluster = 0x1F43B675;
31 static const TUint32 KCues = 0x1C53BB6B;
32 static const TUint32 KAttachments = 0x1941A469;
33 static const TUint32 KChapters = 0x1043A770;
34 static const TUint32 KTags = 0x1254C367;
37 // Matroska Track Types.
39 static const TUint8 KTrackTypeVideo = 0x01;
41 #define KMatroskaConfidenceMask 0x07 // 00000111
42 #define KMatroskaEBMLBit KBit1
43 #define KMatroskaSegmentBit KBit2
44 #define KMatroskaVideoBit KBit3
48 // This truth table maps the following flags to confidence levels.
50 // A: Extension match.
52 // C: Segment tag found.
54 // C B A -> Confidence
55 // --------------------
56 // 0 0 0 -> NotRecognised
60 // 1 0 0 -> ENotRecognised (EBML should be present)
61 // 1 0 1 -> ENotRecognised (EBML should be present)
65 static const TInt KMatroskaFlagsToConfidence[8] =
77 static const TInt KMatExtensionOnlyIndex = 1; // See truth table.
88 // Known Matroska extensions and their corresponding MIME-types.
90 static const TMatroskaExt KMatroskaExt[] =
92 {KExtMAT_A, KMimeMAT_A },
93 {KExtMAT_V, KMimeMAT_V }
96 static const TInt KMatroskaExtCount = sizeof(KMatroskaExt) / sizeof(TMatroskaExt);
102 TMatroskaParser::TMatroskaParser(CReader& aReader, TFlags& aFlags)
112 const TText8* TMatroskaParser::MatchExtension(const TDesC& aExt)
114 for (TInt i = 0; i < KMatroskaExtCount; i++)
116 if (aExt.MatchF(TPtrC(KMatroskaExt[i].iExt)) != KErrNotFound)
118 return KMatroskaExt[i].iMime;
127 // This function calls the parser and turns the results
130 void TMatroskaParser::DoRecognise(const TDesC& aExt, CReader& aReader, TMatch& aMatch)
133 TMatroskaParser parser(aReader, flags);
135 // Try to match the extension.
136 const TText8* extMime = parser.MatchExtension(aExt);
139 flags.SetExtensionFlag();
142 // Try to parse the content.
143 TRAP_IGNORE(parser.ParseL());
144 TInt confIndex = flags.GetBitField(KMatroskaConfidenceMask);
145 aMatch.iConfidence = KMatroskaFlagsToConfidence[confIndex];
146 if (aMatch.iConfidence != KConfNotRecognised)
148 // If any header data has been recognised trust that,
149 // otherwise go with the extension.
150 if (confIndex == KMatExtensionOnlyIndex)
152 aMatch.iMime = extMime;
156 aMatch.iMime = (flags.GetBitField(KMatroskaVideoBit) ? KMimeMAT_V : KMimeMAT_A);
163 // This function does the parsing.
165 void TMatroskaParser::ParseL()
169 TBool haveElement = EFalse;
171 // Assume there's video content if we only have buffer data.
172 if (iReader.Type() == CReader::EBuffer)
174 iFlags.SetBit(KMatroskaVideoBit);
181 ReadElementL(id, size);
187 iFlags.SetBit(KMatroskaEBMLBit);
191 haveElement = ReadSegmentL(id, size);
203 // This function returns ETrue if the aNextID and aNextSize parameters
204 // contain valid values, EFalse otherwise.
206 TBool TMatroskaParser::ReadSegmentL(TUint64& aNextID, TInt64& aNextSize)
210 TBool videoContent = EFalse;
215 iFlags.SetBit(KMatroskaSegmentBit);
217 while (!videoContent)
219 ReadElementL(id, size);
224 videoContent = ReadTrackL(size);
238 // Unrecognised element id. Pass it back to the caller
245 // Tell the caller they must read the next element themselves.
251 // The Track. This lets us know if there's video content present.
253 TBool TMatroskaParser::ReadTrackL(TInt64 aTrackSize)
257 TInt startPos = iReader.Position();
259 while (iReader.Position() - startPos < aTrackSize)
261 ReadElementL(id, size);
270 iReader.ReadByteL(trackType);
271 if (trackType == KTrackTypeVideo)
273 // We found video content so we can stop parsing.
274 iFlags.SetBit(KMatroskaVideoBit);
291 void TMatroskaParser::ReadElementL(TUint64& aElementID, TInt64& aSize)
295 aElementID = ReadDataL();
296 aSize = ReadDataL(ETrue);
298 // Void elements are used for padding and
300 if (aElementID == KVoid)
302 iReader.SeekL(aSize);
305 while (aElementID == KVoid);
312 TUint64 TMatroskaParser::ReadDataL(TBool aTurnOffHighestSetBit)
316 TUint8 mask = 0x80; // [1000 0000]. It will be shifted right 1 in each 'i' iteration.
317 TUint8 size = 1; // It will be incremented in each 'i' iteration.
319 iReader.ReadByteL(byte);
321 for (TInt i = 0; i < sizeof(TUint64); i++)
326 if (aTurnOffHighestSetBit)
328 retval &= ~mask; // Turn off the highest set bit.
331 // Now read the real data.
332 // Start from 1 because we've already read a byte.
333 for (TInt j = 1; j < size; j++)
335 iReader.ReadByteL(byte);
349 User::Leave(KErrCorrupt);
350 return 0; // Keep the compiler happy.