I am trying to encode "live" (buffered) audio data to OggVorbis format however it just isn't working for me. No matter what I do, the output stream contains only the Vorbis header (no Ogg data).
I have successfully encoded to an MP3 stream using libLAME in the same way (replacing ogg functions with LAME obviously).
I have included my code for retrieving the PCM data, feeding it to libOgg and retrieving the output and buffering it. At the moment I am breaking at the "Buffer Overflow" stage and using Xcode to view the memory contained within the outputBuffer.
As I said above, this works for MP3 using libLAME, so I know I can't be far off. If I look at ogg.header and ogg.body, they contain data and ogg.header_length is 282 and ogg.body_length is 255.
If required, I can paste bin the outputBuffer for people to look at.
UInt32 ioLengthInFrames = 256;//ioBufferDuration * self.audioFormat->mSampleRate;
AudioBufferList *ioData = AllocateABL(self.audioFormat->mChannelsPerFrame, self.audioFormat->mBytesPerFrame, NO, ioLengthInFrames);
AudioBufferList *floatData = AllocateABL(self.audioFormat->mChannelsPerFrame, self.audioFormat->mBytesPerFrame, NO, ioLengthInFrames);
UInt32 retVal = TPCircularBufferPeek(inputBuffer, NULL, self.audioFormat);
if (!retVal > 0)
return;
//NSLog (@"Frames Available: %ld", retVal);
TPCircularBufferDequeueBufferListFrames(inputBuffer, &ioLengthInFrames, ioData, NULL, self.audioFormat);
AEFloatConverterToFloatBufferList(self.floatConverter, ioData, floatData, ioLengthInFrames);
if (ioLengthInFrames <= 0)
{
NSLog(@"Not enough frames");
return;
}
float **buffer = vorbis_analysis_buffer(&vd, ioLengthInFrames * self.audioFormat->mBytesPerFrame);
buffer[0] = floatData->mBuffers[0].mData;
buffer[1] = floatData->mBuffers[1].mData;
checkresult (vorbis_analysis_wrote(&vd, ioLengthInFrames * self.audioFormat->mBytesPerFrame), @"Analysis Wrote");
int wrote = 0;
while (vorbis_analysis_blockout(&vd, &vb) == 1)
{
NSLog(@"Block Out");
checkresult (vorbis_analysis(&vb, NULL), @"Analysis");
checkresult (vorbis_bitrate_addblock(&vb), @"BitRate AddBlock");
while (vorbis_bitrate_flushpacket(&vd, &op))
{
NSLog(@"Flush Packet");
ogg_stream_packetin(&os, &op);
bool eos = false;
while (!eos)
{
NSLog(@"EOS");
int result = ogg_stream_pageout(&os, &og);
if (result==0)break;
NSLog(@"EOS 2");
int availableBytes;
unsigned char* head = TPCircularBufferHead(&outputBuffer, &availableBytes);
if (availableBytes < og.header_len + og.body_len)
{
return;
// Buffer Full
}
memcpy(head, og.header, og.header_len);
memcpy(head+og.header_len, og.body, og.body_len);
TPCircularBufferProduce(&outputBuffer, og.header_len + og.body_len);
wrote += og.header_len + og.body_len;
if (ogg_page_eos(&og))eos=true;
}
}
}
NSLog(@"Rendering OggVorbis: %d bytes written", wrote);
In the end I got it working. I had to use memcpy to fill the libOgg input buffers and I had to fix the value I was passing in for the number of samples I was copying to the buffer.
Please see the working code below: