First public contribution.
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.
18 static const TUint8 KISOEndCode = 0xB9;
19 static const TUint8 KPackStartCode = 0xBA;
20 static const TUint8 KVideoElementaryStream = 0xE0;
22 #define KMPEG1PackHeaderLen 8
23 #define KMPEG2PackHeaderLen 10
25 #define KMPEG1PackHeaderID 0x21 // 0010xxx1. See Doc Link 2.
26 #define KMPEG2PackHeaderID 0x44 // 01xxx1xx. See Doc Link 2.
28 #define KStartCodeMask 0xffffff00
29 #define KStartCodeIntro 0x00000100
31 #define KMPEG2StartCode1Bit KBit1
32 #define KMPEG2StartCode2Bit KBit2
33 #define KMPEG2VideoBit KBit3
34 #define KMPEG2MPEG1Bit KBit4
37 // Mapping flags to a confidence level.
43 // C B A -> Confidence
44 // -------------------
45 // 0 0 0 -> ENotRecognised
49 // 1 0 0 -> ENotRecognised
50 // 1 0 1 -> ENotRecognised
54 static const TInt KMPEG2FlagsToConfidence[] =
66 #define KMPEG2ConfidenceMask 0x07 // 00000111
67 #define KMPEG2MimeMask 0x18 // 00011000
68 #define KMPEG2MimeShift 0x03
70 static const TInt KMPEG2ExtOnlyIndex = 1;
73 // The 'ED' bits of the flags member are used as an index into
74 // this table of possible MIME-types.
76 // E: MPEG1 instead of MPEG2
77 // D: Video content present
86 static const TText8* const KMPEG2Mimes[] =
95 // A list of known MPEG2 file extensions.
96 // MPEG1 file extensions are also listed.
105 static const TMPEG2Types KMPEG2Types[] =
107 { KExtMPEG_1, KMimeMPEG2_V },
108 { KExtMPEG_2, KMimeMPEG2_V },
109 { KExtMPEG_3, KMimeMPEG2_V },
110 { KExtMPEG_4, KMimeMPEG2_V },
111 { KExtMPEG_5, KMimeMPEG2_V },
112 { KExtMPEG_6, KMimeMPEG2_V },
113 { KExtMPEG_7, KMimeMPEG1_V },
114 { KExtMPEG_8, KMimeMPEG2_A }
117 #define KMPEG2ExtCount sizeof(KMPEG2Types) / sizeof(TMPEG2Types)
123 TMPEG2Parser::TMPEG2Parser(CReader& aReader, TFlags& aFlags)
131 // Match the file's extension to known MPEG2 file extensions.
133 const TText8* TMPEG2Parser::MatchExtension(const TDesC& aExt)
135 if (aExt.Length() > 0)
137 for (TInt i = 0; i < KMPEG2ExtCount; i++)
139 if (aExt.MatchF(TPtrC(KMPEG2Types[i].iExt)) != KErrNotFound)
141 iFlags.SetExtensionFlag();
142 return KMPEG2Types[i].iMime;
154 void TMPEG2Parser::DoRecognise(const TDesC& aExt, CReader& aReader, TMatch& aMatch)
157 TMPEG2Parser parser(aReader, flags);
159 const TText8* extMime = parser.MatchExtension(aExt);
160 TRAP_IGNORE(parser.ParseL());
162 TInt confIndex = flags.GetBitField(KMPEG2ConfidenceMask);
163 aMatch.iConfidence = KMPEG2FlagsToConfidence[confIndex];
164 if (aMatch.iConfidence != KConfNotRecognised)
166 if (confIndex == KMPEG2ExtOnlyIndex)
168 // The content is corrupt, but the extension was recognised.
169 aMatch.iMime = extMime;
173 TInt mimeIndex = flags.GetBitField(KMPEG2MimeMask, KMPEG2MimeShift);
174 aMatch.iMime = KMPEG2Mimes[mimeIndex];
181 // Attempts to parse an MPEG2 file by looking for start-codes.
183 void TMPEG2Parser::ParseL()
187 // Assume there's video content if we only have a buffer.
188 if (iReader.Type() == CReader::EBuffer)
190 iFlags.SetBit(KMPEG2VideoBit);
195 finished = NextStartCodeL();
202 // Skips over the current start-code box.
204 void TMPEG2Parser::SkipL()
208 iReader.Read16L(size);
209 iReader.SeekL((TInt)size);
214 ** Expects an MPEG2 Pack Header at the current location.
215 ** The Pack Header is used to determine between MPEG1 and MPEG2.
217 void TMPEG2Parser::ReadPackHeaderL()
220 TBuf8<KMPEG2PackHeaderLen> header; // Size is of whichever is larger.
222 iReader.ReadByteL(byte);
224 if ((byte & KMPEG1PackHeaderID) == KMPEG1PackHeaderID)
226 iFlags.SetBit(KMPEG2MPEG1Bit);
227 header.SetLength(KMPEG1PackHeaderLen - 1); // We've already read a byte.
228 iReader.ReadBytesL(header);
230 else if ((byte & KMPEG2PackHeaderID) == KMPEG2PackHeaderID)
232 header.SetLength(KMPEG2PackHeaderLen - 1); // We've already read a byte.
233 iReader.ReadBytesL(header);
235 // The lowest 3 bits of the last byte say how much stuffing is present.
236 TInt stuffing = header[8] & 0x07; // 00000111
239 iReader.SeekL(stuffing);
244 User::Leave(KErrCorrupt);
250 // Start codes are bit patterns that do not occur in the video stream.
251 // The start-code sequence is expected to be at the current CReader position.
253 TBool TMPEG2Parser::NextStartCodeL()
257 iReader.Read32L(data);
259 // Start codes must begin with 0x000001ss, where 'ss' is the start code.
260 if ((data & KStartCodeMask) != KStartCodeIntro)
262 User::Leave(KErrCorrupt);
265 if (!iFlags.GetBitField(KMPEG2StartCode1Bit))
267 iFlags.SetBit(KMPEG2StartCode1Bit);
271 if (!iFlags.GetBitField(KMPEG2StartCode2Bit))
273 iFlags.SetBit(KMPEG2StartCode2Bit);
277 // Try to identify the start code.
278 switch (LOW_BYTE(data))
284 case KVideoElementaryStream:
285 iFlags.SetBit(KMPEG2VideoBit);
289 // This code should occur at the end of the file and
290 // it cannot be skipped over.