Iphone 串流和播放音频问题

发布于 2024-11-28 19:09:31 字数 1811 浏览 1 评论 0原文

我正在尝试制作一个使用 ffmpeg、libmms 播放音频流的应用程序。
我可以打开彩信服务器,获取流,并使用合适的编解码器将音频帧解码为原始帧。
但我不知道下一步该怎么做。
我想我必须使用 AudioToolbox/AudioToolbox.h 并制作音频队列。
但是当我给audioqueuebuffer解码缓冲区的内存并播放时,只播放白噪声。
这是我的代码。

我缺少什么?
非常感谢任何评论和提示。
非常感谢。

while(av_read_frame(pFormatCtx, &pkt)>=0)
{
    int pkt_decoded_len = 0;
    int frame_decoded_len;
    int decode_buff_remain=AVCODEC_MAX_AUDIO_FRAME_SIZE * 5;
    if(pkt.stream_index==audiostream)
    {
        frame_decoded_len=decode_buff_remain;
        int16_t *decode_buff_ptr = decode_buffer;
        int decoded_tot_len=0;
        pkt_decoded_len = avcodec_decode_audio2(pCodecCtx, decode_buff_ptr, &frame_decoded_len,
                                                pkt.data, pkt.size);
        if (pkt_decoded_len <0) break;
        AudioQueueAllocateBuffer(audioQueue, kBufferSize, &buffers[i]);
        AQOutputCallback(self, audioQueue, buffers[i], pkt_decoded_len);

        if(i == 1){
            AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, 1.0);
            AudioQueueStart(audioQueue, NULL);
        }
        i++;
    }
}


void AQOutputCallback(void *inData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, int copySize)
{
    mmsDemoViewController *staticApp = (mmsDemoViewController *)inData;
    [staticApp handleBufferCompleteForQueue:inAQ buffer:inBuffer size:copySize];
}

- (void)handleBufferCompleteForQueue:(AudioQueueRef)inAQ
                          buffer:(AudioQueueBufferRef)inBuffer
                            size:(int)copySize
{
    inBuffer->mAudioDataByteSize = inBuffer->mAudioDataBytesCapacity;
    memcpy((char*)inBuffer->mAudioData, (const char*)decode_buffer, copySize);

    AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);
}

I am trying to make an app that plays audio stream using ffmpeg, libmms.
I can open mms server, get stream, and decode audio frame to raw frame using suitable codec.
However I don't know how to do next.
I think I must use AudioToolbox/AudioToolbox.h and make audioqueue.
but however when I give audioqueuebuffer decode buffer's memory and play, Only plays the white noise.
Here is my code.

What am i missing?
Any comment and hint is very appreciated.
Thanks very much.

while(av_read_frame(pFormatCtx, &pkt)>=0)
{
    int pkt_decoded_len = 0;
    int frame_decoded_len;
    int decode_buff_remain=AVCODEC_MAX_AUDIO_FRAME_SIZE * 5;
    if(pkt.stream_index==audiostream)
    {
        frame_decoded_len=decode_buff_remain;
        int16_t *decode_buff_ptr = decode_buffer;
        int decoded_tot_len=0;
        pkt_decoded_len = avcodec_decode_audio2(pCodecCtx, decode_buff_ptr, &frame_decoded_len,
                                                pkt.data, pkt.size);
        if (pkt_decoded_len <0) break;
        AudioQueueAllocateBuffer(audioQueue, kBufferSize, &buffers[i]);
        AQOutputCallback(self, audioQueue, buffers[i], pkt_decoded_len);

        if(i == 1){
            AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, 1.0);
            AudioQueueStart(audioQueue, NULL);
        }
        i++;
    }
}


void AQOutputCallback(void *inData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, int copySize)
{
    mmsDemoViewController *staticApp = (mmsDemoViewController *)inData;
    [staticApp handleBufferCompleteForQueue:inAQ buffer:inBuffer size:copySize];
}

- (void)handleBufferCompleteForQueue:(AudioQueueRef)inAQ
                          buffer:(AudioQueueBufferRef)inBuffer
                            size:(int)copySize
{
    inBuffer->mAudioDataByteSize = inBuffer->mAudioDataBytesCapacity;
    memcpy((char*)inBuffer->mAudioData, (const char*)decode_buffer, copySize);

    AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

樱桃奶球 2024-12-05 19:09:31

您错误地调用了 AQOutputCallback。您不必调用该方法。
当音频队列使用音频缓冲区时,将自动调用该方法。
并且AQOutputCallback的原型是错误的。
根据你的代码,我认为该方法不会被自动调用。
您可以

typedef void (*AudioQueueOutputCallback) (
   void                 *inUserData,
   AudioQueueRef        inAQ,
   AudioQueueBufferRef  inBuffer
);

像这样

void AudioQueueCallback(void* inUserData, AudioQueueRef inAQ, AudioQueueBufferRef 
                       inBuffer);

覆盖,并且您应该在应用程序启动时设置音频会话。
重要的参考文献是 这里。

但是,您愿意解码的音频扩展名是什么?
如果音频是每个数据包的可变帧,则 AudioStreamPacketDescription 非常重要。
否则,如果每个数据包一帧,则 AudioStreamPacketDescription 并不重要。

接下来你要做的是
设置音频会话,使用解码器获取原始音频帧,将帧放入音频缓冲区。
代替你,让系统填充空的缓冲区。

You called AQOutputCallback wrongly. You don't have to necessarilly call that method.
That method will be called automatically when audio buffers used by audio queue.
And the prototype of AQOutputCallback was wrong.
According to your code That method will not be called automatically I think.
You can Override

typedef void (*AudioQueueOutputCallback) (
   void                 *inUserData,
   AudioQueueRef        inAQ,
   AudioQueueBufferRef  inBuffer
);

like this

void AudioQueueCallback(void* inUserData, AudioQueueRef inAQ, AudioQueueBufferRef 
                       inBuffer);

And you should set the Audio Session When your app starts.
The important references are here.

However, What is the extension of Audio you are willing to decode?
AudioStreamPacketDescription is important if the Audio is Variable Frame per packet.
Otherwise, if One Frame per One Packet, AudioStreamPacketDescription is not significant.

What you do next is
To Set the audio session, To Get raw audio frame using decoder, To Put the frame into the Audio Buffer.
Instead of you, Make the system to fill the empty buffer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文