00001
00002
00003
00004
00005
00006 #include <e32base.h>
00007 #include <e32debug.h>
00008 #include <e32math.h>
00009 #include "VorbisEncoder.h"
00010
00011 const TInt KDefaultBitRate = 64000;
00012 const TInt KDefaultQuality = 0.0;
00013
00014
00015
00016
00017
00018 CVorbisEncoder* CVorbisEncoder::NewL()
00019 {
00020 CVorbisEncoder* self = new(ELeave)CVorbisEncoder;
00021 CleanupStack::PushL(self);
00022 self->ConstructL();
00023 CleanupStack::Pop(self);
00024 return self;
00025 }
00026
00027 CVorbisEncoder::CVorbisEncoder(): iState(ENotReady), iBitRate(KDefaultBitRate), iQuality(KDefaultQuality)
00028 {
00029 }
00030
00031 void CVorbisEncoder::ConstructL()
00032 {
00033 vorbis_info_init(&iInfo);
00034 ogg_stream_init(&iStream,10);
00035 }
00036
00037 CVorbisEncoder::~CVorbisEncoder()
00038 {
00039 if (iState != ENotReady)
00040 {
00041 vorbis_block_clear(&iBlock);
00042 vorbis_dsp_clear(&iDspState);
00043 }
00044 ogg_stream_clear(&iStream);
00045 vorbis_comment_clear(&iComment);
00046 vorbis_info_clear(&iInfo);
00047 }
00048
00056 void CVorbisEncoder::PcmInL(const CMMFDataBuffer& aBuf)
00057 {
00058 TPtrC8 data = aBuf.Data();
00059 TInt bytes = data.Length();
00060 TInt ret = KErrNone;
00061 if (iState == ENotReady)
00062 {
00063 User::Leave(KErrNotReady);
00064 }
00065
00066 iLastBuffer = aBuf.LastBuffer();
00067
00068 if(bytes==0)
00069 {
00070 ret = vorbis_analysis_wrote(&iDspState,0);
00071 DEBUG1("Called vorbis_analysis_wrote zero bytes = %d",bytes);
00072 if (ret != KErrNone)
00073 {
00074 User::Leave(TranslateOggVorbisError(ret));
00075 }
00076 }
00077 else
00078 {
00079 TReal32** buffer;
00080 TInt bytesPerSample = 2*iInfo.channels;
00081 TInt bufSamples = bytes/bytesPerSample;
00082 buffer = vorbis_analysis_buffer(&iDspState,bufSamples);
00083 TInt i = 0;
00084 if(iInfo.channels == 1)
00085 {
00086 for(i = 0 ; i < bufSamples ; i++)
00087 {
00088 buffer[0][i]=((static_cast<TInt8>(data[i*2+1])<<8)|(0x00ff&static_cast<TInt16>(data[i*2])))/32768.f;
00089 }
00090 }
00091 else
00092 {
00093 for(i=0;i<bufSamples;i++)
00094 {
00095
00096 buffer[0][i]=((static_cast<TInt8>(data[i*4+1])<<8)|(0x00ff&static_cast<TInt16>(data[i*4])))/32768.f;
00097 buffer[1][i]=((static_cast<TInt8>(data[i*4+3])<<8)|(0x00ff&static_cast<TInt16>(data[i*4+2])))/32768.f;
00098 }
00099 }
00100
00101 ret = vorbis_analysis_wrote(&iDspState,i);
00102 if (ret != KErrNone)
00103 {
00104 User::Leave(TranslateOggVorbisError(ret));
00105 }
00106 DEBUG1("Called vorbis_analysis_wrote with vals = %d",i);
00107 }
00108 }
00109
00120 TInt CVorbisEncoder::PageOutL(CMMFDataBuffer& aDst)
00121 {
00122 TDes8* dst = &aDst.Data();
00123 dst->SetLength(0);
00124 ogg_packet op;
00125 ogg_page og;
00126 TInt pageCount = 0;
00127 if(iState == EInitialized)
00128 {
00129 while(ogg_stream_flush(&iStream,&og))
00130 {
00131 dst->Append(og.header, og.header_len);
00132 dst->Append(og.body, og.body_len);
00133 DEBUG1("HeaderPageLength %d",og.header_len + og.body_len);
00134 iState = EReady;
00135 }
00136 }
00137 DEBUG("about to call vorbis_analysis_blockout");
00138 if(iLastBuffer)
00139 {
00140 while (vorbis_analysis_blockout(&iDspState,&iBlock) == 1)
00141 {
00142 vorbis_analysis(&iBlock,NULL);
00143 vorbis_bitrate_addblock(&iBlock);
00144
00145 while (vorbis_bitrate_flushpacket(&iDspState,&op))
00146 {
00147 ogg_stream_packetin(&iStream,&op);
00148 }
00149 }
00150 while(ogg_stream_flush(&iStream,&og))
00151 {
00152 dst->Append(og.header, og.header_len);
00153 dst->Append(og.body, og.body_len);
00154 DEBUG("Last Buffer flag is set");
00155 DEBUG1("PageLength %d",og.header_len + og.body_len);
00156 DEBUG1("PageCount %d",++iPageCount);
00157 }
00158 aDst.SetLastBuffer(ETrue);
00159 }
00160 else
00161 {
00162 while (vorbis_analysis_blockout(&iDspState,&iBlock) == 1)
00163 {
00164
00165 DEBUG("called vorbis_analysis_blockout with return of 1");
00166 vorbis_analysis(&iBlock,NULL);
00167 vorbis_bitrate_addblock(&iBlock);
00168 DEBUG1("called packet vorbis_bitrate_flushpacket",(*dst).Length());
00169 while (vorbis_bitrate_flushpacket(&iDspState,&op))
00170 {
00171 ogg_stream_packetin(&iStream,&op);
00172 DEBUG1("CVorbisEncoder::PacketOut packet of length %d added to cache",op.bytes);
00173 while(ogg_stream_pageout(&iStream, &og))
00174 {
00175 dst->Append(og.header, og.header_len);
00176 dst->Append(og.body, og.body_len);
00177
00178 DEBUG1("PageLength %d",og.header_len + og.body_len);
00179 DEBUG1("PageCount %d",++iPageCount);
00180 pageCount++;
00181 if(ogg_page_eos(&og))
00182 {
00183 aDst.SetLastBuffer(ETrue);
00184 DEBUG1("LastPageLength %d",og.header_len + og.body_len);
00185 return dst->Length();
00186 }
00187 }
00188 }
00189 }
00190 }
00191 return dst->Length();
00192 }
00193
00197 void CVorbisEncoder::PrepareHeadersL()
00198 {
00199 ogg_packet op1,op2,op3;
00200 TInt ret = KErrNone;
00201 ret = vorbis_analysis_headerout(&iDspState,&iComment,&op1,&op2,&op3);
00202 if (ret != KErrNone)
00203 {
00204 User::Leave(TranslateOggVorbisError(ret));
00205 }
00206 ogg_stream_packetin(&iStream,&op1);
00207 ogg_stream_packetin(&iStream,&op2);
00208 ogg_stream_packetin(&iStream,&op3);
00209 }
00210
00211 void CVorbisEncoder::Reset()
00212 {
00213 if (iState==EReady)
00214 {
00215 vorbis_block_clear(&iBlock);
00216 vorbis_dsp_clear(&iDspState);
00217 }
00218 vorbis_comment_clear(&iComment);
00219 vorbis_info_clear(&iInfo);
00220 vorbis_info_init(&iInfo);
00221 vorbis_comment_init(&iComment);
00222 iLastBuffer = EFalse;
00223 iState = ENotReady;
00224 }
00225
00226 TInt CVorbisEncoder::BitRateL()
00227 {
00228 return iBitRate;
00229 }
00230
00231 void CVorbisEncoder::SetBitRateL(TInt aBitRate)
00232 {
00233 if (aBitRate < KOggVorbisMinBitrate)
00234 {
00235 aBitRate = KOggVorbisMinBitrate;
00236 }
00237 iBitRate = aBitRate;
00238 ConvertBitRateToQuality(iBitRate, iQuality);
00239 }
00246 void CVorbisEncoder::InitializeVorbisStreamL()
00247 {
00248 TInt ret = KErrNone;
00249 ret = vorbis_encode_init_vbr(&iInfo,iChannels,iSampleRate,iQuality);
00250 if(ret == KErrNone)
00251 {
00252 vorbis_comment_init(&iComment);
00253
00254 vorbis_comment_add_tag(&iComment,"ENCODER","Reference Vorbis Encoder");
00255 vorbis_analysis_init(&iDspState,&iInfo);
00256 vorbis_block_init(&iDspState,&iBlock);
00257 PrepareHeadersL();
00258 iState = EInitialized;
00259 }
00260 if(ret)
00261 {
00262 User::Leave(TranslateOggVorbisError(ret));
00263 }
00264 }
00270 void CVorbisEncoder::ConfigureL(TInt aSampleRate, TInt aChannels)
00271 {
00272 iSampleRate = aSampleRate;
00273 iChannels = aChannels;
00274 InitializeVorbisStreamL();
00275 }
00276
00277 TInt CVorbisEncoder::TranslateOggVorbisError(TInt aError)
00278 {
00279
00280 switch (aError)
00281 {
00282 case OV_EIMPL:
00283 return KErrNotSupported;
00284 case OV_EINVAL:
00285 return KErrArgument;
00286 default:
00287 return KErrUnknown;
00288 }
00289 }
00290
00299 void CVorbisEncoder::ConvertBitRateToQuality(TInt aBitRate, TReal32& aQuality)
00300 {
00301 switch (aBitRate)
00302 {
00303 case KVorbisQuality0:
00304 aQuality = 0.0;
00305 break;
00306 case KVorbisQuality1:
00307 aQuality = 0.1;
00308 break;
00309 case KVorbisQuality2:
00310 aQuality = 0.2;
00311 break;
00312 case KVorbisQuality3:
00313 aQuality = 0.3;
00314 break;
00315 case KVorbisQuality4:
00316 aQuality = 0.4;
00317 break;
00318 case KVorbisQuality5:
00319 aQuality = 0.5;
00320 break;
00321 case KVorbisQuality6:
00322 aQuality = 0.6;
00323 break;
00324 case KVorbisQuality7:
00325 aQuality = 0.7;
00326 break;
00327 case KVorbisQuality8:
00328 aQuality = 0.8;
00329 break;
00330 case KVorbisQuality9:
00331 aQuality = 0.9;
00332 break;
00333 case KVorbisQuality10:
00334 aQuality = 1.0;
00335 break;
00336 default:
00337 aQuality = -0.1;
00338 break;
00339 }
00340 }
00341
00342
00343
00344
00345 CVorbisProcessor* CVorbisProcessor::NewL()
00346 {
00347 CVorbisProcessor* self = new(ELeave)CVorbisProcessor;
00348 CleanupStack::PushL(self);
00349 self->ConstructL();
00350 CleanupStack::Pop(self);
00351 return self;
00352 }
00353
00354 CVorbisProcessor::CVorbisProcessor()
00355 {
00356 }
00357
00358 void CVorbisProcessor::ConstructL()
00359 {
00360 #ifdef SYMBIAN_SEP_HEAP
00361 User::LeaveIfError(iVorbisChunk.CreateLocal(KInitialChunkSize, KMaxChunkSize, EOwnerThread));
00362 iVorbisHeap = User::ChunkHeap(iVorbisChunk, KMinHeapLength);
00363 iDefaultHeap = &User::Heap();
00364 #endif
00365 VORBIS_TRAPD(leaveErr, iEncoder = CVorbisEncoder::NewL());
00366 User::LeaveIfError(leaveErr);
00367 }
00368
00369 CVorbisProcessor::~CVorbisProcessor()
00370 {
00371 #ifdef SYMBIAN_SEP_HEAP
00372 if(iVorbisHeap)
00373 {
00374 User::SwitchHeap(iVorbisHeap);
00375 }
00376 #endif
00377 delete iEncoder;
00378 #ifdef SYMBIAN_SEP_HEAP
00379 if(iVorbisHeap)
00380 {
00381 iVorbisChunk.Close();
00382 User::SwitchHeap(iDefaultHeap);
00383 }
00384 #endif
00385 }
00386
00387 void CVorbisProcessor::ProcessL(const CMMFBuffer& aSource,
00388 CMMFBuffer& aDst,
00389 TProcessResult& aRes,
00390 TUint& aSourceUsed,
00391 TUint& aDestWritten)
00392 {
00393
00394 if (!CMMFBuffer::IsSupportedDataBuffer(aSource.Type()))
00395 {
00396 User::Leave(KErrNotSupported);
00397 }
00398 if (!CMMFBuffer::IsSupportedDataBuffer(aDst.Type()))
00399 {
00400 User::Leave(KErrNotSupported);
00401 }
00402 const CMMFDataBuffer& src = static_cast<const CMMFDataBuffer&>(aSource);
00403 CMMFDataBuffer& dstBuf = static_cast<CMMFDataBuffer&>(aDst);
00404 VORBIS_TRAPD(leaveErr, iEncoder->PcmInL(src));
00405 User::LeaveIfError(leaveErr);
00406 VORBIS_TRAP(leaveErr, iEncoder->PageOutL(dstBuf));
00407 User::LeaveIfError(leaveErr);
00408 aDestWritten = dstBuf.Data().Length();
00409 aSourceUsed = src.Data().Length();
00410 aRes = ( aDestWritten > 0 ? EComplete : EDestNotFilled);
00411 }
00412
00413 TInt CVorbisProcessor::BitRateL()
00414 {
00415 return iEncoder->BitRateL();
00416 }
00417
00418 void CVorbisProcessor::SetBitRateL(TInt aBitRate)
00419 {
00420 iEncoder->SetBitRateL(aBitRate);
00421 }
00422
00423 void CVorbisProcessor::ConfigureL(TInt aSampleRate, TInt aChannels)
00424 {
00425 VORBIS_TRAPD(leaveErr, iEncoder->ConfigureL(aSampleRate, aChannels));
00426 User::LeaveIfError(leaveErr);
00427 }