os/mm/mmlibs/mmfw/Recogniser/src/mpeg4parser.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
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 "parsers.h"
sl@0
    17
#include "constants.h"
sl@0
    18
sl@0
    19
//
sl@0
    20
// Brands.
sl@0
    21
// Some (most) brands have Release information - e.g. 3gp6, 3gp5 etc.
sl@0
    22
// Therefore, to match the brand, we only look at the characters that don't
sl@0
    23
// represent Release information (in the above case, the 4th character).
sl@0
    24
// The Release character is set to zero.
sl@0
    25
//
sl@0
    26
static const TUint32 KMP4Brand = MAKE_INT32('m', 'p', '4', 0);
sl@0
    27
static const TUint32 K3GPBrand = MAKE_INT32('3', 'g', 'p', 0);
sl@0
    28
static const TUint32 K3G2Brand = MAKE_INT32('3', 'g', '2', 0);
sl@0
    29
static const TUint32 K3GSBrand = MAKE_INT32('3', 'g', 's', 0);	// Streaming servers.
sl@0
    30
static const TUint32 K3GRBrand = MAKE_INT32('3', 'g', 'r', 0);	// Progresive download and MMS.
sl@0
    31
static const TUint32 KQTBrand  = MAKE_INT32('q', 't', ' ', ' '); // for quicktime
sl@0
    32
//
sl@0
    33
// Box identifiers.
sl@0
    34
//
sl@0
    35
static const TUint32 KFtyp = MAKE_INT32('f', 't', 'y', 'p');
sl@0
    36
static const TUint32 KMoov = MAKE_INT32('m', 'o', 'o', 'v');
sl@0
    37
static const TUint32 KTrak = MAKE_INT32('t', 'r', 'a', 'k');
sl@0
    38
static const TUint32 KTkhd = MAKE_INT32('t', 'k', 'h', 'd');
sl@0
    39
static const TUint32 KMdia = MAKE_INT32('m', 'd', 'i', 'a');
sl@0
    40
static const TUint32 KHdlr = MAKE_INT32('h', 'd', 'l', 'r');
sl@0
    41
static const TUint32 KVide = MAKE_INT32('v', 'i', 'd', 'e');
sl@0
    42
static const TUint32 KUuid = MAKE_INT32('u', 'u', 'i', 'd');
sl@0
    43
sl@0
    44
sl@0
    45
//
sl@0
    46
// This truth table maps the following flags to a confidence level.
sl@0
    47
//
sl@0
    48
// A - trak box present
sl@0
    49
// B - moov box present
sl@0
    50
//
sl@0
    51
// A B -> Confidence
sl@0
    52
// =================
sl@0
    53
// 0 0 -> EPossible
sl@0
    54
// 0 1 -> EProbable
sl@0
    55
// 1 0 -> EProbable
sl@0
    56
// 1 1 -> ECertain
sl@0
    57
//
sl@0
    58
static const TInt KMPEG4FlagsToConfidence[] =
sl@0
    59
	{
sl@0
    60
	KConfPossible,
sl@0
    61
	KConfProbable,
sl@0
    62
	KConfProbable,
sl@0
    63
	KConfCertain,
sl@0
    64
	};
sl@0
    65
sl@0
    66
sl@0
    67
#define KMPEG4ConfidenceMask	0x03	// 00000011
sl@0
    68
#define KMPEG4BoxTitleLen		4
sl@0
    69
#define KMPEG4TRAKBit			KBit0	// 00000001
sl@0
    70
#define KMPEG4MOOVBit			KBit1	// 00000010
sl@0
    71
#define KMPEG4VideoBit			KBit2	// 00000100
sl@0
    72
sl@0
    73
static const TInt KMPEG4BoxIntroLen = 8;
sl@0
    74
static const TInt KMPEG4Box64BitIntroLen = 16;
sl@0
    75
sl@0
    76
//
sl@0
    77
// In order to find out the type of MPEG4 file it is
sl@0
    78
// we need to be able to map known extensions, expected
sl@0
    79
// ftyp expressions with MIME-types.
sl@0
    80
//
sl@0
    81
typedef struct
sl@0
    82
	{
sl@0
    83
	const TText* iExt;
sl@0
    84
	TUint32 iBrand;
sl@0
    85
	const TText8* iAudioMime;
sl@0
    86
	const TText8* iVideoMime;
sl@0
    87
	}
sl@0
    88
TMPEG4File;
sl@0
    89
sl@0
    90
sl@0
    91
//
sl@0
    92
// A table of ftyp's, extensions and mime-types.
sl@0
    93
//
sl@0
    94
// .mp4 - can contain either audio or video.
sl@0
    95
// .m4a - should contain (unprotected) audio only.
sl@0
    96
// .m4p - should contain protected audio only.
sl@0
    97
// .3gp - can contain either audio or video.
sl@0
    98
//
sl@0
    99
static const TMPEG4File KMPEG4Files[] =
sl@0
   100
	{
sl@0
   101
		{KExtMP4,	KMP4Brand,	KMimeMP4_A,	KMimeMP4_V},
sl@0
   102
		{KExt3GP,	K3GPBrand,	KMime3GP_A,	KMime3GP_V},
sl@0
   103
		{KExtM4A,	KMP4Brand,	KMimeMP4_A,	NULL},
sl@0
   104
		{KExt3G2,	K3G2Brand,	KMime3G2_A,	KMime3G2_V},
sl@0
   105
		{KExt3GP,	K3GSBrand,	KMime3GP_A,	KMime3GP_V},
sl@0
   106
		{KExt3GP,	K3GRBrand,	KMime3GP_A,	KMime3GP_V},
sl@0
   107
		{KExt3GA,	K3GPBrand,	KMime3GA,	NULL},
sl@0
   108
		{KExtMOV,   KQTBrand,   NULL, KMimeQuickV} // this entry is for .mov files
sl@0
   109
	};
sl@0
   110
sl@0
   111
static const TInt KMPEG4FileTypeCount = sizeof(KMPEG4Files) / sizeof(TMPEG4File);
sl@0
   112
sl@0
   113
sl@0
   114
//
sl@0
   115
//
sl@0
   116
//
sl@0
   117
TMPEG4Parser::TMPEG4Parser(CReader& aReader, TFlags& aFlags)
sl@0
   118
 :	iBrandIndex(KErrNotFound),
sl@0
   119
 	iIsFinished(EFalse),
sl@0
   120
 	iReader(aReader),
sl@0
   121
 	iFlags(aFlags),
sl@0
   122
 	iVideoAssumed(EFalse)
sl@0
   123
	{
sl@0
   124
	}
sl@0
   125
sl@0
   126
sl@0
   127
//
sl@0
   128
// Compare a brand with the ones this recogniser knows about.
sl@0
   129
//
sl@0
   130
TInt TMPEG4Parser::IsCompatibleBrand(TUint32 aBrand, TInt aStartPos)
sl@0
   131
	{
sl@0
   132
	for (TInt i = aStartPos; i < KMPEG4FileTypeCount; i++)
sl@0
   133
		{
sl@0
   134
		TUint32 knownBrand = KMPEG4Files[i].iBrand;
sl@0
   135
		if ((aBrand & knownBrand) == knownBrand)
sl@0
   136
			{
sl@0
   137
			return i;
sl@0
   138
			}
sl@0
   139
		}
sl@0
   140
sl@0
   141
	return KErrNotFound;
sl@0
   142
	}
sl@0
   143
sl@0
   144
sl@0
   145
//
sl@0
   146
// Try to determine the mime-type from the extension, and
sl@0
   147
// if that isn't matched, from the FTYP field if present.
sl@0
   148
// If none of these are matched, NULL is returned and the
sl@0
   149
// file isn't a valid MPEG4 file.
sl@0
   150
//
sl@0
   151
const TText8* TMPEG4Parser::MatchFileType(const TDesC& aExt)
sl@0
   152
	{
sl@0
   153
	TBool videoFound = iFlags.GetBitField(KMPEG4VideoBit);
sl@0
   154
	TBool video = (videoFound || iVideoAssumed);
sl@0
   155
	
sl@0
   156
	// Try to match the extension.
sl@0
   157
	if (aExt.Length() > 0)
sl@0
   158
		{
sl@0
   159
		for (TInt i = 0; i < KMPEG4FileTypeCount; i++)
sl@0
   160
			{
sl@0
   161
			TPtrC ext(KMPEG4Files[i].iExt);
sl@0
   162
			if (aExt.MatchF(ext) != KErrNotFound)
sl@0
   163
				{
sl@0
   164
				// Extension match. If the extension is for an audio-only format
sl@0
   165
				// we must make sure there is no video content in the file. If
sl@0
   166
				// video content is present then ignore the extension match.
sl@0
   167
				if (KMPEG4Files[i].iVideoMime == NULL)
sl@0
   168
					{
sl@0
   169
					if (videoFound)
sl@0
   170
						{
sl@0
   171
						// Try to match another extension.
sl@0
   172
						continue;
sl@0
   173
						}
sl@0
   174
					
sl@0
   175
					return KMPEG4Files[i].iAudioMime;
sl@0
   176
					}
sl@0
   177
				
sl@0
   178
				return (video ? KMPEG4Files[i].iVideoMime : KMPEG4Files[i].iAudioMime);
sl@0
   179
				}
sl@0
   180
			}
sl@0
   181
		}
sl@0
   182
sl@0
   183
	// Unknown or no extension. Try to match the brand
sl@0
   184
	while (iBrandIndex != KErrNotFound)
sl@0
   185
		{
sl@0
   186
		if (KMPEG4Files[iBrandIndex].iVideoMime == NULL)
sl@0
   187
			{
sl@0
   188
			if (videoFound)
sl@0
   189
				{
sl@0
   190
				// Try to match another brand.
sl@0
   191
				TUint32 brand = KMPEG4Files[iBrandIndex].iBrand;
sl@0
   192
				iBrandIndex = TMPEG4Parser::IsCompatibleBrand(brand, iBrandIndex + 1);
sl@0
   193
				continue;
sl@0
   194
				}
sl@0
   195
			
sl@0
   196
			return KMPEG4Files[iBrandIndex].iAudioMime;
sl@0
   197
			}
sl@0
   198
		
sl@0
   199
		return (video ? KMPEG4Files[iBrandIndex].iVideoMime : KMPEG4Files[iBrandIndex].iAudioMime);
sl@0
   200
		}
sl@0
   201
sl@0
   202
	// If there is no brand and an unknown extension look at the flags.
sl@0
   203
	// (There are some files that have no ftyp).
sl@0
   204
	// Only return a potential mime-type if all flag bits have been set.
sl@0
   205
	if (iFlags.GetBitField(KMPEG4ConfidenceMask) == KMPEG4ConfidenceMask)
sl@0
   206
		{
sl@0
   207
		return (video ? KMimeMP4_V : KMimeMP4_A);
sl@0
   208
		}
sl@0
   209
		
sl@0
   210
	return NULL;
sl@0
   211
	}
sl@0
   212
sl@0
   213
sl@0
   214
//
sl@0
   215
//
sl@0
   216
//
sl@0
   217
void TMPEG4Parser::DoRecognise(const TDesC& aFileExt, CReader& aReader, TMatch& aMatch)
sl@0
   218
	{
sl@0
   219
	TFlags flags;
sl@0
   220
	TMPEG4Parser parser(aReader, flags);
sl@0
   221
			
sl@0
   222
	TRAP_IGNORE(parser.ParseL());
sl@0
   223
	
sl@0
   224
	// The extension determines the mime-type.
sl@0
   225
	// The flags say if it's a valid MPEG4 file and if video is present.
sl@0
   226
	const TText8* extMime = parser.MatchFileType(aFileExt);
sl@0
   227
	if (extMime != NULL)
sl@0
   228
		{
sl@0
   229
		TInt confIndex = flags.GetBitField(KMPEG4ConfidenceMask);
sl@0
   230
		aMatch.iConfidence = KMPEG4FlagsToConfidence[confIndex];
sl@0
   231
		if (aMatch.iConfidence != KConfNotRecognised)
sl@0
   232
			{
sl@0
   233
			aMatch.iMime = extMime;
sl@0
   234
			}
sl@0
   235
		}
sl@0
   236
	}
sl@0
   237
	
sl@0
   238
sl@0
   239
//
sl@0
   240
//
sl@0
   241
//
sl@0
   242
void TMPEG4Parser::ParseL()
sl@0
   243
	{
sl@0
   244
	// If we have only buffer data, we must assume the video
sl@0
   245
	// content (if any) has been missed. This is because an
sl@0
   246
	// audio-only file recognised as video should play in a
sl@0
   247
	// video application, but a video file recognised as audio
sl@0
   248
	// will not play in a audio application.
sl@0
   249
	if (iReader.Type() == CReader::EBuffer)
sl@0
   250
		{
sl@0
   251
		iVideoAssumed = ETrue;
sl@0
   252
		}
sl@0
   253
		
sl@0
   254
	do
sl@0
   255
		{		
sl@0
   256
		ReadBoxHeaderL();
sl@0
   257
		if (iTitle == KFtyp)
sl@0
   258
			{
sl@0
   259
			ReadFileTypeL();
sl@0
   260
			}
sl@0
   261
		else if (iTitle == KMoov)
sl@0
   262
			{
sl@0
   263
			iFlags.SetBit(KMPEG4MOOVBit);
sl@0
   264
			ReadMovieL();
sl@0
   265
			}
sl@0
   266
		else
sl@0
   267
			{
sl@0
   268
			SkipCurrentBoxL();
sl@0
   269
			}
sl@0
   270
		}
sl@0
   271
	while (!iIsFinished);
sl@0
   272
	}
sl@0
   273
sl@0
   274
sl@0
   275
//
sl@0
   276
//
sl@0
   277
//
sl@0
   278
void TMPEG4Parser::SkipCurrentBoxL()
sl@0
   279
	{
sl@0
   280
	// Intro: [size][title] = 8 bytes.
sl@0
   281
		
sl@0
   282
	if (iSize == 0)
sl@0
   283
		{
sl@0
   284
		// The current box extends to the end of file.
sl@0
   285
		iIsFinished = ETrue;
sl@0
   286
		return;
sl@0
   287
		}
sl@0
   288
	if(iSizeIn32bit)
sl@0
   289
	    {
sl@0
   290
        iReader.SeekL(iSize - KMPEG4BoxIntroLen);
sl@0
   291
	    }
sl@0
   292
	else
sl@0
   293
	    {
sl@0
   294
        iReader.SeekL(iSize - KMPEG4Box64BitIntroLen);
sl@0
   295
	    }
sl@0
   296
	}
sl@0
   297
sl@0
   298
sl@0
   299
//
sl@0
   300
// Parses the 'moov' box.
sl@0
   301
// This box contains sub-boxes we're interested in.
sl@0
   302
//
sl@0
   303
void TMPEG4Parser::ReadMovieL()
sl@0
   304
	{
sl@0
   305
	// This box holds no information.
sl@0
   306
	// It contains 'trak' boxes, which we want.
sl@0
   307
	
sl@0
   308
	TInt64 dataInBox = iSize - KMPEG4BoxIntroLen;
sl@0
   309
	
sl@0
   310
	while ((dataInBox > 0) && !iIsFinished)
sl@0
   311
		{
sl@0
   312
		ReadBoxHeaderL();
sl@0
   313
		dataInBox -= iSize;
sl@0
   314
		
sl@0
   315
		if (iTitle == KTrak)
sl@0
   316
			{
sl@0
   317
			iFlags.SetBit(KMPEG4TRAKBit);
sl@0
   318
			ReadTrackL();
sl@0
   319
			}
sl@0
   320
		else
sl@0
   321
			{
sl@0
   322
			SkipCurrentBoxL();
sl@0
   323
			}
sl@0
   324
		}
sl@0
   325
	}
sl@0
   326
	
sl@0
   327
sl@0
   328
//
sl@0
   329
// Parses the 'trak' box.
sl@0
   330
// This box contains sub-boxes we're interested in.
sl@0
   331
//
sl@0
   332
void TMPEG4Parser::ReadTrackL()
sl@0
   333
	{
sl@0
   334
	// This box holds no information.
sl@0
   335
	// It contains 'tkhd' boxes, which we want.
sl@0
   336
	
sl@0
   337
	TInt64 dataInBox = iSize - KMPEG4BoxIntroLen;
sl@0
   338
	
sl@0
   339
	while ((dataInBox > 0) && !iIsFinished) 
sl@0
   340
		{
sl@0
   341
		ReadBoxHeaderL();
sl@0
   342
		dataInBox -= iSize;
sl@0
   343
		
sl@0
   344
		if (iTitle == KTkhd)
sl@0
   345
			{
sl@0
   346
			ReadTrackHeaderL();
sl@0
   347
			}
sl@0
   348
		else if (iTitle == KMdia)
sl@0
   349
			{
sl@0
   350
			ReadMediaL();
sl@0
   351
			}
sl@0
   352
		else
sl@0
   353
			{
sl@0
   354
			SkipCurrentBoxL();
sl@0
   355
			}
sl@0
   356
		}
sl@0
   357
	}
sl@0
   358
sl@0
   359
//
sl@0
   360
// Parses a 'mdia' box.
sl@0
   361
// This box contains sub-boxes we're interested in.
sl@0
   362
//
sl@0
   363
void TMPEG4Parser::ReadMediaL()
sl@0
   364
	{
sl@0
   365
	TInt64 dataInBox = iSize - KMPEG4BoxIntroLen;
sl@0
   366
	
sl@0
   367
	while ((dataInBox > 0) && !iIsFinished)
sl@0
   368
		{
sl@0
   369
		ReadBoxHeaderL();
sl@0
   370
		dataInBox -= iSize;
sl@0
   371
		
sl@0
   372
		if (iTitle == KHdlr)
sl@0
   373
			{
sl@0
   374
			ReadHandlerL();
sl@0
   375
			}
sl@0
   376
		else
sl@0
   377
			{
sl@0
   378
			SkipCurrentBoxL();
sl@0
   379
			}
sl@0
   380
		}
sl@0
   381
	}
sl@0
   382
sl@0
   383
sl@0
   384
//
sl@0
   385
// Parses a 'hdlr' box.
sl@0
   386
// This is a stand-alone box.
sl@0
   387
//
sl@0
   388
void TMPEG4Parser::ReadHandlerL()
sl@0
   389
	{
sl@0
   390
	// Intro: [size][title][versionFlags][predefined][handler_type] = 20 bytes.
sl@0
   391
	const TInt KMPEG4HandlerIntroLen = 20;
sl@0
   392
	TUint32 versionFlags;
sl@0
   393
	TUint32 predefined;
sl@0
   394
	TUint32 handler;
sl@0
   395
sl@0
   396
	iReader.Read32L(versionFlags);
sl@0
   397
	iReader.Read32L(predefined);
sl@0
   398
	if (predefined != 0)
sl@0
   399
		{
sl@0
   400
		User::Leave(KErrCorrupt);
sl@0
   401
		}
sl@0
   402
		
sl@0
   403
	iReader.Read32L(handler);
sl@0
   404
	if (handler == KVide)
sl@0
   405
		{
sl@0
   406
		iFlags.SetBit(KMPEG4VideoBit);
sl@0
   407
		}
sl@0
   408
		
sl@0
   409
	iReader.SeekL(iSize - KMPEG4HandlerIntroLen);
sl@0
   410
	}
sl@0
   411
sl@0
   412
sl@0
   413
//
sl@0
   414
//
sl@0
   415
//
sl@0
   416
void TMPEG4Parser::ReadTrackHeaderL()
sl@0
   417
	{
sl@0
   418
	const TUint8 KMPEG4TrackVersion0 = 0;
sl@0
   419
	const TUint8 KMPEG4TrackVersion1 = 1;
sl@0
   420
	const TInt KMPEG4Version0ToVolume = 32; // Distance to volume field from version=0 field.
sl@0
   421
	const TInt KMPEG4Version1ToVolume = 44; // Distance to volume field from version=1 field.
sl@0
   422
	const TInt KMPEG4VolumeToWidth = 38;	// Distance to width field from volume field.
sl@0
   423
sl@0
   424
	TUint32 versionFlags;
sl@0
   425
	TUint16 volume;
sl@0
   426
	TUint32 width;
sl@0
   427
	TUint32 height;
sl@0
   428
	
sl@0
   429
	// This box contains information about a single track.
sl@0
   430
	iReader.Read32L(versionFlags);
sl@0
   431
	
sl@0
   432
	// The highest 8 bits contains the version.
sl@0
   433
	switch (HIGH_BYTE32(versionFlags))
sl@0
   434
		{
sl@0
   435
		case KMPEG4TrackVersion0:
sl@0
   436
			iReader.SeekL(KMPEG4Version0ToVolume);
sl@0
   437
			break;
sl@0
   438
			
sl@0
   439
		case KMPEG4TrackVersion1:
sl@0
   440
			iReader.SeekL(KMPEG4Version1ToVolume);
sl@0
   441
			break;
sl@0
   442
			
sl@0
   443
		default:
sl@0
   444
			User::Leave(KErrCorrupt);
sl@0
   445
		}
sl@0
   446
	
sl@0
   447
	// Volume can not be used to distinguish between audio and video anymore.
sl@0
   448
	iReader.Read16L(volume);
sl@0
   449
		
sl@0
   450
	// We want to seek ahead to read the 'width' and 'height' fields.
sl@0
   451
	iReader.SeekL(KMPEG4VolumeToWidth);
sl@0
   452
sl@0
   453
	iReader.Read32L(width);		// 16.16 fixed-point
sl@0
   454
	iReader.Read32L(height);	// 16.16 fixed-point
sl@0
   455
	if ((width != 0) && (height != 0))
sl@0
   456
		{
sl@0
   457
		iFlags.SetBit(KMPEG4VideoBit);
sl@0
   458
		}
sl@0
   459
	}
sl@0
   460
sl@0
   461
	
sl@0
   462
//
sl@0
   463
// Parses the 'ftyp' box.
sl@0
   464
// Records the first recognised brand that helps to
sl@0
   465
// identify the mime-type.
sl@0
   466
//
sl@0
   467
void TMPEG4Parser::ReadFileTypeL()
sl@0
   468
	{
sl@0
   469
	// Intro = [size][title][majorBrand] = 12 bytes.
sl@0
   470
	const TInt KMPEG4FtypIntroLen = 12;
sl@0
   471
	TUint32 brand;
sl@0
   472
	
sl@0
   473
	// If the majorBrand isn't recognised we should also
sl@0
   474
	// search the compatible brand list.
sl@0
   475
	TInt64 bytesRemaining = iSize - KMPEG4FtypIntroLen;
sl@0
   476
	//here there should be bytes remaining. Otherwise we cant read.
sl@0
   477
	if( bytesRemaining <0 )
sl@0
   478
	{
sl@0
   479
	    User::Leave(KErrCorrupt);    
sl@0
   480
	}
sl@0
   481
	
sl@0
   482
	iReader.Read32L(brand);
sl@0
   483
	iBrandIndex = TMPEG4Parser::IsCompatibleBrand(brand);
sl@0
   484
	if (iBrandIndex != KErrNotFound)
sl@0
   485
		{
sl@0
   486
		// The major brand was recognised.
sl@0
   487
		// Skip to the end of the ftyp box.
sl@0
   488
		iReader.SeekL(bytesRemaining);
sl@0
   489
		return;
sl@0
   490
		}
sl@0
   491
		
sl@0
   492
	// The major brand wasn't recognised.
sl@0
   493
	// Skip over the version info (32 bit) to the start of the
sl@0
   494
	// compatible brands list.
sl@0
   495
	TInt skip = sizeof(TUint32);
sl@0
   496
	iReader.SeekL(skip);
sl@0
   497
	bytesRemaining -= skip;
sl@0
   498
	
sl@0
   499
	while ((iBrandIndex == KErrNotFound) && (bytesRemaining > 0))
sl@0
   500
		{
sl@0
   501
		iReader.Read32L(brand);
sl@0
   502
		bytesRemaining -= skip;
sl@0
   503
		iBrandIndex = TMPEG4Parser::IsCompatibleBrand(brand);
sl@0
   504
		}
sl@0
   505
sl@0
   506
	iReader.SeekL(bytesRemaining);
sl@0
   507
	}
sl@0
   508
sl@0
   509
sl@0
   510
//
sl@0
   511
// Reads the first few bytes of a box.
sl@0
   512
// The exact amount read depends on the box.
sl@0
   513
//
sl@0
   514
void TMPEG4Parser::ReadBoxHeaderL()
sl@0
   515
	{
sl@0
   516
	const TInt KMPEG4ExtendedTypeLen = 16;
sl@0
   517
	
sl@0
   518
	TUint32 word1;
sl@0
   519
sl@0
   520
	iReader.Read32L(word1);
sl@0
   521
	iReader.Read32L(iTitle);
sl@0
   522
sl@0
   523
	switch (word1)
sl@0
   524
		{
sl@0
   525
		case 0:
sl@0
   526
			// Box extends to the end of file.
sl@0
   527
			iSize = MAKE_TINT64(0, 0);
sl@0
   528
			break;
sl@0
   529
			
sl@0
   530
		case 1:
sl@0
   531
			// Size is specified in a 64-bit field.
sl@0
   532
		    iSizeIn32bit = EFalse;
sl@0
   533
			iReader.Read64L(iSize);
sl@0
   534
			break;
sl@0
   535
			
sl@0
   536
		default:
sl@0
   537
			// It's an actual 32-bit size.
sl@0
   538
		    iSizeIn32bit = ETrue;
sl@0
   539
			iSize = MAKE_TINT64(0, word1);
sl@0
   540
		}
sl@0
   541
		
sl@0
   542
	if (iTitle == KUuid)
sl@0
   543
		{
sl@0
   544
		// Skip the extended type.
sl@0
   545
		iReader.SeekL(KMPEG4ExtendedTypeLen);
sl@0
   546
		}
sl@0
   547
	}
sl@0
   548
sl@0
   549