首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >libOgg / libVorbis和AudioBufferList

libOgg / libVorbis和AudioBufferList
EN

Stack Overflow用户
提问于 2013-12-17 12:41:19
回答 1查看 418关注 0票数 1

我正在尝试将“实时”(缓冲)音频数据编码为OggVorbis格式,但它对我来说就是不起作用。无论我做什么,输出流只包含Vorbis头(不包含Ogg数据)。

我已经用libLAME以同样的方式成功地编码成了MP3流(显然用LAME替换了ogg函数)。

我已经包含了用于检索PCM数据、将其提供给libOgg、检索输出并对其进行缓冲的代码。目前,我正处于“缓冲区溢出”阶段,使用Xcode查看outputBuffer中包含的内存。

正如我上面所说的,这适用于使用libLAME的MP3,所以我知道我离得不远了。如果我看一下ogg.header和ogg.body,它们包含数据,ogg.header_length是282,ogg.body_length是255。

如果需要,我可以将outputBuffer粘贴到垃圾箱中,供人们查看。

代码语言:javascript
复制
    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);
EN

回答 1

Stack Overflow用户

发布于 2013-12-17 18:41:00

最后,我让它工作了。我必须使用memcpy来填充libOgg输入缓冲区,并且我必须为要复制到缓冲区的样本数修改传入的值。

请看下面的工作代码:

代码语言:javascript
复制
    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;

    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);

    memcpy(buffer[0], floatData->mBuffers[0].mData, floatData->mBuffers[0].mDataByteSize);
    memcpy(buffer[1], floatData->mBuffers[1].mData, floatData->mBuffers[1].mDataByteSize);

    checkresult (vorbis_analysis_wrote(&vd, ioLengthInFrames), @"Analysis Wrote");

    int wrote = 0;

    while (vorbis_analysis_blockout(&vd, &vb) == 1)
    {
        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)
            {
                int result = ogg_stream_pageout(&os, &og);
                if (result==0)break;

                int size = og.header_len + og.body_len;

                int availableBytes;
                unsigned char* head = TPCircularBufferHead(&outputBuffer, &availableBytes);

                if (availableBytes < size)
                {
                    NSLog(@"Buffer Full");
                    return;
                }

                memcpy(head, og.header, og.header_len);
                memcpy(head+og.header_len, og.body, og.body_len);
                TPCircularBufferProduce(&outputBuffer, size);

                wrote += size;

                if (ogg_page_eos(&og))eos=true;
            }
        }
    }

    NSLog(@"Rendering OggVorbis: %d bytes written", wrote);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20626054

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档