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"
19 #define KASFAudioMedia "\xF8\x69\x9E\x40\x5B\x4D\x11\xCF\xA8\xFD\x00\x80\x5F\x5C\x44\x2B"
20 #define KASFVideoMedia "\xBC\x19\xEF\xC0\x5B\x4D\x11\xCF\xA8\xFD\x00\x80\x5F\x5C\x44\x2B"
21 #define KASFHeaderObject "\x75\xB2\x26\x30\x66\x8E\x11\xCF\xA6\xD9\x00\xAA\x00\x62\xCE\x6C"
22 #define KASFStreamPropertiesObject "\xB7\xDC\x07\x91\xA9\xB7\x11\xCF\x8E\xE6\x00\xC0\x0C\x20\x53\x65"
23 #define KASFCodecListObject "\x86\xD1\x52\x40\x31\x1D\x11\xD0\xA3\xA4\x00\xA0\xC9\x03\x48\xF6"
26 static const TInt KGUIDLen = 16; // 128-bit
27 static const TInt KObjectLen = KGUIDLen + 8; // GUID followed by 64-bit size.
28 static const TInt KMinObjectLen = 30; // From documentation
34 const TText8* iVideoMime;
35 const TText8* iAudioMime;
41 // Various ASF container MIME-types.
43 static const TASFType KASFTypes[] =
45 {KExtWMA, KMimeWMA, KMimeWMA},
46 {KExtWMV, KMimeWMV, KMimeWMV},
47 {KExtASF, KMimeASF_V, KMimeASF_A}
50 #define KASFTypesCount sizeof(KASFTypes) / sizeof(TASFType)
53 #define KASFHeaderObjectBit KBit1 // 00000001
54 #define KASFStreamHeaderBit KBit2 // 00000010
55 #define KASFVideoBit KBit3 // 00000100
56 #define KASFConfidenceMask 0x07 // 00000111
59 // Flags mapped to confidence levels.
61 // A: Extension identified.
62 // B: HeaderObject GUID
63 // C: StreamProperties GUID
65 // C B A -> Confidence
66 // -------------------
67 // 0 0 0 -> ENotRecognised
71 // 1 0 0 -> ENotRecognised (StreamProperties occurs within HeaderObject)
72 // 1 0 1 -> ENotRecognised (StreamProperties occurs within HeaderObject)
76 static const TInt KASFFlagsToConfidence[8] =
92 TASFParser::TASFParser(CReader& aReader, TFlags& aFlags)
100 // Sets the mime-type the file extension implies.
102 const TText8* TASFParser::MatchExtension(const TDesC& aExt, TBool aVideo)
104 for (TInt i = 0; i < KASFTypesCount; i++)
106 if (aExt.MatchF(TPtrC(KASFTypes[i].iExt)) != KErrNotFound)
108 return (aVideo ? KASFTypes[i].iVideoMime : KASFTypes[i].iAudioMime);
119 void TASFParser::DoRecognise(const TDesC& aExt, CReader& aReader, TMatch& aMatch)
122 TASFParser parser(aReader, flags);
124 // We need to parse first to determine if there's video content present.
125 TRAPD(err, parser.ParseL());
126 if (err == KErrCorrupt)
128 // Unrecognised content. However the extension may allow
129 // correct identification so assume there's video content.
130 flags.SetBit(KASFVideoBit);
133 const TText8* extMime = parser.MatchExtension(aExt, flags.GetBitField(KASFVideoBit));
136 // The extension was recognised.
137 flags.SetExtensionFlag();
140 TInt confIndex = flags.GetBitField(KASFConfidenceMask);
141 aMatch.iConfidence = KASFFlagsToConfidence[confIndex];
142 if (aMatch.iConfidence != KConfNotRecognised)
144 // Trust the mime-type the extension maps to.
145 // If the extension wasn't recognised, but the content was
146 // then return the generic ASF mime type. ASF format files
147 // can't be identified from their content; just whether they
148 // contain video or not.
149 aMatch.iMime = extMime;
150 if (aMatch.iMime == NULL)
152 aMatch.iMime = (flags.GetBitField(KASFVideoBit) ? KMimeASF_V : KMimeASF_A);
161 void TASFParser::ParseL()
163 // ASF files are logically composed of three types of top-level objects:
164 // the Header Object, the Data Object, and the Index Object(s).
165 // The Header Object is mandatory and must be placed at the beginning of every
166 // ASF file. The Data Object is also mandatory and must follow the Header Object.
167 // The Index Object(s) are optional, but they are useful in providing time-based
168 // random access into ASF files. When present, the Index Object(s) must be the
169 // last object in the ASF file.
171 TBuf8<KGUIDLen> guid;
173 const TBool useLittleEndian = ETrue;
175 // Assume there's video content present if we only have buffer data.
176 if (iReader.Type() == CReader::EBuffer)
178 iFlags.SetBit(KASFVideoBit);
181 ReadObjectL(guid, size);
182 if (guid == MAKE_TPtrC8(KASFHeaderObject))
186 if (size < KMinObjectLen)
188 User::Leave(KErrCorrupt);
191 iFlags.SetBit(KASFHeaderObjectBit);
192 // We need to find out how many objects there are.
193 iReader.Read32L(objectCount, useLittleEndian);
194 iReader.SeekL(2); // Ignore reserved values (two bytes).
196 const TDesC8& streamPropertiesGUID = MAKE_TPtrC8(KASFStreamPropertiesObject);
197 const TDesC8& videoMediaGUID = MAKE_TPtrC8(KASFVideoMedia);
199 for (TInt i = 0; i < objectCount; i++)
201 ReadObjectL(guid, size);
203 // We want the stream properties object.
204 if (guid == streamPropertiesGUID)
206 // There may be more than one present.
207 iFlags.SetBit(KASFStreamHeaderBit);
210 if (guid == videoMediaGUID)
212 iFlags.SetBit(KASFVideoBit);
214 iReader.SeekL(size - KObjectLen - KGUIDLen);
218 iReader.SeekL(size - KObjectLen);
224 User::Leave(KErrCorrupt);
231 void TASFParser::ReadObjectL(TDes8& aGUID, TInt64& aSize)
233 //The base unit of organization for ASF files is called the ASF object.
234 //It consists of a 128-bit GUID for the object, a 64-bit integer object size,
235 //and the variable-length object data. The value of the object size field is
236 //the sum of 24 bytes plus the size of the object data in bytes.
240 const TBool useLittleEndian = ETrue;
242 aGUID.SetLength(KGUIDLen);
245 iReader.Read32L(word2, useLittleEndian);
246 iReader.Read32L(word1, useLittleEndian);
248 aSize = MAKE_TINT64(word1, word2);
255 void TASFParser::ReadGUIDL(TDes8& aGUID)
259 if (aGUID.Length() != KGUIDLen)
261 User::Leave(KErrUnderflow);
264 // Parts of the GUID are stored in big-endian order.
265 // They're converted to little-endian order here.
266 iReader.ReadByteL(byte); aGUID[3] = byte;
267 iReader.ReadByteL(byte); aGUID[2] = byte;
268 iReader.ReadByteL(byte); aGUID[1] = byte;
269 iReader.ReadByteL(byte); aGUID[0] = byte;
271 iReader.ReadByteL(byte); aGUID[5] = byte;
272 iReader.ReadByteL(byte); aGUID[4] = byte;
274 iReader.ReadByteL(byte); aGUID[7] = byte;
275 iReader.ReadByteL(byte); aGUID[6] = byte;
277 for (TInt i = 8; i < KGUIDLen; i++)
279 iReader.ReadByteL(byte);