赞
踩
近期收到一个用户需求,要求音视频组件能够切换声卡,首先要在vlc上实现,于是马不停蹄的研究起来,马上查阅对应vlc有没有自带的api接口,查看接口前,先打开vlc播放器,看下能不能切换,因为不是所有播放器都有这个功能,试了下vlc当然是可以的,这个是最基本的前提,如果连播放器本身都没有,那就很悬了。vlc的主要播放接口都在 libvlc_media_player.h 头文件中,音频设备搜索关键词是 audio device 之类的,找到libvlc_audio_output_device_set这个函数,根据对应的函数接口上面的注释解析,提示需要先执行libvlc_audio_output_set才能正确执行成功。不得不说vlc的函数接口中的英文说明还是非常详细的,相同类似的或者相关的函数都会写在上面,比如还提示了libvlc_audio_output_device_enum用于枚举当前播放支持的音频设备。
拿到接口仅仅是第一步,根据参数要求有个device_id的参数需要传入,这个应该是音频输出设备的编号,而我们一般人类认知的一般是设备名,而不是设备编号,于是又需要通过vlc中的函数去获取设备名称和编号集合,下拉框中显示的是中文的非常直观的设备名称,对应传入的就是设备编号,一串系统底层定义的设备唯一编号。上面就已经说了通过libvlc_audio_output_device_enum可以用于枚举当前播放实例支持的设备,那有没有可能提供一个静态的全局函数来获取这个列表呢?因为不想每次都通过new一个播放实例再去获取,当然也是可以的,经过反复折腾,发现只需要有一个libvlc_instance_t实例即可,根本不需要libvlc_media_player_t对象。于是直接在vlchelper类中封装了一个静态函数,专门获取本机的音频输出设备列表。再做的好一点就是,为了防止每次都去获取一次,直接定义成static变量,判断没有获取过就去获取一次就行。这里特别需要提示的是,切换声卡后vlc不会立即应用,需要关闭libvlc_media_player_stop再重新打开播放libvlc_media_player_play才会正常应用。
既然vlc搞定了,那mpv等内核按照这个机制来,应该也是可以的,mpv相对来说要简单一些,这主要得益于mpv的万能接口设计,通过set/get这种机制,提供对照表,根据对照表来就行。qtmpv::get_property(mpvPlayer, “audio-device-list”)获取音频设备列表,qtmpv::set_property(mpvPlayer, “audio-device”, device)用来切换声卡即可。
void FFmpegThread::setAudioDevice(const QString &audioDevice) { //默认设备不用处理 if (audioDevice == "default") { return; } this->audioDevice = audioDevice; if (audioIndex < 0 || !audioPlayer || audioDevice.isEmpty()) { return; } this->initAudioOutput(); } void FFmpegThread::initAudioOutput() { //打开音频播放设备 QMetaObject::invokeMethod(audioPlayer, "openAudioOutput", Q_ARG(QString, audioDevice), Q_ARG(int, sampleRate), Q_ARG(int, channelCount), Q_ARG(int, 16)); } void AudioPlayer::openAudioOutput(const QString &deviceName, int sampleRate, int channelCount, int sampleSize) { #ifdef multimedia //先关闭设备 this->closeAudioOutput(); //初始化音频格式 QAudioFormat format; AudioHelper::initAudioFormat(format, sampleRate, channelCount, sampleSize); this->sampleSize = sampleSize; //找到指定设备并实例化音频类(为空则采用默认设备) if (deviceName.isEmpty()) { audioOutput = new QAudioOutputx(format, this); } else { QAudioDevice device = AudioHelper::getAudioDevice(deviceName, false); audioOutput = new QAudioOutputx(device, format, this); } //启动音频服务 deviceOutput = audioOutput->start(); //重新设置音量大小 this->setVolume(volume); #endif } void AudioPlayer::closeAudioOutput() { #ifdef multimedia if (audioOutput) { audioOutput->reset(); audioOutput->stop(); audioOutput->deleteLater(); audioOutput = NULL; } #endif } void AudioHelper::initAudioFormat(QAudioFormat &format, int sampleRate, int channelCount, int sampleSize) { //qDebug() << sampleRate << channelCount << sampleSize; format.setSampleRate(sampleRate); format.setChannelCount(channelCount); #if (QT_VERSION >= QT_VERSION_CHECK(6,2,0)) if (sampleSize == 8) { format.setSampleFormat(QAudioFormat::UInt8); } else if (sampleSize == 16) { format.setSampleFormat(QAudioFormat::Int16); } else if (sampleSize == 32) { format.setSampleFormat(QAudioFormat::Int32); } #else format.setSampleSize(sampleSize); format.setCodec("audio/pcm"); format.setSampleType(sampleSize == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt); format.setByteOrder(QAudioFormat::LittleEndian); #endif }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。