os/mm/mmplugins/mmfwplugins/src/Plugin/Controller/Video/AviPlayController/avireader.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
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 "avireader.h"
sl@0
    17
sl@0
    18
const TInt KReadBufferSize = 0x8000; // 4k
sl@0
    19
const TInt KChunkHeaderSize = 8;
sl@0
    20
sl@0
    21
const TInt KInvalidMediaIdx = -1;
sl@0
    22
sl@0
    23
#define RiffChunkName(A,B,C,D) ((D<<24)+(C<<16)+(B<<8)+A)
sl@0
    24
sl@0
    25
const TInt KRiffChunkNameRiff = RiffChunkName('R','I','F','F');
sl@0
    26
const TInt KRiffChunkNameList = RiffChunkName('L','I','S','T');
sl@0
    27
const TInt KRiffChunkNameAvih = RiffChunkName('a','v','i','h');
sl@0
    28
const TInt KRiffChunkTypeAvi  = RiffChunkName('A','V','I',' ');
sl@0
    29
const TInt KRiffChunkTypeHdrl = RiffChunkName('h','d','r','l');
sl@0
    30
const TInt KRiffChunkTypeStrl = RiffChunkName('s','t','r','l');
sl@0
    31
const TInt KRiffChunkNameStrh = RiffChunkName('s','t','r','h');
sl@0
    32
const TInt KRiffChunkNameStrf = RiffChunkName('s','t','r','f');
sl@0
    33
const TInt KRiffChunkNameStrn = RiffChunkName('s','t','r','n');
sl@0
    34
const TInt KRiffChunkTypeVids = RiffChunkName('v','i','d','s');
sl@0
    35
const TInt KRiffChunkTypeAuds = RiffChunkName('a','u','d','s');
sl@0
    36
const TInt KRiffChunkNameJunk = RiffChunkName('J','U','N','K');
sl@0
    37
const TInt KRiffChunkTypeMovi = RiffChunkName('m','o','v','i');
sl@0
    38
const TInt KRiffChunkName00db = RiffChunkName('0','0','d','b');
sl@0
    39
const TInt KRiffChunkName00dc = RiffChunkName('0','0','d','c');
sl@0
    40
const TInt KRiffChunkName00wb = RiffChunkName('0','0','w','b');
sl@0
    41
const TInt KRiffChunkName01wb = RiffChunkName('0','1','w','b');
sl@0
    42
const TInt KRiffChunkName01db = RiffChunkName('0','1','d','b');
sl@0
    43
const TInt KRiffChunkName01dc = RiffChunkName('0','1','d','c');
sl@0
    44
const TInt KRiffChunkNameXvid = RiffChunkName('X','V','I','D');
sl@0
    45
const TInt KRiffChunkNameIdx1 = RiffChunkName('i','d','x','1');
sl@0
    46
const TInt KRiffChunkNameStrd = RiffChunkName('s','t','r','d'); 
sl@0
    47
const TInt KRiffChunkNameIndex = RiffChunkName('i','n','d','x');
sl@0
    48
const TInt KRiffChunkNameVprp = RiffChunkName('v','p','r','p');
sl@0
    49
const TInt KAVIF_ISINTERLEAVED = 0x00000001;
sl@0
    50
sl@0
    51
sl@0
    52
sl@0
    53
sl@0
    54
//CAviReader Functions
sl@0
    55
sl@0
    56
/**
sl@0
    57
Fast read for non-aligned 16 bit data.
sl@0
    58
@param aPtr
sl@0
    59
@return
sl@0
    60
*/
sl@0
    61
LOCAL_C TUint16 Read16(const TUint8* aPtr)
sl@0
    62
	{
sl@0
    63
    return *(TUint16*)aPtr;
sl@0
    64
    }
sl@0
    65
sl@0
    66
/**
sl@0
    67
Fast read for non-aligned 32 bit data.
sl@0
    68
@param aPtr
sl@0
    69
@return
sl@0
    70
*/
sl@0
    71
LOCAL_C TUint32 Read32(const TUint8* aPtr)
sl@0
    72
    {
sl@0
    73
    TUint32 x = *aPtr++;
sl@0
    74
    x |= *aPtr++ << 8;
sl@0
    75
    x |= *aPtr++ << 16;
sl@0
    76
    x |= *aPtr++ << 24;
sl@0
    77
    return x;
sl@0
    78
    }
sl@0
    79
sl@0
    80
/**
sl@0
    81
Creates CAviReader object.
sl@0
    82
@param aClip
sl@0
    83
@param aObserver
sl@0
    84
@return CAviReader*
sl@0
    85
*/ 
sl@0
    86
CAviReader* CAviReader::NewL(CMMFClip& aClip, MAviReaderObserver& aObserver)
sl@0
    87
    {
sl@0
    88
    CAviReader* self = new(ELeave) CAviReader(aClip, aObserver);
sl@0
    89
    CleanupStack::PushL(self);
sl@0
    90
    self->ConstructL();
sl@0
    91
    CleanupStack::Pop(self);
sl@0
    92
    return self;
sl@0
    93
    }
sl@0
    94
  
sl@0
    95
/**
sl@0
    96
Constructor of CAviReader
sl@0
    97
*/
sl@0
    98
CAviReader::CAviReader(CMMFClip& aClip, MAviReaderObserver& aObserver)
sl@0
    99
         :MDataSink(KNullUid),iObserver(aObserver),iClip(aClip),iAudioIdx(KInvalidMediaIdx),
sl@0
   100
         iVideoIdx(KInvalidMediaIdx)
sl@0
   101
    {
sl@0
   102
    }
sl@0
   103
sl@0
   104
/**
sl@0
   105
Destructor of CAviReader
sl@0
   106
*/  
sl@0
   107
CAviReader::~CAviReader()
sl@0
   108
    {
sl@0
   109
	delete iVideoBuffer;
sl@0
   110
	delete iAudioBuffer;
sl@0
   111
	delete iSourceBuffer;
sl@0
   112
    }
sl@0
   113
sl@0
   114
/**
sl@0
   115
Second phase constructor.
sl@0
   116
*/ 
sl@0
   117
void CAviReader::ConstructL()
sl@0
   118
    {
sl@0
   119
    if (iClip.Size() > 0)
sl@0
   120
    	{
sl@0
   121
    	iClip.SourcePrimeL();
sl@0
   122
    	iSourceBuffer = CMMFDescriptorBuffer::NewL(KReadBufferSize);
sl@0
   123
    	ReadFormatL();
sl@0
   124
    	}
sl@0
   125
     else
sl@0
   126
    	{
sl@0
   127
    	iClip.SourceStopL();
sl@0
   128
    	User::Leave(KErrCorrupt);
sl@0
   129
    	}
sl@0
   130
    }   
sl@0
   131
sl@0
   132
/**
sl@0
   133
Reads the header information in the clip.
sl@0
   134
@leave KErrCorrupt if the header information is incorrect.
sl@0
   135
*/ 
sl@0
   136
TInt CAviReader::ReadFormatL()
sl@0
   137
	{
sl@0
   138
	User::LeaveIfError(FindRiffChunksL());
sl@0
   139
	return 0;
sl@0
   140
	}
sl@0
   141
	
sl@0
   142
/**
sl@0
   143
Reads the header information in the clip.
sl@0
   144
@return KErrNone on Success or KErrCorrupt on incorrect header.
sl@0
   145
*/ 
sl@0
   146
TInt CAviReader::FindRiffChunksL()
sl@0
   147
	{
sl@0
   148
	TBool videoEnabled = EFalse;
sl@0
   149
	iClip.ReadBufferL(iSourceBuffer,0);
sl@0
   150
	TUint8* rawform = &(iSourceBuffer->Data()[0]);
sl@0
   151
	TUint8* pBufBegin =  rawform;
sl@0
   152
	if (Read32(rawform) !=  KRiffChunkNameRiff)
sl@0
   153
		{
sl@0
   154
		return KErrCorrupt; //not a RIFF file	
sl@0
   155
		}
sl@0
   156
	rawform+=4;
sl@0
   157
	rawform+=4;// skip file size
sl@0
   158
	if (Read32(rawform) != KRiffChunkTypeAvi)
sl@0
   159
		{
sl@0
   160
	 	return KErrCorrupt;//not an .avi file
sl@0
   161
		}
sl@0
   162
	rawform+=4;
sl@0
   163
	if (Read32(rawform) != KRiffChunkNameList)
sl@0
   164
		{
sl@0
   165
		return KErrCorrupt; 	//it is not a list
sl@0
   166
		}
sl@0
   167
	rawform+=4;
sl@0
   168
	TUint32 dwToRead = Read32(rawform);
sl@0
   169
	rawform+=4;//crossed the list size
sl@0
   170
	if (Read32(rawform) !=KRiffChunkTypeHdrl)
sl@0
   171
		{
sl@0
   172
		return KErrCorrupt;
sl@0
   173
		}
sl@0
   174
	rawform+=4;
sl@0
   175
	if (Read32(rawform) != KRiffChunkNameAvih)
sl@0
   176
		{
sl@0
   177
		return KErrCorrupt;	
sl@0
   178
		}
sl@0
   179
	rawform+=4;
sl@0
   180
	rawform+=4; //skip chunk size
sl@0
   181
	iMainHeader.iMicroSecPerFrame = Read32(rawform);rawform+=4;
sl@0
   182
	iMainHeader.iMaxBytesPerSec = Read32(rawform);rawform+=4;
sl@0
   183
	iMainHeader.iPaddingGranularity= Read32(rawform);rawform+=4;
sl@0
   184
	//Audio gives underflow if the file is interleaved.So audio and video
sl@0
   185
	//is read separately.
sl@0
   186
	iMainHeader.iFlags= Read32(rawform); rawform+=4;
sl@0
   187
	iMainHeader.iTotalFrames= Read32(rawform);rawform+=4;
sl@0
   188
	iMainHeader.iInitialFrames= Read32(rawform);rawform+=4;
sl@0
   189
	iMainHeader.iStreams	= Read32(rawform);rawform+=4;
sl@0
   190
	if(iMainHeader.iStreams > 2)
sl@0
   191
		{
sl@0
   192
		return KErrCorrupt;
sl@0
   193
		}
sl@0
   194
	iMainHeader.iSuggestedBufferSize= Read32(rawform);rawform+=4;
sl@0
   195
	iMainHeader.iWidth= Read32(rawform);rawform+=4;
sl@0
   196
	iMainHeader.iHeight= Read32(rawform);rawform+=4;
sl@0
   197
	iMainHeader.iReserved[0]= Read32(rawform);rawform+=4;
sl@0
   198
    iMainHeader.iReserved[1]= Read32(rawform);rawform+=4;
sl@0
   199
    iMainHeader.iReserved[2]= Read32(rawform);rawform+=4;
sl@0
   200
    iMainHeader.iReserved[3]= Read32(rawform);rawform+=4;
sl@0
   201
sl@0
   202
	for (TUint8 i=0; i < iMainHeader.iStreams; i++)
sl@0
   203
		{
sl@0
   204
		if(Read32(rawform) != KRiffChunkNameList)
sl@0
   205
			{
sl@0
   206
			return KErrCorrupt;	
sl@0
   207
			}
sl@0
   208
		rawform+=4;
sl@0
   209
		rawform+=4; //skip list size;
sl@0
   210
		if(Read32(rawform) != KRiffChunkTypeStrl)
sl@0
   211
			{
sl@0
   212
			return KErrCorrupt;
sl@0
   213
			}
sl@0
   214
		rawform+=4;
sl@0
   215
		if(Read32(rawform) != KRiffChunkNameStrh)
sl@0
   216
			{
sl@0
   217
			return KErrCorrupt;
sl@0
   218
			}
sl@0
   219
		rawform+=4;//read stream header chunk
sl@0
   220
		rawform+=4; //skip stream header chunk size;
sl@0
   221
		iStreamHeader[i].iFccType = Read32(rawform);rawform+=4;
sl@0
   222
		iStreamHeader[i].iFccHandler = Read32(rawform);rawform+=4;
sl@0
   223
		iStreamHeader[i].iFlags= Read32(rawform);rawform+=4; 
sl@0
   224
		iStreamHeader[i].iReserved = Read32(rawform);rawform+=4;
sl@0
   225
		iStreamHeader[i].iInitialFrames =Read32(rawform);rawform+=4;
sl@0
   226
		iStreamHeader[i].iScale =Read32(rawform);rawform+=4;
sl@0
   227
		iStreamHeader[i].iRate= Read32(rawform);rawform+=4;
sl@0
   228
		iStreamHeader[i].iStart = Read32(rawform);rawform+=4;
sl@0
   229
		iStreamHeader[i].iLength = Read32(rawform);rawform+=4;
sl@0
   230
		iStreamHeader[i].iSuggestedBufferSize = Read32(rawform);rawform+=4;
sl@0
   231
		iStreamHeader[i].iQuality = Read32(rawform);rawform+=4;
sl@0
   232
		iStreamHeader[i].iSampleSize = Read32(rawform);rawform+=4;
sl@0
   233
		iStreamHeader[i].iRcFrame.iLeft =Read16(rawform);rawform+=2;
sl@0
   234
		iStreamHeader[i].iRcFrame.iTop =Read16(rawform);rawform+=2;
sl@0
   235
		iStreamHeader[i].iRcFrame.iRight =Read16(rawform);rawform+=2;
sl@0
   236
		iStreamHeader[i].iRcFrame.iBottom =Read16(rawform);rawform+=2;
sl@0
   237
		if (Read32(rawform) != KRiffChunkNameStrf)		
sl@0
   238
			{
sl@0
   239
			return KErrCorrupt;		
sl@0
   240
			}
sl@0
   241
		rawform+=4;//read stream format chunk
sl@0
   242
		TInt chunklen = Read32(rawform);
sl@0
   243
		rawform+=4; //skip stream format chunk size;	
sl@0
   244
	
sl@0
   245
		if (iStreamHeader[i].iFccType == KRiffChunkTypeAuds) //if audio stream
sl@0
   246
			{
sl@0
   247
			if(iAudioEnabled)
sl@0
   248
				{
sl@0
   249
				return KErrCorrupt;	
sl@0
   250
				}
sl@0
   251
			iAudioEnabled = ETrue;
sl@0
   252
			if (Read16(rawform) == 0x0001) // Do not have support except PCM
sl@0
   253
				{
sl@0
   254
	    		iPCMWaveFormat.iWaveFormat.iFormatTag = Read16(rawform);rawform+=2;
sl@0
   255
                iPCMWaveFormat.iWaveFormat.iNChannels = Read16(rawform);rawform+=2;
sl@0
   256
                iPCMWaveFormat.iWaveFormat.iNSamplesPerSec = Read32(rawform);rawform+=4; 
sl@0
   257
                 iPCMWaveFormat.iWaveFormat.iNAvgBytesPerSec= Read32(rawform); rawform+=4;
sl@0
   258
                iPCMWaveFormat.iWaveFormat.iNBlockAlign = Read16(rawform);rawform+=2;
sl@0
   259
                iPCMWaveFormat.iBitsPerSample = Read16(rawform);rawform+=2;                
sl@0
   260
sl@0
   261
	    		iAudioIdx = i;				
sl@0
   262
				}
sl@0
   263
			else
sl@0
   264
				{
sl@0
   265
				return KErrNotSupported;
sl@0
   266
				}
sl@0
   267
			}
sl@0
   268
			
sl@0
   269
		else if (iStreamHeader[i].iFccType == KRiffChunkTypeVids) //if video stream
sl@0
   270
			{
sl@0
   271
			if(iStreamHeader[i].iFccHandler != KRiffChunkNameXvid) 
sl@0
   272
				{
sl@0
   273
				return KErrNotSupported;
sl@0
   274
				}
sl@0
   275
			if(videoEnabled)
sl@0
   276
				{
sl@0
   277
				return KErrCorrupt;	
sl@0
   278
				}
sl@0
   279
				
sl@0
   280
			TUint8* temp =  rawform;
sl@0
   281
			
sl@0
   282
			iBitmapInfoHeader.iBiSize= Read32(rawform);rawform+=4;
sl@0
   283
            iBitmapInfoHeader.iBiWidth= Read32(rawform);rawform+=4;
sl@0
   284
            iBitmapInfoHeader.iBiHeight= Read32(rawform);rawform+=4;
sl@0
   285
            iBitmapInfoHeader.iBiPlanes= Read16(rawform);rawform+=2;
sl@0
   286
            iBitmapInfoHeader.iBiBitCount= Read16(rawform);rawform+=2;
sl@0
   287
            iBitmapInfoHeader.iBiCompression= Read32(rawform);rawform+=4;
sl@0
   288
            iBitmapInfoHeader.iBiSizeImage= Read32(rawform);rawform+=4;
sl@0
   289
            iBitmapInfoHeader.iBiXPelsPerMeter= Read32(rawform);rawform+=4;
sl@0
   290
            iBitmapInfoHeader.iBiYPelsPerMeter= Read32(rawform);rawform+=4;
sl@0
   291
            iBitmapInfoHeader.iBiClrUsed= Read32(rawform);rawform+=4;
sl@0
   292
            iBitmapInfoHeader.iBiClrImportant= Read32(rawform);rawform+=4;
sl@0
   293
            
sl@0
   294
            rawform = temp + chunklen;
sl@0
   295
sl@0
   296
			iVideoIdx = i;
sl@0
   297
			videoEnabled = ETrue;
sl@0
   298
			}
sl@0
   299
		else				//if unidentified stream types.
sl@0
   300
			{
sl@0
   301
			return KErrCorrupt;
sl@0
   302
			}
sl@0
   303
	
sl@0
   304
		TUint32 temp = Read32(rawform);	
sl@0
   305
		while (temp == KRiffChunkNameStrn || temp == KRiffChunkNameStrd || temp == KRiffChunkNameJunk || temp == KRiffChunkNameIndex || temp == KRiffChunkNameVprp) // Skipping the chunks
sl@0
   306
			{
sl@0
   307
			rawform+=4;
sl@0
   308
			temp = Read32(rawform);
sl@0
   309
			rawform+=4+temp;
sl@0
   310
			temp = Read32(rawform);
sl@0
   311
			}
sl@0
   312
		}
sl@0
   313
	
sl@0
   314
	//added to skip the rest of the header to reach movi list. 
sl@0
   315
	TInt bytesRead = rawform - pBufBegin;
sl@0
   316
	iSourcePos = bytesRead;
sl@0
   317
	
sl@0
   318
	for (TInt i = 0; i < KReadBufferSize - bytesRead; i ++)
sl@0
   319
		{
sl@0
   320
		if(Read32(rawform) == KRiffChunkTypeMovi)
sl@0
   321
			{
sl@0
   322
			iSourcePos += i + 4;
sl@0
   323
			iAudioPos = iSourcePos;
sl@0
   324
			iVideoPos = iSourcePos;
sl@0
   325
			break;
sl@0
   326
			}
sl@0
   327
		rawform += 1;	
sl@0
   328
		}
sl@0
   329
	
sl@0
   330
	return KErrNone;
sl@0
   331
	}
sl@0
   332
sl@0
   333
/**
sl@0
   334
Fills the aBuffer with video data depends on interleaved or not.
sl@0
   335
@param aBuffer 
sl@0
   336
*/ 
sl@0
   337
void CAviReader::FillVideoBufferL(TVideoInputBuffer* aBuffer)
sl@0
   338
	{
sl@0
   339
	if (!aBuffer)
sl@0
   340
		{
sl@0
   341
		User::Leave(KErrArgument);
sl@0
   342
		}
sl@0
   343
	iBufferFromDevVideo = aBuffer;
sl@0
   344
	iVideoRequestMade = ETrue;
sl@0
   345
sl@0
   346
	if (iMainHeader.iFlags == KAVIF_ISINTERLEAVED)
sl@0
   347
		{
sl@0
   348
		
sl@0
   349
		//Here Audio and Video data are interleaved in the form of REc lists.
sl@0
   350
		if (!iReadRequestMade) 
sl@0
   351
			{
sl@0
   352
			//Read request for REC list is not yet made. So read the REC list into the sourcebuffer.
sl@0
   353
			ReadNextFrameL(TUid::Null(), iSourcePos);
sl@0
   354
			iReadRequestMade = ETrue;
sl@0
   355
			}
sl@0
   356
sl@0
   357
		else if (iReadCompleted)
sl@0
   358
			{
sl@0
   359
			//REC list is already read into the video buffer.
sl@0
   360
			//copy the data from the video buffer to devvideo buffer.
sl@0
   361
			aBuffer->iData.Copy(iVideoBuffer->Data());
sl@0
   362
			ReadComplete();
sl@0
   363
			}
sl@0
   364
		}
sl@0
   365
sl@0
   366
	else
sl@0
   367
		{
sl@0
   368
		//There are no REC lists. Audio and Video is spread across the file. So we read audio and video
sl@0
   369
		//chunks independently
sl@0
   370
		ReadNextFrameL(KUidMediaTypeVideo, iVideoPos);
sl@0
   371
		}
sl@0
   372
	}
sl@0
   373
sl@0
   374
/**
sl@0
   375
Fills the aBuffer with audio data depends on interleaved or not.
sl@0
   376
@param aBuffer 
sl@0
   377
*/ 
sl@0
   378
void CAviReader::FillAudioBufferL(CMMFBuffer* aBuffer)
sl@0
   379
	{
sl@0
   380
	if (!aBuffer)
sl@0
   381
		{
sl@0
   382
		User::Leave(KErrArgument);
sl@0
   383
		}
sl@0
   384
	iBufferFromDevSound = aBuffer;
sl@0
   385
	iAudioRequestMade = ETrue;
sl@0
   386
	if (iMainHeader.iFlags == KAVIF_ISINTERLEAVED)
sl@0
   387
		{
sl@0
   388
		//Here Audio and Video data are interleaved in the form of REc lists.
sl@0
   389
		if (!iReadRequestMade)
sl@0
   390
			{
sl@0
   391
			//Read request for REC list is not yet made. So read the REC list into the sourcebuffer.
sl@0
   392
			ReadNextFrameL(TUid::Null(), iSourcePos);
sl@0
   393
			iReadRequestMade = ETrue;
sl@0
   394
			}
sl@0
   395
		else if (iReadCompleted)
sl@0
   396
			{
sl@0
   397
			//audio frame is already read into the audio buffer
sl@0
   398
			//copy the data from the audio buffer to devsound buffer.
sl@0
   399
			CMMFDataBuffer* bufferFromSink = static_cast<CMMFDataBuffer*>(aBuffer);
sl@0
   400
			bufferFromSink->Data().Copy(iAudioBuffer->Data());
sl@0
   401
			ReadComplete();
sl@0
   402
			}
sl@0
   403
		}
sl@0
   404
	else
sl@0
   405
		{
sl@0
   406
		if (iAudioBuffer)
sl@0
   407
			{
sl@0
   408
			BufferFilledL(iAudioBuffer);
sl@0
   409
			}
sl@0
   410
		else
sl@0
   411
			{
sl@0
   412
			//non-interleaved
sl@0
   413
			ReadNextFrameL(KUidMediaTypeAudio, iAudioPos);
sl@0
   414
			}
sl@0
   415
		}
sl@0
   416
	}			
sl@0
   417
sl@0
   418
/**
sl@0
   419
Identifies if the chunk is valid by the media type and fills the data in buffer
sl@0
   420
@param aMediaType
sl@0
   421
@param aPosition
sl@0
   422
*/
sl@0
   423
void CAviReader::ReadNextFrameL(TUid aMediaType, TInt& aPosition)
sl@0
   424
	{
sl@0
   425
	TUint32 dwChunkId = 0;
sl@0
   426
	TUint32 dwChunkSz = 0;
sl@0
   427
	TUint8* rawForm = NULL;
sl@0
   428
	
sl@0
   429
	//We read chunkId and chunkSize first into the headerframe below. If Audio and Video chunks are found, data is read into the respective buffers 
sl@0
   430
	//we skip chunkSize bytes if we come across any other blocks.
sl@0
   431
	CMMFDescriptorBuffer* headerFrame = CMMFDescriptorBuffer::NewL(KChunkHeaderSize);
sl@0
   432
    CleanupStack::PushL(headerFrame);
sl@0
   433
    
sl@0
   434
	for(;;)
sl@0
   435
		{
sl@0
   436
		iClip.ReadBufferL(headerFrame, aPosition);
sl@0
   437
		TInt len = headerFrame->Data().Length();
sl@0
   438
		if (len == 0)
sl@0
   439
			{
sl@0
   440
			SetMediaEOS(aMediaType);
sl@0
   441
			break;
sl@0
   442
			}
sl@0
   443
			
sl@0
   444
		rawForm = &(headerFrame->Data()[0]);
sl@0
   445
		dwChunkId = Read32(rawForm);
sl@0
   446
		if (!IsValidBlock(dwChunkId))
sl@0
   447
			{
sl@0
   448
			//Sometimes we dont get next chunk immediately after the Previous chunk(Padding). 
sl@0
   449
			//we need to search for next valid data chunk ourselves if the chunkId read is not valid
sl@0
   450
			if (!ReadNextFrameStartL(aPosition))
sl@0
   451
				{
sl@0
   452
				//no more data frames
sl@0
   453
				SetMediaEOS(aMediaType);
sl@0
   454
				break;
sl@0
   455
				}
sl@0
   456
			continue;//found valid chunk. so continue to read the chunk
sl@0
   457
			}
sl@0
   458
sl@0
   459
		rawForm += 4; //Skip ChunkId
sl@0
   460
		aPosition += 4; //Skip ChunkId 
sl@0
   461
		dwChunkSz = Read32(rawForm);
sl@0
   462
							
sl@0
   463
		rawForm+=4; //Skip ChunkSize
sl@0
   464
		aPosition += 4; //Skip ChunkSIze
sl@0
   465
sl@0
   466
		if (dwChunkSz == 0)
sl@0
   467
			{
sl@0
   468
			//We may get chunks of length Zero. So loop again to read the next chunk.
sl@0
   469
			continue;
sl@0
   470
			}
sl@0
   471
		if (dwChunkId == KRiffChunkNameList)//list rec
sl@0
   472
			{
sl@0
   473
			if(iMainHeader.iFlags == KAVIF_ISINTERLEAVED)
sl@0
   474
				{
sl@0
   475
				//found REC list. Read the whole list into the SourceBuffer
sl@0
   476
				delete iSourceBuffer;
sl@0
   477
				iSourceBuffer = NULL;
sl@0
   478
				iSourceBuffer = CMMFDescriptorBuffer::NewL(dwChunkSz);
sl@0
   479
				iClip.ReadBufferL(iSourceBuffer,aPosition, this);
sl@0
   480
				aPosition += dwChunkSz;//skip the list size
sl@0
   481
				break;
sl@0
   482
				}
sl@0
   483
			else
sl@0
   484
				{
sl@0
   485
				continue;
sl@0
   486
				}
sl@0
   487
			}
sl@0
   488
		else if (dwChunkId == KRiffChunkNameJunk)//junk
sl@0
   489
			{
sl@0
   490
			//found Junk chunk. Skip it.
sl@0
   491
			aPosition += dwChunkSz;
sl@0
   492
			}
sl@0
   493
		else if ((dwChunkId == KRiffChunkName00db) || (dwChunkId == KRiffChunkName00dc)
sl@0
   494
			|| (dwChunkId == KRiffChunkName01db) || (dwChunkId == KRiffChunkName01dc)) //video
sl@0
   495
			{
sl@0
   496
			if (aMediaType == KUidMediaTypeVideo)
sl@0
   497
				{
sl@0
   498
				//found video when aMediaType is Video. So read the video chunk into the videobuffer.
sl@0
   499
				delete iVideoBuffer;
sl@0
   500
				iVideoBuffer = NULL;
sl@0
   501
				iVideoBuffer = CMMFDescriptorBuffer::NewL(dwChunkSz);
sl@0
   502
				iClip.ReadBufferL(iVideoBuffer,aPosition, this);
sl@0
   503
				aPosition += dwChunkSz;
sl@0
   504
				break;
sl@0
   505
				}
sl@0
   506
			else
sl@0
   507
				{
sl@0
   508
				//found video when aMediaType is not Video. So Skip it.
sl@0
   509
				aPosition += dwChunkSz;	
sl@0
   510
				}
sl@0
   511
			}
sl@0
   512
		else if ((dwChunkId == KRiffChunkName00wb) || (dwChunkId == KRiffChunkName01wb)) //audio
sl@0
   513
			{
sl@0
   514
			if (aMediaType == KUidMediaTypeAudio)
sl@0
   515
				{
sl@0
   516
				//found audio when aMediaType is Audio. So read the audio chunk into the audiobuffer.
sl@0
   517
				delete iAudioBuffer;
sl@0
   518
				iAudioBuffer = NULL;
sl@0
   519
				iAudioBuffer = CMMFDescriptorBuffer::NewL(dwChunkSz);
sl@0
   520
				iClip.ReadBufferL(iAudioBuffer,aPosition, this);	
sl@0
   521
				aPosition += dwChunkSz;
sl@0
   522
				break;	
sl@0
   523
				}
sl@0
   524
			else
sl@0
   525
				{
sl@0
   526
				//found audio when aMediaType is not audio. So Skip it.
sl@0
   527
				aPosition += dwChunkSz;
sl@0
   528
				}		
sl@0
   529
			}
sl@0
   530
		else if (dwChunkId == KRiffChunkNameIdx1)//index block
sl@0
   531
			{
sl@0
   532
			aPosition += dwChunkSz;
sl@0
   533
			//Reached index block. This is placed at the end of the data. No more data
sl@0
   534
			SetMediaEOS(aMediaType);
sl@0
   535
			break;
sl@0
   536
			}
sl@0
   537
	   }
sl@0
   538
	CleanupStack::PopAndDestroy(headerFrame);
sl@0
   539
	
sl@0
   540
	}		
sl@0
   541
sl@0
   542
sl@0
   543
/**
sl@0
   544
Loops through until a valid chunk is identified.
sl@0
   545
@param aStartPos
sl@0
   546
@return ETrue if valid chunk is found.
sl@0
   547
*/
sl@0
   548
TBool CAviReader::ReadNextFrameStartL(TInt& aStartPos)
sl@0
   549
	{
sl@0
   550
	TBool found = EFalse;
sl@0
   551
	TInt count = 0;
sl@0
   552
sl@0
   553
	CMMFDescriptorBuffer* buffer = CMMFDescriptorBuffer::NewL(KReadBufferSize);
sl@0
   554
    CleanupStack::PushL(buffer);
sl@0
   555
	iClip.ReadBufferL(buffer, aStartPos);
sl@0
   556
sl@0
   557
	TUint8* rawform = &(buffer->Data()[0]);
sl@0
   558
	
sl@0
   559
	while (count < KReadBufferSize)
sl@0
   560
		{
sl@0
   561
		if (IsValidBlock(Read32(rawform)))
sl@0
   562
			{
sl@0
   563
			found = ETrue;
sl@0
   564
			break;
sl@0
   565
			}
sl@0
   566
		aStartPos++;
sl@0
   567
		rawform++;
sl@0
   568
		count++;
sl@0
   569
		}
sl@0
   570
	CleanupStack::PopAndDestroy(buffer);
sl@0
   571
	return found;
sl@0
   572
	}
sl@0
   573
sl@0
   574
/**
sl@0
   575
Identifies a valid audio and video chunk is present
sl@0
   576
@param aChunkId
sl@0
   577
@return ETrue if validblock is found else EFalse.
sl@0
   578
*/
sl@0
   579
TBool CAviReader::IsValidBlock(TUint aChunkId) 
sl@0
   580
	{
sl@0
   581
	switch(aChunkId)
sl@0
   582
		{
sl@0
   583
		case KRiffChunkName00wb:
sl@0
   584
		case KRiffChunkName01wb:
sl@0
   585
		case KRiffChunkName00db:
sl@0
   586
		case KRiffChunkName00dc:
sl@0
   587
		case KRiffChunkName01db:
sl@0
   588
		case KRiffChunkName01dc:	
sl@0
   589
		case KRiffChunkNameList:
sl@0
   590
		case KRiffChunkNameJunk:
sl@0
   591
		case KRiffChunkNameIdx1:
sl@0
   592
			return ETrue;
sl@0
   593
		default:
sl@0
   594
			return EFalse;
sl@0
   595
		}
sl@0
   596
	}			
sl@0
   597
sl@0
   598
/**
sl@0
   599
Fills the buffer with audio/Video data and informs the observer
sl@0
   600
@param aBuffer
sl@0
   601
*/
sl@0
   602
void CAviReader::BufferFilledL(CMMFBuffer* aBuffer)
sl@0
   603
	{
sl@0
   604
	if (!aBuffer)
sl@0
   605
		{
sl@0
   606
		User::Leave(KErrArgument);
sl@0
   607
		}
sl@0
   608
	if (aBuffer == iVideoBuffer)
sl@0
   609
		{
sl@0
   610
		//callback for video read when the file is not interleaved(No REC lists)
sl@0
   611
		iBufferFromDevVideo->iData.Copy(iVideoBuffer->Data());
sl@0
   612
		iObserver.VideoBufferFilled(iBufferFromDevVideo);
sl@0
   613
		}
sl@0
   614
	else if (aBuffer == iAudioBuffer) 
sl@0
   615
		{
sl@0
   616
		//callback for audio read when the file is not interleaved(No REC lists)
sl@0
   617
		CMMFDataBuffer* bufferFromSink = static_cast<CMMFDataBuffer*>(iBufferFromDevSound);
sl@0
   618
sl@0
   619
		TInt sinkBufLen = bufferFromSink->Data().MaxSize();
sl@0
   620
		TInt audBufLen = iAudioBuffer->Data().Length();
sl@0
   621
		
sl@0
   622
		if (sinkBufLen < audBufLen)
sl@0
   623
			{
sl@0
   624
			bufferFromSink->Data().Copy(iAudioBuffer->Data().Ptr(), sinkBufLen);
sl@0
   625
			CMMFDescriptorBuffer* tempBuffer = CMMFDescriptorBuffer::NewL(audBufLen - sinkBufLen);
sl@0
   626
			tempBuffer->Data().Copy(iAudioBuffer->Data().Mid(sinkBufLen));
sl@0
   627
			delete iAudioBuffer;
sl@0
   628
			iAudioBuffer = tempBuffer;
sl@0
   629
			}
sl@0
   630
		else
sl@0
   631
			{
sl@0
   632
			// DEF113319 - call SetLastBuffer when sending last audio chunk
sl@0
   633
			TInt position = 0;
sl@0
   634
			position = (iMainHeader.iFlags == KAVIF_ISINTERLEAVED) ? iSourcePos : iAudioPos;
sl@0
   635
			if(!IsAudioDataAvailableL(position))
sl@0
   636
				{
sl@0
   637
				bufferFromSink->SetLastBuffer(ETrue);
sl@0
   638
				SetMediaEOS(KUidMediaTypeAudio);
sl@0
   639
				}
sl@0
   640
sl@0
   641
			bufferFromSink->Data().Copy(iAudioBuffer->Data());
sl@0
   642
			delete iAudioBuffer;
sl@0
   643
			iAudioBuffer = NULL;
sl@0
   644
			}
sl@0
   645
		iObserver.AudioBufferFilled();
sl@0
   646
		}
sl@0
   647
	else if (aBuffer == iSourceBuffer)//callback for REC list
sl@0
   648
		{
sl@0
   649
		//callback for REC list read. We need to extract video and audio chunks from the sourcebuffer
sl@0
   650
		TUint8* rawform = &(iSourceBuffer->Data()[0]);
sl@0
   651
		TInt desPos = 0; //position in descriptor
sl@0
   652
sl@0
   653
		//Now we should be pointing to audio or video chunks
sl@0
   654
		TInt bufLen = iSourceBuffer->Data().Length();
sl@0
   655
		if(bufLen < 4)
sl@0
   656
			{
sl@0
   657
			User::Leave(KErrCorrupt);	
sl@0
   658
			}
sl@0
   659
		rawform += 4; //skip the fourcc of REC
sl@0
   660
		desPos += 4; //byte count corresponding to where rawform points to
sl@0
   661
		
sl@0
   662
		if (bufLen - desPos < 8)
sl@0
   663
		 	{
sl@0
   664
		 	//if the buffer is not long enough to accomodate - chunk id and size leave
sl@0
   665
		  	User::Leave(KErrCorrupt);
sl@0
   666
		  	}
sl@0
   667
sl@0
   668
		for (TUint8 i=0; i < iMainHeader.iStreams; i++)//we expect only 2 streams at the moment
sl@0
   669
			{
sl@0
   670
			if (desPos == bufLen) //caution check for the necessity of the block
sl@0
   671
				{
sl@0
   672
	 			//Sometimes we only have one stream in this list. No more data to read
sl@0
   673
				break;
sl@0
   674
				}
sl@0
   675
sl@0
   676
			if (bufLen - desPos < 8 && i== 1)
sl@0
   677
			 	{
sl@0
   678
			 	//if the buffer is not long enough to accomodate - chunk id and size leave
sl@0
   679
			  	break;
sl@0
   680
			  	}
sl@0
   681
sl@0
   682
			TUint32 dwChunkId = Read32(rawform);
sl@0
   683
			rawform += 4; //Skip chunkId
sl@0
   684
			desPos += 4;
sl@0
   685
			TBool bAudioId = EFalse;
sl@0
   686
			TBool bVideoId = EFalse;
sl@0
   687
			switch (dwChunkId)	//identify chunk
sl@0
   688
				{
sl@0
   689
				case KRiffChunkName00db:
sl@0
   690
				case KRiffChunkName00dc:
sl@0
   691
				case KRiffChunkName01db:
sl@0
   692
				case KRiffChunkName01dc:
sl@0
   693
					bVideoId = ETrue;
sl@0
   694
					break;
sl@0
   695
				case KRiffChunkName00wb:
sl@0
   696
				case KRiffChunkName01wb:
sl@0
   697
					bAudioId = ETrue;
sl@0
   698
					break;
sl@0
   699
				default:
sl@0
   700
					User::Leave(KErrCorrupt);
sl@0
   701
				}
sl@0
   702
			
sl@0
   703
			if (!bAudioId && !bVideoId)
sl@0
   704
				{
sl@0
   705
				//we are supposed to get audio or video stream here. if anything else, we return KErrCorrupt				
sl@0
   706
				User::Leave(KErrCorrupt);
sl@0
   707
				}
sl@0
   708
			TUint32 dwChunkSz = Read32(rawform);
sl@0
   709
			if (dwChunkSz > bufLen - desPos)
sl@0
   710
				{
sl@0
   711
				User::Leave(KErrCorrupt); //caution - check	
sl@0
   712
				}
sl@0
   713
			rawform += 4; //Skip chunkSize
sl@0
   714
			desPos += 4;
sl@0
   715
			TPtr8 temp = iSourceBuffer->Data().MidTPtr(desPos, dwChunkSz);
sl@0
   716
			if (bVideoId)// video
sl@0
   717
				{
sl@0
   718
				if (iVideoRequestMade)
sl@0
   719
					{
sl@0
   720
					//if video request is already made we can copy the data directly into the devvideo buffer
sl@0
   721
					//instead of iVideoBuffer
sl@0
   722
					iBufferFromDevVideo->iData.Copy(temp);
sl@0
   723
					}
sl@0
   724
				else 
sl@0
   725
					{
sl@0
   726
					//DevVideo request is not made. So copy the data into video buffer
sl@0
   727
					delete iVideoBuffer;
sl@0
   728
					iVideoBuffer = NULL;
sl@0
   729
					iVideoBuffer = CMMFDescriptorBuffer::NewL(dwChunkSz);
sl@0
   730
					iVideoBuffer->Data().Copy(temp);
sl@0
   731
					}
sl@0
   732
				}
sl@0
   733
			else if (bAudioId)//audio
sl@0
   734
				{
sl@0
   735
				if (iAudioRequestMade)
sl@0
   736
					{
sl@0
   737
					//if audio request is already made, copy the data into devsound buffer
sl@0
   738
					CMMFDataBuffer* bufferFromSink = static_cast<CMMFDataBuffer*>(iBufferFromDevSound);
sl@0
   739
					bufferFromSink->Data().Copy(temp);
sl@0
   740
					}
sl@0
   741
				else 
sl@0
   742
					{
sl@0
   743
					//DevSound request is not made. copy the audio chunk into audio buffer
sl@0
   744
					delete iAudioBuffer;
sl@0
   745
					iAudioBuffer = NULL;
sl@0
   746
					iAudioBuffer = CMMFDescriptorBuffer::NewL(dwChunkSz);
sl@0
   747
					iAudioBuffer->Data().Copy(temp);
sl@0
   748
					}
sl@0
   749
				}
sl@0
   750
			rawform	+= dwChunkSz;//Skip video/audio chunk
sl@0
   751
			desPos += dwChunkSz;	
sl@0
   752
			}
sl@0
   753
		iReadCompleted = ETrue;//REC list is read
sl@0
   754
		// we send the bufferfilled callbacks after both audio and video requests are made.
sl@0
   755
		ReadComplete();
sl@0
   756
		}
sl@0
   757
	else
sl@0
   758
		{
sl@0
   759
		User::Leave(KErrCorrupt);
sl@0
   760
		}
sl@0
   761
	}
sl@0
   762
sl@0
   763
/**
sl@0
   764
Informs audio and video data in rec list is read and the buffer can
sl@0
   765
now be sent for decoding.This function is specific for interleaved files
sl@0
   766
where it is sent for decoding only after both audio and video data is read.
sl@0
   767
*/
sl@0
   768
void CAviReader::ReadComplete()
sl@0
   769
	{
sl@0
   770
	if ((iAudioRequestMade) && (iVideoRequestMade))
sl@0
   771
		{
sl@0
   772
		//reset back everything for the next cycle
sl@0
   773
		iReadRequestMade = EFalse;
sl@0
   774
		iReadCompleted = EFalse;
sl@0
   775
		iAudioRequestMade = EFalse;
sl@0
   776
		iVideoRequestMade = EFalse;
sl@0
   777
		iObserver.VideoBufferFilled(iBufferFromDevVideo);
sl@0
   778
		iObserver.AudioBufferFilled();
sl@0
   779
		}
sl@0
   780
	}
sl@0
   781
sl@0
   782
/**
sl@0
   783
Resets the data positions in the file 
sl@0
   784
*/			
sl@0
   785
void CAviReader::ResetL()
sl@0
   786
	{
sl@0
   787
	iVideoEos = EFalse;
sl@0
   788
	iAudioEos = EFalse;
sl@0
   789
	iAudioPos = iSourcePos;
sl@0
   790
	iVideoPos = iSourcePos;
sl@0
   791
	iReadRequestMade = EFalse;
sl@0
   792
	iReadCompleted = EFalse;
sl@0
   793
	iAudioRequestMade = EFalse;
sl@0
   794
	iVideoRequestMade = EFalse;
sl@0
   795
	iClip.SourceStopL();
sl@0
   796
	}
sl@0
   797
sl@0
   798
/**
sl@0
   799
Identifies if video data in the clip is fully read.
sl@0
   800
@return ETrue if end of videodata
sl@0
   801
*/			
sl@0
   802
TBool CAviReader::IsVideoInputEnd()
sl@0
   803
	{
sl@0
   804
	return iVideoEos;		
sl@0
   805
	}
sl@0
   806
sl@0
   807
/**
sl@0
   808
Identifies if audio data in the clip is fully read.
sl@0
   809
@return ETrue if end of audiodata
sl@0
   810
*/		
sl@0
   811
TBool CAviReader::IsAudioInputEnd()
sl@0
   812
	{
sl@0
   813
	return iAudioEos;		
sl@0
   814
	}
sl@0
   815
	
sl@0
   816
/**
sl@0
   817
Set the position in the file to play from
sl@0
   818
@param aPosition - this is not used.
sl@0
   819
@leave KErrNotSupported.
sl@0
   820
*/
sl@0
   821
void CAviReader::SetPositionL(TInt /*aPosition*/)
sl@0
   822
	{
sl@0
   823
	//This will leave KErrNotSuuported as there is no support to
sl@0
   824
	//seek the position in an .avi file.
sl@0
   825
	User::Leave(KErrNotSupported);
sl@0
   826
	}
sl@0
   827
sl@0
   828
/**
sl@0
   829
Returns if audio is enabled in an .avi file.
sl@0
   830
@param aEnabled.
sl@0
   831
*/
sl@0
   832
void CAviReader::AudioEnabled(TBool& aEnabled)
sl@0
   833
	{
sl@0
   834
	aEnabled = iAudioEnabled;
sl@0
   835
	}
sl@0
   836
	
sl@0
   837
sl@0
   838
/**
sl@0
   839
Returns the frame rate applied for video
sl@0
   840
@param aFramesPerSecond
sl@0
   841
*/
sl@0
   842
void CAviReader::FrameRate(TReal32 &aFramesPerSecond)
sl@0
   843
	{
sl@0
   844
	ASSERT(iVideoIdx > KInvalidMediaIdx);
sl@0
   845
	if (iStreamHeader[iVideoIdx].iScale == 0)	
sl@0
   846
		{
sl@0
   847
		//If this value is 0 consider it as 1 second.
sl@0
   848
		iStreamHeader[iVideoIdx].iScale = 1; 
sl@0
   849
		}	
sl@0
   850
	aFramesPerSecond = iStreamHeader[iVideoIdx].iRate;	
sl@0
   851
	}
sl@0
   852
sl@0
   853
/**
sl@0
   854
Returns the sample rate applied for audio.
sl@0
   855
@return audio samplerate 
sl@0
   856
*/	
sl@0
   857
TInt CAviReader::SampleRate()
sl@0
   858
	{
sl@0
   859
	ASSERT(iAudioIdx > KInvalidMediaIdx);
sl@0
   860
	return iPCMWaveFormat.iWaveFormat.iNSamplesPerSec ;
sl@0
   861
	}
sl@0
   862
sl@0
   863
/**
sl@0
   864
Returns the number of channels set in audio.
sl@0
   865
@return number of audio channels.
sl@0
   866
*/	
sl@0
   867
TInt CAviReader::Channels()
sl@0
   868
	{
sl@0
   869
	ASSERT(iAudioIdx > KInvalidMediaIdx);
sl@0
   870
	return iPCMWaveFormat.iWaveFormat.iNChannels;
sl@0
   871
	}
sl@0
   872
sl@0
   873
/**
sl@0
   874
Returns the bits per sample for audio.
sl@0
   875
@return bitspersample
sl@0
   876
*/
sl@0
   877
TInt CAviReader::BitsPerSample()
sl@0
   878
	{
sl@0
   879
	ASSERT(iAudioIdx > KInvalidMediaIdx);
sl@0
   880
	return iPCMWaveFormat.iBitsPerSample;
sl@0
   881
	}
sl@0
   882
	
sl@0
   883
sl@0
   884
/**
sl@0
   885
Returns the framesize of video file.
sl@0
   886
@param aFrameSize
sl@0
   887
*/
sl@0
   888
void CAviReader::VideoFrameSize(TSize &aFrameSize)
sl@0
   889
	{
sl@0
   890
	ASSERT(iVideoIdx > KInvalidMediaIdx);
sl@0
   891
	aFrameSize.iHeight = iMainHeader.iHeight;
sl@0
   892
	aFrameSize.iWidth =  iMainHeader.iWidth;
sl@0
   893
	}	
sl@0
   894
	
sl@0
   895
/**
sl@0
   896
Returns the Video codec used in the video file
sl@0
   897
@param aMimeType -this is not used
sl@0
   898
*/
sl@0
   899
void CAviReader::VideoMimeType(TDes8& /*aMimeType*/)
sl@0
   900
	{
sl@0
   901
	//there is no conversion from fcchandler to descriptor
sl@0
   902
	}
sl@0
   903
sl@0
   904
/**
sl@0
   905
Returns the audioCodec used in the video file. 
sl@0
   906
@param aCodec
sl@0
   907
*/	
sl@0
   908
void CAviReader::AudioCodec(TFourCC& /*aCodec*/)
sl@0
   909
	{
sl@0
   910
	//there is no conversion from iFccHandler to descriptor
sl@0
   911
	}
sl@0
   912
sl@0
   913
/**
sl@0
   914
Returns the duration of video file.
sl@0
   915
@return Duration of the file in TTimeIntervalMicroSeconds
sl@0
   916
*/
sl@0
   917
TTimeIntervalMicroSeconds CAviReader::Duration() const
sl@0
   918
	{
sl@0
   919
	ASSERT(iVideoIdx > KInvalidMediaIdx);
sl@0
   920
	ASSERT(iStreamHeader[iVideoIdx].iRate);
sl@0
   921
	return (iMainHeader.iTotalFrames*1000000)/iStreamHeader[iVideoIdx].iRate;				
sl@0
   922
	}
sl@0
   923
	
sl@0
   924
/**
sl@0
   925
Sets the playwindow for playing audio and video.
sl@0
   926
@param aStart
sl@0
   927
@param aEnd
sl@0
   928
*/	
sl@0
   929
void CAviReader::SetPlayWindowL(TTimeIntervalMicroSeconds /*aStart*/,TTimeIntervalMicroSeconds /*aEnd*/)
sl@0
   930
	{
sl@0
   931
	//this will leave with KErrNotSupported as there is no
sl@0
   932
	//support for seeking the position in the file.
sl@0
   933
	User::Leave(KErrNotSupported);
sl@0
   934
	}
sl@0
   935
	
sl@0
   936
/**
sl@0
   937
Sets the end of audio and video data.
sl@0
   938
@param aMediaType
sl@0
   939
*/	
sl@0
   940
void CAviReader::SetMediaEOS(TUid aMediaType)	
sl@0
   941
	{
sl@0
   942
	if (aMediaType == KUidMediaTypeAudio) //end of audio
sl@0
   943
		{
sl@0
   944
		iAudioEos = ETrue;	
sl@0
   945
		}
sl@0
   946
	else if (aMediaType == KUidMediaTypeVideo)//end of video
sl@0
   947
		{
sl@0
   948
		iVideoEos = ETrue;
sl@0
   949
		}
sl@0
   950
	else //end of REC lists
sl@0
   951
		{
sl@0
   952
		iAudioEos = ETrue;
sl@0
   953
		iVideoEos = ETrue;
sl@0
   954
		}
sl@0
   955
	}
sl@0
   956
sl@0
   957
//MDataSink
sl@0
   958
CMMFBuffer* CAviReader::CreateSinkBufferL(TMediaId /*aMediaId*/, TBool&/*aReference*/)
sl@0
   959
	{
sl@0
   960
	User::Leave(KErrNotSupported);
sl@0
   961
	return NULL;
sl@0
   962
	}
sl@0
   963
sl@0
   964
void CAviReader::ConstructSinkL( const TDesC8& /*aInitData*/)
sl@0
   965
	{
sl@0
   966
	User::Leave(KErrNotSupported);
sl@0
   967
	}
sl@0
   968
	
sl@0
   969
TFourCC CAviReader::SinkDataTypeCode(TMediaId /*aMediaId*/)
sl@0
   970
	{
sl@0
   971
	return 0;
sl@0
   972
	}
sl@0
   973
		
sl@0
   974
void CAviReader::EmptyBufferL(CMMFBuffer* /*aBuffer*/, MDataSource* /*aSupplier*/, TMediaId /*aMediaId*/)
sl@0
   975
	{
sl@0
   976
	User::Leave(KErrNotSupported);
sl@0
   977
	}
sl@0
   978
	
sl@0
   979
TBool CAviReader::CanCreateSinkBuffer()
sl@0
   980
	{
sl@0
   981
	return EFalse;	
sl@0
   982
	}
sl@0
   983
sl@0
   984
/**
sl@0
   985
// DEF113319 - added to check last audio chunk
sl@0
   986
Loops through to check whether valid audio chunk is available.
sl@0
   987
@param aStartPos
sl@0
   988
@return ETrue if valid audio chunk is found.
sl@0
   989
*/
sl@0
   990
TBool CAviReader::IsAudioDataAvailableL(TInt aStartPos)
sl@0
   991
	{
sl@0
   992
	TBool foundValidAudioChunk = EFalse;
sl@0
   993
	TUint32 dwChunkId = 0;
sl@0
   994
	TUint8* rawform = NULL;
sl@0
   995
sl@0
   996
	CMMFDescriptorBuffer* headerFrame = CMMFDescriptorBuffer::NewL(KChunkHeaderSize);
sl@0
   997
    CleanupStack::PushL(headerFrame);
sl@0
   998
	
sl@0
   999
	for(;;)
sl@0
  1000
		{
sl@0
  1001
		iClip.ReadBufferL(headerFrame, aStartPos);
sl@0
  1002
		TInt len = headerFrame->Data().Length();
sl@0
  1003
		if (len == 0)
sl@0
  1004
			{
sl@0
  1005
			// end of stream
sl@0
  1006
			break;
sl@0
  1007
			}
sl@0
  1008
		rawform = &(headerFrame->Data()[0]);
sl@0
  1009
		dwChunkId = Read32(rawform);
sl@0
  1010
		
sl@0
  1011
		if (!IsValidBlock(dwChunkId))
sl@0
  1012
			{
sl@0
  1013
			// No valid chunk id found ... 
sl@0
  1014
			//Sometimes we dont get next chunk immediately after the Previous chunk(Padding). 
sl@0
  1015
			//we need to search for next valid data chunk ourselves if the chunkId read is not valid
sl@0
  1016
			if (!ReadNextFrameStartL(aStartPos))
sl@0
  1017
				{
sl@0
  1018
				// reached EOS 
sl@0
  1019
				break;
sl@0
  1020
				}
sl@0
  1021
			continue;//found valid chunk. so continue to read the chunk
sl@0
  1022
			}
sl@0
  1023
		if ((dwChunkId == KRiffChunkName00wb) || (dwChunkId == KRiffChunkName01wb)) // check if its valid audio chunk
sl@0
  1024
			{
sl@0
  1025
			foundValidAudioChunk = ETrue;
sl@0
  1026
			break;
sl@0
  1027
			}
sl@0
  1028
		// non audio chunk found, so go and look for next frame header
sl@0
  1029
		rawform += 4; //Skip ChunkId
sl@0
  1030
		aStartPos += ((Read32(rawform)) + 4 + 4); //Skip: 1. dwChunkSz, 2. ChunkSize(4), 3.ChunkId(4) 
sl@0
  1031
		}
sl@0
  1032
	CleanupStack::PopAndDestroy(headerFrame);
sl@0
  1033
	return foundValidAudioChunk;
sl@0
  1034
	}