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 if(bytes==0)
00066 {
00067 ret = vorbis_analysis_wrote(&iDspState,0);
00068 DEBUG1("Called vorbis_analysis_wrote zero bytes = %d",bytes);
00069 if (ret != KErrNone)
00070 {
00071 User::Leave(TranslateOggVorbisError(ret));
00072 }
00073 }
00074 else
00075 {
00076 TReal32** buffer;
00077 TInt bytesPerSample = 2*iInfo.channels;
00078 TInt bufSamples = bytes/bytesPerSample;
00079 buffer = vorbis_analysis_buffer(&iDspState,bufSamples);
00080 TInt i = 0;
00081 if(iInfo.channels == 1)
00082 {
00083 for(i = 0 ; i < bufSamples ; i++)
00084 {
00085 buffer[0][i]=((static_cast<TInt8>(data[i*2+1])<<8)|(0x00ff&static_cast<TInt16>(data[i*2])))/32768.f;
00086 }
00087 }
00088 else
00089 {
00090 for(i=0;i<bufSamples;i++)
00091 {
00092
00093 buffer[0][i]=((static_cast<TInt8>(data[i*4+1])<<8)|(0x00ff&static_cast<TInt16>(data[i*4])))/32768.f;
00094 buffer[1][i]=((static_cast<TInt8>(data[i*4+3])<<8)|(0x00ff&static_cast<TInt16>(data[i*4+2])))/32768.f;
00095 }
00096 }
00097
00098 ret = vorbis_analysis_wrote(&iDspState,i);
00099 if (ret != KErrNone)
00100 {
00101 User::Leave(TranslateOggVorbisError(ret));
00102 }
00103 DEBUG1("Called vorbis_analysis_wrote with vals = %d",i);
00104 }
00105 }
00106
00117 TInt CVorbisEncoder::PageOutL(CMMFDataBuffer& aDst)
00118 {
00119 TDes8* dst = &aDst.Data();
00120 dst->SetLength(0);
00121 ogg_packet op;
00122 ogg_page og;
00123 TInt pageCount = 0;
00124 if(iState == EInitialized)
00125 {
00126 while(ogg_stream_flush(&iStream,&og))
00127 {
00128 dst->Append(og.header, og.header_len);
00129 dst->Append(og.body, og.body_len);
00130 DEBUG1("HeaderPageLength %d",og.header_len + og.body_len);
00131 iState = EReady;
00132 }
00133 }
00134 DEBUG("about to call vorbis_analysis_blockout");
00135 while (vorbis_analysis_blockout(&iDspState,&iBlock) == 1)
00136 {
00137
00138 DEBUG("called vorbis_analysis_blockout with return of 1");
00139 vorbis_analysis(&iBlock,NULL);
00140 vorbis_bitrate_addblock(&iBlock);
00141 DEBUG1("called packet vorbis_bitrate_flushpacket",(*dst).Length());
00142 while (vorbis_bitrate_flushpacket(&iDspState,&op))
00143 {
00144 ogg_stream_packetin(&iStream,&op);
00145 DEBUG1("CVorbisEncoder::PacketOut packet of length %d added to cache",op.bytes);
00146 while(ogg_stream_pageout(&iStream, &og))
00147 {
00148 dst->Append(og.header, og.header_len);
00149 dst->Append(og.body, og.body_len);
00150
00151 DEBUG1("PageLength %d",og.header_len + og.body_len);
00152 DEBUG1("PageCount %d",++iPageCount);
00153 pageCount++;
00154 if(ogg_page_eos(&og))
00155 {
00156 aDst.SetLastBuffer(ETrue);
00157 DEBUG1("LastPageLength %d",og.header_len + og.body_len);
00158 return dst->Length();
00159 }
00160 }
00161 }
00162 }
00163 return dst->Length();
00164 }
00165
00169 void CVorbisEncoder::PrepareHeadersL()
00170 {
00171 ogg_packet op1,op2,op3;
00172 TInt ret = KErrNone;
00173 ret = vorbis_analysis_headerout(&iDspState,&iComment,&op1,&op2,&op3);
00174 if (ret != KErrNone)
00175 {
00176 User::Leave(TranslateOggVorbisError(ret));
00177 }
00178 ogg_stream_packetin(&iStream,&op1);
00179 ogg_stream_packetin(&iStream,&op2);
00180 ogg_stream_packetin(&iStream,&op3);
00181 }
00182
00183 void CVorbisEncoder::Reset()
00184 {
00185 if (iState==EReady)
00186 {
00187 vorbis_block_clear(&iBlock);
00188 vorbis_dsp_clear(&iDspState);
00189 }
00190 vorbis_comment_clear(&iComment);
00191 vorbis_info_clear(&iInfo);
00192 vorbis_info_init(&iInfo);
00193 vorbis_comment_init(&iComment);
00194 iState = ENotReady;
00195 }
00196
00197 TInt CVorbisEncoder::BitRateL()
00198 {
00199 return iBitRate;
00200 }
00201
00202 void CVorbisEncoder::SetBitRateL(TInt aBitRate)
00203 {
00204 if (aBitRate < KOggVorbisMinBitrate)
00205 {
00206 aBitRate = KOggVorbisMinBitrate;
00207 }
00208 iBitRate = aBitRate;
00209 ConvertBitRateToQuality(iBitRate, iQuality);
00210 }
00217 void CVorbisEncoder::InitializeVorbisStreamL()
00218 {
00219 TInt ret = KErrNone;
00220 ret = vorbis_encode_init_vbr(&iInfo,iChannels,iSampleRate,iQuality);
00221 if(ret == KErrNone)
00222 {
00223 vorbis_comment_init(&iComment);
00224
00225 vorbis_comment_add_tag(&iComment,"ENCODER","Reference Vorbis Encoder");
00226 vorbis_analysis_init(&iDspState,&iInfo);
00227 vorbis_block_init(&iDspState,&iBlock);
00228 PrepareHeadersL();
00229 iState = EInitialized;
00230 }
00231 if(ret)
00232 {
00233 User::Leave(TranslateOggVorbisError(ret));
00234 }
00235 }
00241 void CVorbisEncoder::ConfigureL(TInt aSampleRate, TInt aChannels)
00242 {
00243 iSampleRate = aSampleRate;
00244 iChannels = aChannels;
00245 InitializeVorbisStreamL();
00246 }
00247
00248 TInt CVorbisEncoder::TranslateOggVorbisError(TInt aError)
00249 {
00250
00251 switch (aError)
00252 {
00253 case OV_EIMPL:
00254 return KErrNotSupported;
00255 case OV_EINVAL:
00256 return KErrArgument;
00257 default:
00258 return KErrUnknown;
00259 }
00260 }
00261
00270 void CVorbisEncoder::ConvertBitRateToQuality(TInt aBitRate, TReal32& aQuality)
00271 {
00272 switch (aBitRate)
00273 {
00274 case KVorbisQuality0:
00275 aQuality = 0.0;
00276 break;
00277 case KVorbisQuality1:
00278 aQuality = 0.1;
00279 break;
00280 case KVorbisQuality2:
00281 aQuality = 0.2;
00282 break;
00283 case KVorbisQuality3:
00284 aQuality = 0.3;
00285 break;
00286 case KVorbisQuality4:
00287 aQuality = 0.4;
00288 break;
00289 case KVorbisQuality5:
00290 aQuality = 0.5;
00291 break;
00292 case KVorbisQuality6:
00293 aQuality = 0.6;
00294 break;
00295 case KVorbisQuality7:
00296 aQuality = 0.7;
00297 break;
00298 case KVorbisQuality8:
00299 aQuality = 0.8;
00300 break;
00301 case KVorbisQuality9:
00302 aQuality = 0.9;
00303 break;
00304 case KVorbisQuality10:
00305 aQuality = 1.0;
00306 break;
00307 default:
00308 aQuality = -0.1;
00309 break;
00310 }
00311 }
00312
00313
00314
00315
00316 CVorbisProcessor* CVorbisProcessor::NewL()
00317 {
00318 CVorbisProcessor* self = new(ELeave)CVorbisProcessor;
00319 CleanupStack::PushL(self);
00320 self->ConstructL();
00321 CleanupStack::Pop(self);
00322 return self;
00323 }
00324
00325 CVorbisProcessor::CVorbisProcessor()
00326 {
00327 }
00328
00329 void CVorbisProcessor::ConstructL()
00330 {
00331 #ifdef SYMBIAN_SEP_HEAP
00332 User::LeaveIfError(iVorbisChunk.CreateLocal(KInitialChunkSize, KMaxChunkSize, EOwnerThread));
00333 iVorbisHeap = User::ChunkHeap(iVorbisChunk, KMinHeapLength);
00334 iDefaultHeap = &User::Heap();
00335 #endif
00336 VORBIS_TRAPD(leaveErr, iEncoder = CVorbisEncoder::NewL());
00337 User::LeaveIfError(leaveErr);
00338 }
00339
00340 CVorbisProcessor::~CVorbisProcessor()
00341 {
00342 #ifdef SYMBIAN_SEP_HEAP
00343 if(iVorbisHeap)
00344 {
00345 User::SwitchHeap(iVorbisHeap);
00346 }
00347 #endif
00348 delete iEncoder;
00349 #ifdef SYMBIAN_SEP_HEAP
00350 if(iVorbisHeap)
00351 {
00352 iVorbisChunk.Close();
00353 User::SwitchHeap(iDefaultHeap);
00354 }
00355 #endif
00356 }
00357
00358 void CVorbisProcessor::ProcessL(const CMMFBuffer& aSource,
00359 CMMFBuffer& aDst,
00360 TProcessResult& aRes,
00361 TUint& aSourceUsed,
00362 TUint& aDestWritten)
00363 {
00364
00365 if (!CMMFBuffer::IsSupportedDataBuffer(aSource.Type()))
00366 {
00367 User::Leave(KErrNotSupported);
00368 }
00369 if (!CMMFBuffer::IsSupportedDataBuffer(aDst.Type()))
00370 {
00371 User::Leave(KErrNotSupported);
00372 }
00373 const CMMFDataBuffer& src = static_cast<const CMMFDataBuffer&>(aSource);
00374 CMMFDataBuffer& dstBuf = static_cast<CMMFDataBuffer&>(aDst);
00375 VORBIS_TRAPD(leaveErr, iEncoder->PcmInL(src));
00376 User::LeaveIfError(leaveErr);
00377 VORBIS_TRAP(leaveErr, iEncoder->PageOutL(dstBuf));
00378 User::LeaveIfError(leaveErr);
00379 aDestWritten = dstBuf.Data().Length();
00380 aSourceUsed = src.Data().Length();
00381 aRes = ( aDestWritten > 0 ? EComplete : EDestNotFilled);
00382 }
00383
00384 TInt CVorbisProcessor::BitRateL()
00385 {
00386 return iEncoder->BitRateL();
00387 }
00388
00389 void CVorbisProcessor::SetBitRateL(TInt aBitRate)
00390 {
00391 iEncoder->SetBitRateL(aBitRate);
00392 }
00393
00394 void CVorbisProcessor::ConfigureL(TInt aSampleRate, TInt aChannels)
00395 {
00396 VORBIS_TRAPD(leaveErr, iEncoder->ConfigureL(aSampleRate, aChannels));
00397 User::LeaveIfError(leaveErr);
00398 }