os/mm/mmplugins/mmfwplugins/src/Plugin/Controller/Video/AviPlayController/avireader.cpp
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.
16 #include "avireader.h"
18 const TInt KReadBufferSize = 0x8000; // 4k
19 const TInt KChunkHeaderSize = 8;
21 const TInt KInvalidMediaIdx = -1;
23 #define RiffChunkName(A,B,C,D) ((D<<24)+(C<<16)+(B<<8)+A)
25 const TInt KRiffChunkNameRiff = RiffChunkName('R','I','F','F');
26 const TInt KRiffChunkNameList = RiffChunkName('L','I','S','T');
27 const TInt KRiffChunkNameAvih = RiffChunkName('a','v','i','h');
28 const TInt KRiffChunkTypeAvi = RiffChunkName('A','V','I',' ');
29 const TInt KRiffChunkTypeHdrl = RiffChunkName('h','d','r','l');
30 const TInt KRiffChunkTypeStrl = RiffChunkName('s','t','r','l');
31 const TInt KRiffChunkNameStrh = RiffChunkName('s','t','r','h');
32 const TInt KRiffChunkNameStrf = RiffChunkName('s','t','r','f');
33 const TInt KRiffChunkNameStrn = RiffChunkName('s','t','r','n');
34 const TInt KRiffChunkTypeVids = RiffChunkName('v','i','d','s');
35 const TInt KRiffChunkTypeAuds = RiffChunkName('a','u','d','s');
36 const TInt KRiffChunkNameJunk = RiffChunkName('J','U','N','K');
37 const TInt KRiffChunkTypeMovi = RiffChunkName('m','o','v','i');
38 const TInt KRiffChunkName00db = RiffChunkName('0','0','d','b');
39 const TInt KRiffChunkName00dc = RiffChunkName('0','0','d','c');
40 const TInt KRiffChunkName00wb = RiffChunkName('0','0','w','b');
41 const TInt KRiffChunkName01wb = RiffChunkName('0','1','w','b');
42 const TInt KRiffChunkName01db = RiffChunkName('0','1','d','b');
43 const TInt KRiffChunkName01dc = RiffChunkName('0','1','d','c');
44 const TInt KRiffChunkNameXvid = RiffChunkName('X','V','I','D');
45 const TInt KRiffChunkNameIdx1 = RiffChunkName('i','d','x','1');
46 const TInt KRiffChunkNameStrd = RiffChunkName('s','t','r','d');
47 const TInt KRiffChunkNameIndex = RiffChunkName('i','n','d','x');
48 const TInt KRiffChunkNameVprp = RiffChunkName('v','p','r','p');
49 const TInt KAVIF_ISINTERLEAVED = 0x00000001;
54 //CAviReader Functions
57 Fast read for non-aligned 16 bit data.
61 LOCAL_C TUint16 Read16(const TUint8* aPtr)
63 return *(TUint16*)aPtr;
67 Fast read for non-aligned 32 bit data.
71 LOCAL_C TUint32 Read32(const TUint8* aPtr)
81 Creates CAviReader object.
86 CAviReader* CAviReader::NewL(CMMFClip& aClip, MAviReaderObserver& aObserver)
88 CAviReader* self = new(ELeave) CAviReader(aClip, aObserver);
89 CleanupStack::PushL(self);
91 CleanupStack::Pop(self);
96 Constructor of CAviReader
98 CAviReader::CAviReader(CMMFClip& aClip, MAviReaderObserver& aObserver)
99 :MDataSink(KNullUid),iObserver(aObserver),iClip(aClip),iAudioIdx(KInvalidMediaIdx),
100 iVideoIdx(KInvalidMediaIdx)
105 Destructor of CAviReader
107 CAviReader::~CAviReader()
111 delete iSourceBuffer;
115 Second phase constructor.
117 void CAviReader::ConstructL()
119 if (iClip.Size() > 0)
121 iClip.SourcePrimeL();
122 iSourceBuffer = CMMFDescriptorBuffer::NewL(KReadBufferSize);
128 User::Leave(KErrCorrupt);
133 Reads the header information in the clip.
134 @leave KErrCorrupt if the header information is incorrect.
136 TInt CAviReader::ReadFormatL()
138 User::LeaveIfError(FindRiffChunksL());
143 Reads the header information in the clip.
144 @return KErrNone on Success or KErrCorrupt on incorrect header.
146 TInt CAviReader::FindRiffChunksL()
148 TBool videoEnabled = EFalse;
149 iClip.ReadBufferL(iSourceBuffer,0);
150 TUint8* rawform = &(iSourceBuffer->Data()[0]);
151 TUint8* pBufBegin = rawform;
152 if (Read32(rawform) != KRiffChunkNameRiff)
154 return KErrCorrupt; //not a RIFF file
157 rawform+=4;// skip file size
158 if (Read32(rawform) != KRiffChunkTypeAvi)
160 return KErrCorrupt;//not an .avi file
163 if (Read32(rawform) != KRiffChunkNameList)
165 return KErrCorrupt; //it is not a list
168 TUint32 dwToRead = Read32(rawform);
169 rawform+=4;//crossed the list size
170 if (Read32(rawform) !=KRiffChunkTypeHdrl)
175 if (Read32(rawform) != KRiffChunkNameAvih)
180 rawform+=4; //skip chunk size
181 iMainHeader.iMicroSecPerFrame = Read32(rawform);rawform+=4;
182 iMainHeader.iMaxBytesPerSec = Read32(rawform);rawform+=4;
183 iMainHeader.iPaddingGranularity= Read32(rawform);rawform+=4;
184 //Audio gives underflow if the file is interleaved.So audio and video
185 //is read separately.
186 iMainHeader.iFlags= Read32(rawform); rawform+=4;
187 iMainHeader.iTotalFrames= Read32(rawform);rawform+=4;
188 iMainHeader.iInitialFrames= Read32(rawform);rawform+=4;
189 iMainHeader.iStreams = Read32(rawform);rawform+=4;
190 if(iMainHeader.iStreams > 2)
194 iMainHeader.iSuggestedBufferSize= Read32(rawform);rawform+=4;
195 iMainHeader.iWidth= Read32(rawform);rawform+=4;
196 iMainHeader.iHeight= Read32(rawform);rawform+=4;
197 iMainHeader.iReserved[0]= Read32(rawform);rawform+=4;
198 iMainHeader.iReserved[1]= Read32(rawform);rawform+=4;
199 iMainHeader.iReserved[2]= Read32(rawform);rawform+=4;
200 iMainHeader.iReserved[3]= Read32(rawform);rawform+=4;
202 for (TUint8 i=0; i < iMainHeader.iStreams; i++)
204 if(Read32(rawform) != KRiffChunkNameList)
209 rawform+=4; //skip list size;
210 if(Read32(rawform) != KRiffChunkTypeStrl)
215 if(Read32(rawform) != KRiffChunkNameStrh)
219 rawform+=4;//read stream header chunk
220 rawform+=4; //skip stream header chunk size;
221 iStreamHeader[i].iFccType = Read32(rawform);rawform+=4;
222 iStreamHeader[i].iFccHandler = Read32(rawform);rawform+=4;
223 iStreamHeader[i].iFlags= Read32(rawform);rawform+=4;
224 iStreamHeader[i].iReserved = Read32(rawform);rawform+=4;
225 iStreamHeader[i].iInitialFrames =Read32(rawform);rawform+=4;
226 iStreamHeader[i].iScale =Read32(rawform);rawform+=4;
227 iStreamHeader[i].iRate= Read32(rawform);rawform+=4;
228 iStreamHeader[i].iStart = Read32(rawform);rawform+=4;
229 iStreamHeader[i].iLength = Read32(rawform);rawform+=4;
230 iStreamHeader[i].iSuggestedBufferSize = Read32(rawform);rawform+=4;
231 iStreamHeader[i].iQuality = Read32(rawform);rawform+=4;
232 iStreamHeader[i].iSampleSize = Read32(rawform);rawform+=4;
233 iStreamHeader[i].iRcFrame.iLeft =Read16(rawform);rawform+=2;
234 iStreamHeader[i].iRcFrame.iTop =Read16(rawform);rawform+=2;
235 iStreamHeader[i].iRcFrame.iRight =Read16(rawform);rawform+=2;
236 iStreamHeader[i].iRcFrame.iBottom =Read16(rawform);rawform+=2;
237 if (Read32(rawform) != KRiffChunkNameStrf)
241 rawform+=4;//read stream format chunk
242 TInt chunklen = Read32(rawform);
243 rawform+=4; //skip stream format chunk size;
245 if (iStreamHeader[i].iFccType == KRiffChunkTypeAuds) //if audio stream
251 iAudioEnabled = ETrue;
252 if (Read16(rawform) == 0x0001) // Do not have support except PCM
254 iPCMWaveFormat.iWaveFormat.iFormatTag = Read16(rawform);rawform+=2;
255 iPCMWaveFormat.iWaveFormat.iNChannels = Read16(rawform);rawform+=2;
256 iPCMWaveFormat.iWaveFormat.iNSamplesPerSec = Read32(rawform);rawform+=4;
257 iPCMWaveFormat.iWaveFormat.iNAvgBytesPerSec= Read32(rawform); rawform+=4;
258 iPCMWaveFormat.iWaveFormat.iNBlockAlign = Read16(rawform);rawform+=2;
259 iPCMWaveFormat.iBitsPerSample = Read16(rawform);rawform+=2;
265 return KErrNotSupported;
269 else if (iStreamHeader[i].iFccType == KRiffChunkTypeVids) //if video stream
271 if(iStreamHeader[i].iFccHandler != KRiffChunkNameXvid)
273 return KErrNotSupported;
280 TUint8* temp = rawform;
282 iBitmapInfoHeader.iBiSize= Read32(rawform);rawform+=4;
283 iBitmapInfoHeader.iBiWidth= Read32(rawform);rawform+=4;
284 iBitmapInfoHeader.iBiHeight= Read32(rawform);rawform+=4;
285 iBitmapInfoHeader.iBiPlanes= Read16(rawform);rawform+=2;
286 iBitmapInfoHeader.iBiBitCount= Read16(rawform);rawform+=2;
287 iBitmapInfoHeader.iBiCompression= Read32(rawform);rawform+=4;
288 iBitmapInfoHeader.iBiSizeImage= Read32(rawform);rawform+=4;
289 iBitmapInfoHeader.iBiXPelsPerMeter= Read32(rawform);rawform+=4;
290 iBitmapInfoHeader.iBiYPelsPerMeter= Read32(rawform);rawform+=4;
291 iBitmapInfoHeader.iBiClrUsed= Read32(rawform);rawform+=4;
292 iBitmapInfoHeader.iBiClrImportant= Read32(rawform);rawform+=4;
294 rawform = temp + chunklen;
297 videoEnabled = ETrue;
299 else //if unidentified stream types.
304 TUint32 temp = Read32(rawform);
305 while (temp == KRiffChunkNameStrn || temp == KRiffChunkNameStrd || temp == KRiffChunkNameJunk || temp == KRiffChunkNameIndex || temp == KRiffChunkNameVprp) // Skipping the chunks
308 temp = Read32(rawform);
310 temp = Read32(rawform);
314 //added to skip the rest of the header to reach movi list.
315 TInt bytesRead = rawform - pBufBegin;
316 iSourcePos = bytesRead;
318 for (TInt i = 0; i < KReadBufferSize - bytesRead; i ++)
320 if(Read32(rawform) == KRiffChunkTypeMovi)
323 iAudioPos = iSourcePos;
324 iVideoPos = iSourcePos;
334 Fills the aBuffer with video data depends on interleaved or not.
337 void CAviReader::FillVideoBufferL(TVideoInputBuffer* aBuffer)
341 User::Leave(KErrArgument);
343 iBufferFromDevVideo = aBuffer;
344 iVideoRequestMade = ETrue;
346 if (iMainHeader.iFlags == KAVIF_ISINTERLEAVED)
349 //Here Audio and Video data are interleaved in the form of REc lists.
350 if (!iReadRequestMade)
352 //Read request for REC list is not yet made. So read the REC list into the sourcebuffer.
353 ReadNextFrameL(TUid::Null(), iSourcePos);
354 iReadRequestMade = ETrue;
357 else if (iReadCompleted)
359 //REC list is already read into the video buffer.
360 //copy the data from the video buffer to devvideo buffer.
361 aBuffer->iData.Copy(iVideoBuffer->Data());
368 //There are no REC lists. Audio and Video is spread across the file. So we read audio and video
369 //chunks independently
370 ReadNextFrameL(KUidMediaTypeVideo, iVideoPos);
375 Fills the aBuffer with audio data depends on interleaved or not.
378 void CAviReader::FillAudioBufferL(CMMFBuffer* aBuffer)
382 User::Leave(KErrArgument);
384 iBufferFromDevSound = aBuffer;
385 iAudioRequestMade = ETrue;
386 if (iMainHeader.iFlags == KAVIF_ISINTERLEAVED)
388 //Here Audio and Video data are interleaved in the form of REc lists.
389 if (!iReadRequestMade)
391 //Read request for REC list is not yet made. So read the REC list into the sourcebuffer.
392 ReadNextFrameL(TUid::Null(), iSourcePos);
393 iReadRequestMade = ETrue;
395 else if (iReadCompleted)
397 //audio frame is already read into the audio buffer
398 //copy the data from the audio buffer to devsound buffer.
399 CMMFDataBuffer* bufferFromSink = static_cast<CMMFDataBuffer*>(aBuffer);
400 bufferFromSink->Data().Copy(iAudioBuffer->Data());
408 BufferFilledL(iAudioBuffer);
413 ReadNextFrameL(KUidMediaTypeAudio, iAudioPos);
419 Identifies if the chunk is valid by the media type and fills the data in buffer
423 void CAviReader::ReadNextFrameL(TUid aMediaType, TInt& aPosition)
425 TUint32 dwChunkId = 0;
426 TUint32 dwChunkSz = 0;
427 TUint8* rawForm = NULL;
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
430 //we skip chunkSize bytes if we come across any other blocks.
431 CMMFDescriptorBuffer* headerFrame = CMMFDescriptorBuffer::NewL(KChunkHeaderSize);
432 CleanupStack::PushL(headerFrame);
436 iClip.ReadBufferL(headerFrame, aPosition);
437 TInt len = headerFrame->Data().Length();
440 SetMediaEOS(aMediaType);
444 rawForm = &(headerFrame->Data()[0]);
445 dwChunkId = Read32(rawForm);
446 if (!IsValidBlock(dwChunkId))
448 //Sometimes we dont get next chunk immediately after the Previous chunk(Padding).
449 //we need to search for next valid data chunk ourselves if the chunkId read is not valid
450 if (!ReadNextFrameStartL(aPosition))
452 //no more data frames
453 SetMediaEOS(aMediaType);
456 continue;//found valid chunk. so continue to read the chunk
459 rawForm += 4; //Skip ChunkId
460 aPosition += 4; //Skip ChunkId
461 dwChunkSz = Read32(rawForm);
463 rawForm+=4; //Skip ChunkSize
464 aPosition += 4; //Skip ChunkSIze
468 //We may get chunks of length Zero. So loop again to read the next chunk.
471 if (dwChunkId == KRiffChunkNameList)//list rec
473 if(iMainHeader.iFlags == KAVIF_ISINTERLEAVED)
475 //found REC list. Read the whole list into the SourceBuffer
476 delete iSourceBuffer;
477 iSourceBuffer = NULL;
478 iSourceBuffer = CMMFDescriptorBuffer::NewL(dwChunkSz);
479 iClip.ReadBufferL(iSourceBuffer,aPosition, this);
480 aPosition += dwChunkSz;//skip the list size
488 else if (dwChunkId == KRiffChunkNameJunk)//junk
490 //found Junk chunk. Skip it.
491 aPosition += dwChunkSz;
493 else if ((dwChunkId == KRiffChunkName00db) || (dwChunkId == KRiffChunkName00dc)
494 || (dwChunkId == KRiffChunkName01db) || (dwChunkId == KRiffChunkName01dc)) //video
496 if (aMediaType == KUidMediaTypeVideo)
498 //found video when aMediaType is Video. So read the video chunk into the videobuffer.
501 iVideoBuffer = CMMFDescriptorBuffer::NewL(dwChunkSz);
502 iClip.ReadBufferL(iVideoBuffer,aPosition, this);
503 aPosition += dwChunkSz;
508 //found video when aMediaType is not Video. So Skip it.
509 aPosition += dwChunkSz;
512 else if ((dwChunkId == KRiffChunkName00wb) || (dwChunkId == KRiffChunkName01wb)) //audio
514 if (aMediaType == KUidMediaTypeAudio)
516 //found audio when aMediaType is Audio. So read the audio chunk into the audiobuffer.
519 iAudioBuffer = CMMFDescriptorBuffer::NewL(dwChunkSz);
520 iClip.ReadBufferL(iAudioBuffer,aPosition, this);
521 aPosition += dwChunkSz;
526 //found audio when aMediaType is not audio. So Skip it.
527 aPosition += dwChunkSz;
530 else if (dwChunkId == KRiffChunkNameIdx1)//index block
532 aPosition += dwChunkSz;
533 //Reached index block. This is placed at the end of the data. No more data
534 SetMediaEOS(aMediaType);
538 CleanupStack::PopAndDestroy(headerFrame);
544 Loops through until a valid chunk is identified.
546 @return ETrue if valid chunk is found.
548 TBool CAviReader::ReadNextFrameStartL(TInt& aStartPos)
550 TBool found = EFalse;
553 CMMFDescriptorBuffer* buffer = CMMFDescriptorBuffer::NewL(KReadBufferSize);
554 CleanupStack::PushL(buffer);
555 iClip.ReadBufferL(buffer, aStartPos);
557 TUint8* rawform = &(buffer->Data()[0]);
559 while (count < KReadBufferSize)
561 if (IsValidBlock(Read32(rawform)))
570 CleanupStack::PopAndDestroy(buffer);
575 Identifies a valid audio and video chunk is present
577 @return ETrue if validblock is found else EFalse.
579 TBool CAviReader::IsValidBlock(TUint aChunkId)
583 case KRiffChunkName00wb:
584 case KRiffChunkName01wb:
585 case KRiffChunkName00db:
586 case KRiffChunkName00dc:
587 case KRiffChunkName01db:
588 case KRiffChunkName01dc:
589 case KRiffChunkNameList:
590 case KRiffChunkNameJunk:
591 case KRiffChunkNameIdx1:
599 Fills the buffer with audio/Video data and informs the observer
602 void CAviReader::BufferFilledL(CMMFBuffer* aBuffer)
606 User::Leave(KErrArgument);
608 if (aBuffer == iVideoBuffer)
610 //callback for video read when the file is not interleaved(No REC lists)
611 iBufferFromDevVideo->iData.Copy(iVideoBuffer->Data());
612 iObserver.VideoBufferFilled(iBufferFromDevVideo);
614 else if (aBuffer == iAudioBuffer)
616 //callback for audio read when the file is not interleaved(No REC lists)
617 CMMFDataBuffer* bufferFromSink = static_cast<CMMFDataBuffer*>(iBufferFromDevSound);
619 TInt sinkBufLen = bufferFromSink->Data().MaxSize();
620 TInt audBufLen = iAudioBuffer->Data().Length();
622 if (sinkBufLen < audBufLen)
624 bufferFromSink->Data().Copy(iAudioBuffer->Data().Ptr(), sinkBufLen);
625 CMMFDescriptorBuffer* tempBuffer = CMMFDescriptorBuffer::NewL(audBufLen - sinkBufLen);
626 tempBuffer->Data().Copy(iAudioBuffer->Data().Mid(sinkBufLen));
628 iAudioBuffer = tempBuffer;
632 // DEF113319 - call SetLastBuffer when sending last audio chunk
634 position = (iMainHeader.iFlags == KAVIF_ISINTERLEAVED) ? iSourcePos : iAudioPos;
635 if(!IsAudioDataAvailableL(position))
637 bufferFromSink->SetLastBuffer(ETrue);
638 SetMediaEOS(KUidMediaTypeAudio);
641 bufferFromSink->Data().Copy(iAudioBuffer->Data());
645 iObserver.AudioBufferFilled();
647 else if (aBuffer == iSourceBuffer)//callback for REC list
649 //callback for REC list read. We need to extract video and audio chunks from the sourcebuffer
650 TUint8* rawform = &(iSourceBuffer->Data()[0]);
651 TInt desPos = 0; //position in descriptor
653 //Now we should be pointing to audio or video chunks
654 TInt bufLen = iSourceBuffer->Data().Length();
657 User::Leave(KErrCorrupt);
659 rawform += 4; //skip the fourcc of REC
660 desPos += 4; //byte count corresponding to where rawform points to
662 if (bufLen - desPos < 8)
664 //if the buffer is not long enough to accomodate - chunk id and size leave
665 User::Leave(KErrCorrupt);
668 for (TUint8 i=0; i < iMainHeader.iStreams; i++)//we expect only 2 streams at the moment
670 if (desPos == bufLen) //caution check for the necessity of the block
672 //Sometimes we only have one stream in this list. No more data to read
676 if (bufLen - desPos < 8 && i== 1)
678 //if the buffer is not long enough to accomodate - chunk id and size leave
682 TUint32 dwChunkId = Read32(rawform);
683 rawform += 4; //Skip chunkId
685 TBool bAudioId = EFalse;
686 TBool bVideoId = EFalse;
687 switch (dwChunkId) //identify chunk
689 case KRiffChunkName00db:
690 case KRiffChunkName00dc:
691 case KRiffChunkName01db:
692 case KRiffChunkName01dc:
695 case KRiffChunkName00wb:
696 case KRiffChunkName01wb:
700 User::Leave(KErrCorrupt);
703 if (!bAudioId && !bVideoId)
705 //we are supposed to get audio or video stream here. if anything else, we return KErrCorrupt
706 User::Leave(KErrCorrupt);
708 TUint32 dwChunkSz = Read32(rawform);
709 if (dwChunkSz > bufLen - desPos)
711 User::Leave(KErrCorrupt); //caution - check
713 rawform += 4; //Skip chunkSize
715 TPtr8 temp = iSourceBuffer->Data().MidTPtr(desPos, dwChunkSz);
716 if (bVideoId)// video
718 if (iVideoRequestMade)
720 //if video request is already made we can copy the data directly into the devvideo buffer
721 //instead of iVideoBuffer
722 iBufferFromDevVideo->iData.Copy(temp);
726 //DevVideo request is not made. So copy the data into video buffer
729 iVideoBuffer = CMMFDescriptorBuffer::NewL(dwChunkSz);
730 iVideoBuffer->Data().Copy(temp);
733 else if (bAudioId)//audio
735 if (iAudioRequestMade)
737 //if audio request is already made, copy the data into devsound buffer
738 CMMFDataBuffer* bufferFromSink = static_cast<CMMFDataBuffer*>(iBufferFromDevSound);
739 bufferFromSink->Data().Copy(temp);
743 //DevSound request is not made. copy the audio chunk into audio buffer
746 iAudioBuffer = CMMFDescriptorBuffer::NewL(dwChunkSz);
747 iAudioBuffer->Data().Copy(temp);
750 rawform += dwChunkSz;//Skip video/audio chunk
753 iReadCompleted = ETrue;//REC list is read
754 // we send the bufferfilled callbacks after both audio and video requests are made.
759 User::Leave(KErrCorrupt);
764 Informs audio and video data in rec list is read and the buffer can
765 now be sent for decoding.This function is specific for interleaved files
766 where it is sent for decoding only after both audio and video data is read.
768 void CAviReader::ReadComplete()
770 if ((iAudioRequestMade) && (iVideoRequestMade))
772 //reset back everything for the next cycle
773 iReadRequestMade = EFalse;
774 iReadCompleted = EFalse;
775 iAudioRequestMade = EFalse;
776 iVideoRequestMade = EFalse;
777 iObserver.VideoBufferFilled(iBufferFromDevVideo);
778 iObserver.AudioBufferFilled();
783 Resets the data positions in the file
785 void CAviReader::ResetL()
789 iAudioPos = iSourcePos;
790 iVideoPos = iSourcePos;
791 iReadRequestMade = EFalse;
792 iReadCompleted = EFalse;
793 iAudioRequestMade = EFalse;
794 iVideoRequestMade = EFalse;
799 Identifies if video data in the clip is fully read.
800 @return ETrue if end of videodata
802 TBool CAviReader::IsVideoInputEnd()
808 Identifies if audio data in the clip is fully read.
809 @return ETrue if end of audiodata
811 TBool CAviReader::IsAudioInputEnd()
817 Set the position in the file to play from
818 @param aPosition - this is not used.
819 @leave KErrNotSupported.
821 void CAviReader::SetPositionL(TInt /*aPosition*/)
823 //This will leave KErrNotSuuported as there is no support to
824 //seek the position in an .avi file.
825 User::Leave(KErrNotSupported);
829 Returns if audio is enabled in an .avi file.
832 void CAviReader::AudioEnabled(TBool& aEnabled)
834 aEnabled = iAudioEnabled;
839 Returns the frame rate applied for video
840 @param aFramesPerSecond
842 void CAviReader::FrameRate(TReal32 &aFramesPerSecond)
844 ASSERT(iVideoIdx > KInvalidMediaIdx);
845 if (iStreamHeader[iVideoIdx].iScale == 0)
847 //If this value is 0 consider it as 1 second.
848 iStreamHeader[iVideoIdx].iScale = 1;
850 aFramesPerSecond = iStreamHeader[iVideoIdx].iRate;
854 Returns the sample rate applied for audio.
855 @return audio samplerate
857 TInt CAviReader::SampleRate()
859 ASSERT(iAudioIdx > KInvalidMediaIdx);
860 return iPCMWaveFormat.iWaveFormat.iNSamplesPerSec ;
864 Returns the number of channels set in audio.
865 @return number of audio channels.
867 TInt CAviReader::Channels()
869 ASSERT(iAudioIdx > KInvalidMediaIdx);
870 return iPCMWaveFormat.iWaveFormat.iNChannels;
874 Returns the bits per sample for audio.
875 @return bitspersample
877 TInt CAviReader::BitsPerSample()
879 ASSERT(iAudioIdx > KInvalidMediaIdx);
880 return iPCMWaveFormat.iBitsPerSample;
885 Returns the framesize of video file.
888 void CAviReader::VideoFrameSize(TSize &aFrameSize)
890 ASSERT(iVideoIdx > KInvalidMediaIdx);
891 aFrameSize.iHeight = iMainHeader.iHeight;
892 aFrameSize.iWidth = iMainHeader.iWidth;
896 Returns the Video codec used in the video file
897 @param aMimeType -this is not used
899 void CAviReader::VideoMimeType(TDes8& /*aMimeType*/)
901 //there is no conversion from fcchandler to descriptor
905 Returns the audioCodec used in the video file.
908 void CAviReader::AudioCodec(TFourCC& /*aCodec*/)
910 //there is no conversion from iFccHandler to descriptor
914 Returns the duration of video file.
915 @return Duration of the file in TTimeIntervalMicroSeconds
917 TTimeIntervalMicroSeconds CAviReader::Duration() const
919 ASSERT(iVideoIdx > KInvalidMediaIdx);
920 ASSERT(iStreamHeader[iVideoIdx].iRate);
921 return (iMainHeader.iTotalFrames*1000000)/iStreamHeader[iVideoIdx].iRate;
925 Sets the playwindow for playing audio and video.
929 void CAviReader::SetPlayWindowL(TTimeIntervalMicroSeconds /*aStart*/,TTimeIntervalMicroSeconds /*aEnd*/)
931 //this will leave with KErrNotSupported as there is no
932 //support for seeking the position in the file.
933 User::Leave(KErrNotSupported);
937 Sets the end of audio and video data.
940 void CAviReader::SetMediaEOS(TUid aMediaType)
942 if (aMediaType == KUidMediaTypeAudio) //end of audio
946 else if (aMediaType == KUidMediaTypeVideo)//end of video
950 else //end of REC lists
958 CMMFBuffer* CAviReader::CreateSinkBufferL(TMediaId /*aMediaId*/, TBool&/*aReference*/)
960 User::Leave(KErrNotSupported);
964 void CAviReader::ConstructSinkL( const TDesC8& /*aInitData*/)
966 User::Leave(KErrNotSupported);
969 TFourCC CAviReader::SinkDataTypeCode(TMediaId /*aMediaId*/)
974 void CAviReader::EmptyBufferL(CMMFBuffer* /*aBuffer*/, MDataSource* /*aSupplier*/, TMediaId /*aMediaId*/)
976 User::Leave(KErrNotSupported);
979 TBool CAviReader::CanCreateSinkBuffer()
985 // DEF113319 - added to check last audio chunk
986 Loops through to check whether valid audio chunk is available.
988 @return ETrue if valid audio chunk is found.
990 TBool CAviReader::IsAudioDataAvailableL(TInt aStartPos)
992 TBool foundValidAudioChunk = EFalse;
993 TUint32 dwChunkId = 0;
994 TUint8* rawform = NULL;
996 CMMFDescriptorBuffer* headerFrame = CMMFDescriptorBuffer::NewL(KChunkHeaderSize);
997 CleanupStack::PushL(headerFrame);
1001 iClip.ReadBufferL(headerFrame, aStartPos);
1002 TInt len = headerFrame->Data().Length();
1008 rawform = &(headerFrame->Data()[0]);
1009 dwChunkId = Read32(rawform);
1011 if (!IsValidBlock(dwChunkId))
1013 // No valid chunk id found ...
1014 //Sometimes we dont get next chunk immediately after the Previous chunk(Padding).
1015 //we need to search for next valid data chunk ourselves if the chunkId read is not valid
1016 if (!ReadNextFrameStartL(aStartPos))
1021 continue;//found valid chunk. so continue to read the chunk
1023 if ((dwChunkId == KRiffChunkName00wb) || (dwChunkId == KRiffChunkName01wb)) // check if its valid audio chunk
1025 foundValidAudioChunk = ETrue;
1028 // non audio chunk found, so go and look for next frame header
1029 rawform += 4; //Skip ChunkId
1030 aStartPos += ((Read32(rawform)) + 4 + 4); //Skip: 1. dwChunkSz, 2. ChunkSize(4), 3.ChunkId(4)
1032 CleanupStack::PopAndDestroy(headerFrame);
1033 return foundValidAudioChunk;