QtScrcpy源码解析(4)

311 阅读1分钟

前沿

之前开发了一个云真机软件,参考的是QtScrcpy这个工程来开发。
开发的时间比较旧了,当时参考的这个工程还是一年多前了,现在回头再看看,源码解析一下这个工程,顺便也重新学习一下。
QtScrcpy地址
解析的版本是v2.1.2

音频处理

使用了sndcpy库,同样也是通过socket连接手机服务实现
sndcpy地址
主要实现的类在audiooutput.cpp中

void AudioOutput::startAudioOutput()
{
    if (m_audioOutput) {
        return;
    }
    // 使用QAudioOutput来播放音频
    QAudioFormat format;
    format.setSampleRate(48000);
    format.setChannelCount(2);
    format.setSampleSize(16);
    format.setCodec("audio/pcm");
    format.setByteOrder(QAudioFormat::LittleEndian);
    format.setSampleType(QAudioFormat::SignedInt);

    QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
    if (!info.isFormatSupported(format)) {
        qWarning() << "AudioOutput::audio format not supported, cannot play audio.";
        return;
    }

    m_audioOutput = new QAudioOutput(format, this);
    connect(m_audioOutput, &QAudioOutput::stateChanged, this, [](QAudio::State state) {
        qInfo() << "AudioOutput::audio state changed:" << state;
    });
    m_audioOutput->setBufferSize(48000*2*15/1000 * 20);
    m_outputDevice = m_audioOutput->start();
}

void AudioOutput::startRecvData(int port)
{
    // 省略
    // 实时读取音频数据,将音频数据输入到QAudioOutput中进行播放
    connect(audioSocket, &QIODevice::readyRead, audioSocket, [this, audioSocket]() {
        qint64 recv = audioSocket->bytesAvailable();
        //qDebug() << "AudioOutput::recv data:" << recv;

        if (!m_outputDevice) {
            return;
        }
        if (m_buffer.capacity() < recv) {
            m_buffer.reserve(recv);
        }

        qint64 count = audioSocket->read(m_buffer.data(), audioSocket->bytesAvailable());
        m_outputDevice->write(m_buffer.data(), count);
    });
    // 省略
}