00001
00002
00003
00004
00005
00006 #include <e32base.h>
00007 #include <mmf/server/mmfdatabuffer.h>
00008 #include "ivorbiscodec.h"
00009 #include <oggutil.h>
00010 #include <vorbisinfo.h>
00011 #include "VorbisDecoder.h"
00012 #include "../OggVorbisUtil/OggUtilBody.h"
00013 #include <e32debug.h>
00014
00015 const TInt KMaxPcmOutFromPacket = 8000;
00016 const TInt KEndOfStreamBytePos = 5;
00017 const TUint KEndOfStreamFlag = 0x0004;
00018 const TInt KInitDataPage = 3;
00019 _LIT8(KOggS, "OggS");
00020
00021 CVorbisDecoder* CVorbisDecoder::NewL()
00022 {
00023 CVorbisDecoder* self = new(ELeave)CVorbisDecoder;
00024 CleanupStack::PushL(self);
00025 self->ConstructL();
00026 CleanupStack::Pop(self);
00027 return self;
00028 }
00029
00030 CVorbisDecoder::CVorbisDecoder()
00031 {
00032 }
00033
00034 void CVorbisDecoder::ConstructL()
00035 {
00036 vorbis_info_init(&iInfo);
00037 vorbis_comment_init(&iComment);
00038
00039 iSyncState = ogg_sync_create();
00040
00041
00042
00043 iStreamState = ogg_stream_create(-1);
00044 }
00045
00046 CVorbisDecoder::~CVorbisDecoder()
00047 {
00048 if (iState==EReady)
00049 {
00050 vorbis_block_clear(&iBlock);
00051 vorbis_dsp_clear(&iDspState);
00052 }
00053 vorbis_comment_clear(&iComment);
00054 vorbis_info_clear(&iInfo);
00055 ogg_packet_release(&iPacket);
00056 ogg_page_release(&iPage);
00057 ogg_sync_destroy(iSyncState);
00058 ogg_stream_destroy(iStreamState);
00059 }
00060
00071 void CVorbisDecoder::PacketInL(ogg_packet aPacket)
00072 {
00073 if (iState == EBadStream)
00074 {
00075 User::Leave(KErrCorrupt);
00076 }
00077 else if (iState == ENotVorbis)
00078 {
00079 User::Leave(KErrNotSupported);
00080 }
00081 iPacket = aPacket;
00082 if (iState == EInitializing)
00083 {
00084 TInt res = vorbis_synthesis_headerin(&iInfo, &iComment, &iPacket);
00085 if (res < KErrNone)
00086 {
00087 if (res == OV_ENOTVORBIS)
00088 {
00089 iState = ENotVorbis;
00090 User::Leave(KErrNotSupported);
00091 }
00092 else
00093 {
00094 iState = EBadStream;
00095 User::Leave(KErrCorrupt);
00096 }
00097 }
00098 ++iPacketCount;
00099
00100 if (iPacketCount == 3)
00101 {
00102 vorbis_synthesis_init(&iDspState, &iInfo);
00103 vorbis_block_init(&iDspState, &iBlock);
00104 iState = EReady;
00105 }
00106 }
00107 else if (iState == EReady)
00108 {
00109 TInt res = vorbis_synthesis(&iBlock, &iPacket, 1);
00110 if (res == KErrNone)
00111 {
00112 vorbis_synthesis_blockin(&iDspState, &iBlock);
00113 }
00114 else
00115 {
00116 User::Leave(KErrCorrupt);
00117 }
00118 }
00119 else
00120 {
00121 User::Leave(KErrGeneral);
00122 }
00123 }
00124
00135 void CVorbisDecoder::PcmOutL(TDes8& aBuf)
00136 {
00137 if (iState == ENotVorbis)
00138 {
00139 User::Leave(KErrNotSupported);
00140 }
00141 else if (iState == EBadStream)
00142 {
00143 User::Leave(KErrCorrupt);
00144 }
00145 else if (iState == EInitializing)
00146 {
00147 aBuf.SetLength(0);
00148 }
00149 else if (iState == EReady)
00150 {
00151 TInt** pcm;
00152 TInt samples = vorbis_synthesis_pcmout(&iDspState, &pcm);
00153 while ( samples > 0)
00154 {
00155 TInt bytesPerSample = 2*iInfo.channels;
00156 if (bytesPerSample == 0)
00157 {
00158 User::Leave(KErrCorrupt);
00159 }
00160 TInt data = aBuf.Length();
00161 TInt newLength = 0;
00162 if ( data == 0)
00163 {
00164 newLength = aBuf.MaxLength();
00165 }
00166 else
00167 {
00168 newLength = aBuf.MaxLength() - data;
00169 }
00170 TInt bufSamples = newLength/bytesPerSample;
00171 TInt toConv = (samples>bufSamples) ? bufSamples : samples;
00172 TInt length = data + (toConv*bytesPerSample);
00173 if(length <= aBuf.MaxLength())
00174 {
00175 aBuf.SetLength(length);
00176 }
00177 else
00178 {
00179 User::Leave(KErrOverflow);
00180 }
00181 TInt16* bufptr = reinterpret_cast<TInt16*>(&aBuf[data + 0]);
00182
00183 for (TInt c=0; c<iInfo.channels; ++c)
00184 {
00185 TInt* mono = pcm[c];
00186 TInt16* dest = &bufptr[c];
00187 for (TInt i=0; i<toConv; i++)
00188 {
00189 TInt s = mono[i]>>9;
00190
00191
00192 if (s>KMaxTInt16)
00193 {
00194 s = KMaxTInt16;
00195 }
00196 else if (s<KMinTInt16)
00197 {
00198 s = KMinTInt16;
00199 }
00200 dest[i*iInfo.channels] = s;
00201 }
00202 }
00203 vorbis_synthesis_read(&iDspState, toConv);
00204 samples = vorbis_synthesis_pcmout(&iDspState, &pcm);
00205 }
00206 }
00207 else
00208 {
00209 User::Leave(KErrGeneral);
00210 }
00211 }
00212
00213 void CVorbisDecoder::Reset()
00214 {
00215 if (iState==EReady)
00216 {
00217 vorbis_block_clear(&iBlock);
00218 vorbis_dsp_clear(&iDspState);
00219 }
00220 vorbis_comment_clear(&iComment);
00221 vorbis_info_clear(&iInfo);
00222 vorbis_info_init(&iInfo);
00223 vorbis_comment_init(&iComment);
00224 iPacketCount = 0;
00225 iPageNumber = 0;
00226 iState = EInitializing;
00227 }
00239 void CVorbisDecoder::DecoderL(const CMMFDataBuffer& aBuf, TDes8& aDstBuf)
00240 {
00241 CMMFDataBuffer& srcBuf = const_cast<CMMFDataBuffer&>(aBuf);
00242 if(srcBuf.Status()!= EUnAvailable)
00243 {
00244 unsigned char* buf = ogg_sync_bufferin(iSyncState, aBuf.BufferSize());
00245 TPtr8 bufPtr(buf, 0, aBuf.BufferSize());
00246 bufPtr.Copy(aBuf.Data());
00247 ogg_sync_wrote(iSyncState, aBuf.BufferSize());
00248 if(iPageNumber > KInitDataPage && IsLastPage(srcBuf))
00249 {
00250 srcBuf.SetStatus(EUnAvailable);
00251 }
00252 }
00253 TInt res = 0;
00254 while(ETrue)
00255 {
00256 res = ogg_stream_packetout(iStreamState, &iPacket);
00257 if (res > 0)
00258 {
00259 PacketInL(iPacket);
00260 if(iState != EInitializing)
00261 {
00262 PcmOutL(aDstBuf);
00263
00264
00265 if (aDstBuf.MaxLength() - aDstBuf.Length() < KMaxPcmOutFromPacket)
00266 {
00267 break;
00268 }
00269 }
00270 }
00271 else if(res == 0)
00272 {
00273
00274 TInt length = ogg_sync_pageseek(iSyncState, &iPage);
00275 if ( length < 0 )
00276 {
00277 continue;
00278 }
00279 else if ( length > 0 )
00280 {
00281 if(iPageNumber == 0)
00282 {
00283 ogg_stream_reset_serialno(iStreamState, ogg_page_serialno(&iPage));
00284 }
00285 ++iPageNumber;
00286
00287 ogg_stream_pagein(iStreamState, &iPage);
00288 }
00289 else
00290 {
00291 break;
00292 }
00293 }
00294 }
00295 }
00296
00297 TBool CVorbisDecoder::IsLastPage(CMMFDataBuffer& aSrcBuf)
00298 {
00299 if(iPageNumber > KInitDataPage)
00300 {
00301 TInt pos = aSrcBuf.Data().Find(KOggS);
00302 if(pos != KErrNotFound)
00303 {
00304 if(pos + KEndOfStreamBytePos < aSrcBuf.BufferSize())
00305 {
00306 TInt flag = aSrcBuf.Data()[pos + KEndOfStreamBytePos] & KEndOfStreamFlag;
00307 if(flag)
00308 {
00309 return ETrue;
00310 }
00311 }
00312 }
00313 }
00314 return EFalse;
00315 }
00316
00317
00318
00319
00320 CVorbisDecoderProcessor* CVorbisDecoderProcessor::NewL()
00321 {
00322 CVorbisDecoderProcessor* self = new(ELeave)CVorbisDecoderProcessor;
00323 CleanupStack::PushL(self);
00324 self->ConstructL();
00325 CleanupStack::Pop(self);
00326 return self;
00327 }
00328
00329 CVorbisDecoderProcessor::CVorbisDecoderProcessor()
00330 {
00331 }
00332
00333 void CVorbisDecoderProcessor::ConstructL()
00334 {
00335 #ifdef SYMBIAN_SEP_HEAP
00336 User::LeaveIfError(iVorbisChunk.CreateLocal(KInitialChunkSize, KMaxChunkSize, EOwnerThread));
00337 iVorbisHeap = User::ChunkHeap(iVorbisChunk, KMinHeapLength);
00338 iDefaultHeap = &User::Heap();
00339 #endif
00340 VORBIS_TRAPD(leaveErr, iDecoder = CVorbisDecoder::NewL());
00341 User::LeaveIfError(leaveErr);
00342 }
00343
00344 CVorbisDecoderProcessor::~CVorbisDecoderProcessor()
00345 {
00346 #ifdef SYMBIAN_SEP_HEAP
00347 if(iVorbisHeap)
00348 {
00349 User::SwitchHeap(iVorbisHeap);
00350 }
00351 #endif
00352 delete iDecoder;
00353 #ifdef SYMBIAN_SEP_HEAP
00354 if(iVorbisHeap)
00355 {
00356 iVorbisChunk.Close();
00357 User::SwitchHeap(iDefaultHeap);
00358 }
00359 #endif
00360 }
00361
00379 void CVorbisDecoderProcessor::ProcessL(const CMMFBuffer& aSource,
00380 CMMFBuffer& aDst,
00381 TProcessResult& aRes,
00382 TUint& aSourceUsed,
00383 TUint& aDestWritten)
00384 {
00385
00386 if (!CMMFBuffer::IsSupportedDataBuffer(aSource.Type()))
00387 {
00388 User::Leave(KErrNotSupported);
00389 }
00390 if (!CMMFBuffer::IsSupportedDataBuffer(aDst.Type()))
00391 {
00392 User::Leave(KErrNotSupported);
00393 }
00394 const CMMFDataBuffer& src = static_cast<const CMMFDataBuffer&>(aSource);
00395 if((src.LastBuffer()) && (src.Data().Length() == 0 ))
00396 {
00397
00398 aDestWritten = 0;
00399 aSourceUsed = 0;
00400 aRes = EComplete;
00401 return;
00402 }
00403 CMMFDataBuffer& dstBuf = static_cast<CMMFDataBuffer&>(aDst);
00404 if ((aSource.FrameNumber()<2) && (aSource.FrameNumber()<iLastFrame))
00405 {
00406 #ifdef SYMBIAN_SEP_HEAP
00407 User::SwitchHeap(iVorbisHeap);
00408 #endif
00409 iDecoder->Reset();
00410 #ifdef SYMBIAN_SEP_HEAP
00411 iVorbisChunk.Close();
00412 #endif
00413 }
00414 dstBuf.Data().SetLength(0);
00415
00416 VORBIS_TRAPD(leaveErr, iDecoder->DecoderL(src,dstBuf.Data()));
00417 User::LeaveIfError(leaveErr);
00418 aDestWritten = dstBuf.Data().Length();
00419 dstBuf.Data().SetLength(dstBuf.Data().Length());
00420 aSourceUsed = src.Data().Length()-aSource.Position();
00421 aRes = ( aDestWritten==0) ? EDestNotFilled : EComplete ;
00422 iLastFrame = aSource.FrameNumber();
00423 if( aDestWritten==0 && src.LastBuffer() )
00424 {
00425 #ifdef SYMBIAN_SEP_HEAP
00426 RHeap* oldHeap = User::SwitchHeap(iVorbisHeap);
00427 #endif
00428 iDecoder->Reset();
00429 #ifdef SYMBIAN_SEP_HEAP
00430 User::SwitchHeap(oldHeap);
00431 #endif
00432 }
00433 }
00434