Rudius guerrerat 2024-03-26 00:43 采纳率: 50%
浏览 59

QaudioOutput读取音频噪音和卡顿问题

void AVPlayer::audioCallBack(uint8_t *m_audiobuffer, std::shared_ptr<void> par)
{
    // 加锁
    m_mutex.lock();

    m_audioIndex = m_pDecoder->audioIndex();
    int errtimes = 10;
    double currenttime = 0.00;
    double nexttime = 0.00;
    QByteArray audioBuffer;

    int desiredBufferSize = 5 * output->periodSize();
    // double times = output->bufferSize() / output->periodSize();

    while (1)
    {
        int ret = m_pDecoder->getAFrame(m_audioFrame);
        if (ret != 1)
        {
            if (errtimes == 0)
            {
                printf("Failed to get audio frame.\n");
                break;
            }
            errtimes--;
            printf("Retrying...\n");
            continue;
        }
        // Calculate the next timestamp based on the audio frame's presentation time
        double nexttime = m_audioFrame->pts * av_q2d(m_pFormatContext->streams[m_audioIndex]->time_base);

        // Convert the frame to PCM
        int len = Audio::AudioFFmpeg::GetAudio()->ToPCM(&m_audiobuffer, m_audioFrame, &m_audioBufSize);

        // Sleep until the next timestamp
        av_usleep(nexttime * 1000000 - currenttime * 1000000);
        currenttime = nexttime;

        // Accumulate audio data in the buffer
        audioBuffer.append(reinterpret_cast<const char *>(m_audiobuffer), len);

        // Check if the accumulated data is enough to write

        while (audioBuffer.size() >= desiredBufferSize)
        {
            io->write(audioBuffer.constData(),len);
            audioBuffer.remove(0,len); // Remove the written data from the buffer
        }

        // Update the audio clock
        AVPlayer::GetPlay()->m_audioClock.setClock(currenttime);

        // Clear the audio buffer
        memset(m_audiobuffer, 0, m_audioBufSize);
    }
    // 释放锁
    m_mutex.unlock();
}

把output->bufferSize()缓冲区全部读出就不会有白噪音,但会出现明显卡顿,如果分批读取output->periodSize()则会出现白噪音(蜂鸣声)。

  • 写回答

3条回答 默认 最新

  • 关注

    Rudius guerrerat 上午好☀️☀️☀️️
    本答案参考ChatGPT-3.5

    针对音频噪音和卡顿问题,可以考虑以下解决方案:

    1. 调整音频输出缓冲区的大小:根据你提到的问题,如果一次性将整个缓冲区读出,可以避免白噪音,但会出现卡顿。而分批读取缓冲区会出现白噪音。这可能意味着缓冲区的大小设置不合适。建议尝试调整缓冲区的大小,以找到一个合适的平衡点,既能避免白噪音,又能减少卡顿。

    2. 调整音频播放的速率:如果卡顿问题无法通过调整缓冲区大小解决,可以尝试调整音频播放的速率。可以尝试将音频帧的播放速率加快或减慢,以适应音频的数据流。这样可以在不丢失音频数据的情况下,提高播放的实时性和流畅性。

    3. 优化音频解码和播放过程:确保音频解码和播放过程的效率高,避免因为解码过慢或播放过程中的阻塞导致的卡顿问题。可以检查代码逻辑,尽量减少耗时操作,并确保解码和播放的线程不会相互阻塞。

    4. 使用合适的音频编解码库:使用当前版本稳定可靠的编解码库,确保音频的解码和播放能够被正确地支持和处理。同时,对于存在问题的编解码库,可以尝试升级到修复了已知问题和优化了性能的版本。

    以下是给出的修改后的代码,对应上述解决方案中的第1点:

    void AVPlayer::audioCallBack(uint8_t *m_audiobuffer, std::shared_ptr<void> par)
    {
        // 加锁
        m_mutex.lock();
    
        m_audioIndex = m_pDecoder->audioIndex();
        int errtimes = 10;
        double currenttime = 0.00;
        double nexttime = 0.00;
        QByteArray audioBuffer;
    
        int desiredBufferSize = output->periodSize(); // 修改为一个period的大小
    
        while (1)
        {
            // ...
    
            // Accumulate audio data in the buffer
            audioBuffer.append(reinterpret_cast<const char *>(m_audiobuffer), len);
    
            // Check if the accumulated data is enough to write
            if (audioBuffer.size() >= desiredBufferSize)
            {
                io->write(audioBuffer.constData(), desiredBufferSize); // 只写入desiredBufferSize大小的数据
                audioBuffer.remove(0, desiredBufferSize); // Remove the written data from the buffer
            }
    
            // ...
        }
        // 释放锁
        m_mutex.unlock();
    }
    

    以上修改后的代码将每次从缓冲区写入desiredBufferSize大小的音频数据,这样可以减少白噪音的产生,同时分批处理可以避免卡顿问题。

    评论

报告相同问题?

问题事件

  • 创建了问题 3月26日

悬赏问题

  • ¥20 python爬虫遇到空文本取不出来
  • ¥15 x264库中预测模式字IPM、运动向量差MVD、量化后的DCT系数的位置
  • ¥15 curl 命令调用正常,程序调用报 java.net.ConnectException: connection refused
  • ¥20 关于web前端如何播放二次加密m3u8视频的问题
  • ¥15 使用百度地图api 位置函数报错?
  • ¥15 metamask如何添加TRON自定义网络
  • ¥66 关于川崎机器人调速问题
  • ¥15 winFrom界面无法打开
  • ¥30 crossover21 ARM64版本安装软件问题
  • ¥15 mymetaobjecthandler没有进入