libVLC 音频立体声模式切换

在libVLC中,可以使用libvlc_audio_set_channel函数来设置音频的立体声模式。这个函数允许选择不同的音频通道,例如立体声、左声道、右声道、环绕声等。

/*** Set current audio channel.** \param p_mi media player* \param channel the audio channel, \see libvlc_audio_output_channel_t* \return 0 on success, -1 on error*/
LIBVLC_API int libvlc_audio_set_channel( libvlc_media_player_t *p_mi, int channel );

参数说明:

  • p_mi:媒体播放器实例。
  • channel:要设置的音频通道,是一个 libvlc_audio_output_channel_t 类型的枚举值。

返回值是一个整数,如果设置成功则返回 0,如果设置失败则返回一个负数。

的可能值包括:

/*** Audio channels*/
typedef enum libvlc_audio_output_channel_t {libvlc_AudioChannel_Error   = -1, //错误通道libvlc_AudioChannel_Stereo  =  1, //立体声libvlc_AudioChannel_RStereo =  2, //翻转立体声libvlc_AudioChannel_Left    =  3, //左声道libvlc_AudioChannel_Right   =  4, //右声道libvlc_AudioChannel_Dolbys  =  5  //杜比环绕声
} libvlc_audio_output_channel_t;

以下是VLC播放器中使用的视频裁剪,我们仿照这个做一个界面。  

以下是做出来的效果:

首先做一个菜单:

	QMenu *m_moduleMenu = nullptr;		//立体声模式菜单QAction *m_actionModule = nullptr;	//立体声模式QAction *m_actionMono = nullptr;//单声道QAction *m_actionStereo = nullptr;//立体声QAction *m_actionLeft = nullptr;//左声道QAction *m_actionRight = nullptr;//右声道QAction *m_actionRevStereo = nullptr;//反转立体声m_moduleMenu = new QMenu(this);m_actionMono = m_moduleMenu->addAction("单声道");m_actionMono->setData((int)libvlc_AudioChannel_Dolbys);m_actionStereo = m_moduleMenu->addAction("立体声");m_actionStereo->setData((int)libvlc_AudioChannel_Stereo);m_actionLeft = m_moduleMenu->addAction("左声道");m_actionLeft->setData((int)libvlc_AudioChannel_Left);m_actionRight = m_moduleMenu->addAction("右声道");m_actionRight->setData((int)libvlc_AudioChannel_Right);m_actionRevStereo = m_moduleMenu->addAction("反转立体声");m_actionRevStereo->setData((int)libvlc_AudioChannel_RStereo);m_actionModule->setMenu(m_moduleMenu);

接受槽函数的响应事件:

void showWidget::slotActionModuleTriggered(QAction *action)
{if (!vlc_mediaPlayer)return;libvlc_audio_output_channel_t channel = (libvlc_audio_output_channel_t)action->data().toInt();int cc = libvlc_audio_set_channel(vlc_mediaPlayer, channel);action->setIcon(QIcon(":/image/images/point.png"));m_preAction->setIcon(QIcon());m_preAction = action;
}

设置鼠标右键弹出菜单:重写鼠标点击事件,弹出菜单。

首先设置libvlc忽略鼠标事件libvlc_video_set_mouse_input(vlc_mediaPlayer, 0);

再重写鼠标事件:

void showWidget::mousePressEvent(QMouseEvent *event)
{switch (event->button()){case Qt::RightButton://this->setWindowState(Qt::WindowMinimized);m_menu->exec(event->globalPos());break;default:QWidget::mousePressEvent(event);}
}

完整代码:

头文件。

#pragma once#include <QtWidgets/QWidget>
#include "ui_showWidget.h"
#include <QMenu>
#include <QActionGroup>
#include <vlc/vlc.h>
#include <QDebug>
#include <QFileDialog>
#include <QThread>
#include <QMouseEvent>
#include <QKeyEvent>enum Rate
{Rate2X,Rate1_5X,Rate1_25X,Rate1_0X,Rate0_75X,Rate0_5X
};class showWidget : public QWidget
{Q_OBJECTpublic:showWidget(QWidget *parent = nullptr);~showWidget();private slots:void slotOpenFile();void slotPlay();void slotPause();void slotStop();void slotValueChanged(int value);void slotCurrentIndexChanged(int index);void slotActionTriggered(QAction *action);void slotActionModuleTriggered(QAction *action);protected:virtual void mousePressEvent(QMouseEvent *event);private://事件处理回调static void vlcEvents(const libvlc_event_t *ev, void *param);private:Ui::showWidgetClass ui;private:libvlc_instance_t *vlc_base = nullptr;libvlc_media_t *vlc_media = nullptr;libvlc_media_player_t *vlc_mediaPlayer = nullptr;QList<float> m_lstRate;QList<QString> m_lstAudioDevice;QMenu *m_menu = nullptr;QMenu *m_deviceMenu = nullptr;			//音频设备菜单QMenu *m_moduleMenu = nullptr;		//立体声模式菜单QAction *m_actionAudioDev = nullptr;	//音频设备QAction *m_actionModule = nullptr;	//立体声模式QAction *m_actionMono = nullptr;//单声道QAction *m_actionStereo = nullptr;//立体声QAction *m_actionLeft = nullptr;//左声道QAction *m_actionRight = nullptr;//右声道QAction *m_actionRevStereo = nullptr;//反转立体声QActionGroup *m_group = nullptr;QActionGroup *m_groupModule = nullptr;QAction *m_preAction = nullptr;
};

cpp文件。 

#include "showWidget.h"
#include <QTimer>
#include <QTime>#pragma execution_character_set("utf-8")showWidget::showWidget(QWidget *parent): QWidget(parent)
{ui.setupUi(this);this->setWindowTitle("视频播放器");m_menu = new QMenu(this);m_actionAudioDev = m_menu->addAction("音频设备");m_actionModule = m_menu->addAction("立体声模式");m_deviceMenu = new QMenu(this);m_actionAudioDev->setMenu(m_deviceMenu);m_moduleMenu = new QMenu(this);m_actionMono = m_moduleMenu->addAction("单声道");m_actionMono->setData((int)libvlc_AudioChannel_Dolbys);m_actionStereo = m_moduleMenu->addAction("立体声");m_actionStereo->setData((int)libvlc_AudioChannel_Stereo);m_actionLeft = m_moduleMenu->addAction("左声道");m_actionLeft->setData((int)libvlc_AudioChannel_Left);m_actionRight = m_moduleMenu->addAction("右声道");m_actionRight->setData((int)libvlc_AudioChannel_Right);m_actionRevStereo = m_moduleMenu->addAction("反转立体声");m_actionRevStereo->setData((int)libvlc_AudioChannel_RStereo);m_actionModule->setMenu(m_moduleMenu);m_group = new QActionGroup(this);connect(m_group, &QActionGroup::triggered, this, &showWidget::slotActionTriggered);m_groupModule = new QActionGroup(this);m_groupModule->addAction(m_actionMono);m_groupModule->addAction(m_actionStereo);m_groupModule->addAction(m_actionLeft);m_groupModule->addAction(m_actionRight);m_groupModule->addAction(m_actionRevStereo);connect(m_groupModule, &QActionGroup::triggered, this, &showWidget::slotActionModuleTriggered);vlc_base = libvlc_new(0, NULL);m_lstAudioDevice.clear();libvlc_audio_output_device_t *pDevList = nullptr;libvlc_audio_output_t *pOutputList = libvlc_audio_output_list_get(vlc_base);while (pOutputList){//获取设备pDevList = libvlc_audio_output_device_list_get(vlc_base, pOutputList->psz_name);while (pDevList){// 找到我想要的那个设备,跳出循环,这里使用i控制,我知道我想要的设备位置if (strcmp(pOutputList->psz_name, "mmdevice") == 0){QString des = QString::fromStdString(std::string(pDevList->psz_description, strlen(pDevList->psz_description)));m_lstAudioDevice.append(des);QAction *action = m_deviceMenu->addAction(des);action->setData(pDevList->psz_device);m_group->addAction(action);}pDevList = pDevList->p_next;}pOutputList = pOutputList->p_next;}ui.cbxRate->setCurrentIndex(Rate1_0X);m_lstRate << 2.0 << 1.5 << 1.25 << 1.0 << 0.75 << 0.5;ui.btnOpen->setFocusPolicy(Qt::NoFocus);ui.btnPlay->setFocusPolicy(Qt::NoFocus);ui.btnPause->setFocusPolicy(Qt::NoFocus);ui.btnStop->setFocusPolicy(Qt::NoFocus);ui.hSliderVolumn->setFocusPolicy(Qt::NoFocus);ui.cbxRate->setFocusPolicy(Qt::NoFocus);connect(ui.btnOpen, &QPushButton::clicked, this, &showWidget::slotOpenFile);connect(ui.btnPlay, &QPushButton::clicked, this, &showWidget::slotPlay);connect(ui.btnPause, &QPushButton::clicked, this, &showWidget::slotPause);connect(ui.btnStop, &QPushButton::clicked, this, &showWidget::slotStop);connect(ui.hSliderVolumn, &QSlider::valueChanged, this, &showWidget::slotValueChanged);connect(ui.cbxRate,SIGNAL(currentIndexChanged(int)), this, SLOT(slotCurrentIndexChanged(int)));
}showWidget::~showWidget()
{libvlc_release(vlc_base); //减少libvlc实例的引用计数,并销毁
}void showWidget::slotOpenFile()
{/*选择文件*/QString filename = QFileDialog::getOpenFileName(this, "选择打开的文件", "D:/", tr("*.*"));std::replace(filename.begin(), filename.end(), QChar('/'), QChar('\\'));vlc_media = libvlc_media_new_path(vlc_base, filename.toUtf8().data());if (!vlc_media) {return;}// 创建libvlc实例和媒体播放器vlc_mediaPlayer = libvlc_media_player_new_from_media(vlc_media);if (!vlc_mediaPlayer) {return;}//libvlc_media_add_option(vlc_media, "--video-filter=transform");//libvlc_media_add_option(vlc_media, "---transform-type=270");// 等待元数据加载完成libvlc_media_parse(vlc_media);libvlc_video_set_mouse_input(vlc_mediaPlayer, 0);libvlc_video_set_key_input(vlc_mediaPlayer, 0);// 获取各种元数据const char *title = libvlc_media_get_meta(vlc_media, libvlc_meta_Title);const char *artist = libvlc_media_get_meta(vlc_media, libvlc_meta_Artist);const char *album = libvlc_media_get_meta(vlc_media, libvlc_meta_Album);const char *url = libvlc_media_get_meta(vlc_media, libvlc_meta_URL);const char *date = libvlc_media_get_meta(vlc_media, libvlc_meta_Date);const char *lang = libvlc_media_get_meta(vlc_media, libvlc_meta_Language);int duration = libvlc_media_get_duration(vlc_media);  // 获取时长(单位:毫秒)qDebug("Title: %s", title ? title : "N/A");qDebug("Artist: %s", artist ? artist : "N/A");qDebug("Album: %s", album ? album : "N/A");qDebug("Duration: %d ms", duration);qDebug("url: %s", url ? url : "N/A");qDebug("date: %s", date ? date : "N/A");qDebug("lang: %s", lang ? lang : "N/A");libvlc_media_track_t **tracks;int track_count = libvlc_media_tracks_get(vlc_media,&tracks);for (unsigned i = 0; i < track_count; i++) {libvlc_media_track_t* track = tracks[i];// 显示轨道信息printf("Track #%u: %s\n", i, track->psz_description);// 这里可以获取到每一个轨道的信息,比如轨道类型 track->i_type// 可能是 libvlc_track_video, libvlc_track_audio 或者 libvlc_track_text (字幕)if (track->i_type == libvlc_track_video) {// 处理视频轨道信息qDebug("width = %d",track->video->i_width);qDebug("height = %d", track->video->i_height);qDebug("rate_num = %d", track->video->i_frame_rate_num);qDebug("rate_den = %d", track->video->i_frame_rate_den);}else if (track->i_type == libvlc_track_audio) {// 处理音频轨道信息qDebug("channels = %d", track->audio->i_channels);qDebug("rate = %d", track->audio->i_rate);}else if (track->i_type == libvlc_track_text) {// 处理字幕轨道信息}}//获取事件管理器libvlc_event_manager_t *em = libvlc_media_player_event_manager(vlc_mediaPlayer);// 注册事件监听器libvlc_event_attach(em, libvlc_MediaPlayerTimeChanged, vlcEvents, this);libvlc_event_attach(em, libvlc_MediaPlayerEndReached, vlcEvents, this);libvlc_event_attach(em, libvlc_MediaPlayerStopped, vlcEvents, this);libvlc_event_attach(em, libvlc_MediaPlayerPlaying, vlcEvents, this);libvlc_event_attach(em, libvlc_MediaPlayerPaused, vlcEvents, this);libvlc_media_player_set_hwnd(vlc_mediaPlayer, (void *)ui.widgetShow->winId());libvlc_video_set_adjust_int(vlc_mediaPlayer, libvlc_adjust_Enable, 1);//获取当前的channelint curChannel = libvlc_audio_get_channel(vlc_mediaPlayer);m_actionStereo->setIcon(QIcon(":/image/images/point.png"));m_preAction = m_actionStereo;QTimer::singleShot(1000, this, &showWidget::slotPlay);libvlc_video_filter_list_get(vlc_base);
}void showWidget::slotPlay()
{if (vlc_mediaPlayer){libvlc_media_player_play(vlc_mediaPlayer);}}void showWidget::slotPause()
{if (vlc_mediaPlayer)libvlc_media_player_pause(vlc_mediaPlayer);
}void showWidget::slotStop()
{if (vlc_mediaPlayer)libvlc_media_player_stop(vlc_mediaPlayer);
}void showWidget::slotValueChanged(int value)
{if (vlc_mediaPlayer)libvlc_audio_set_volume(vlc_mediaPlayer, value);
}void showWidget::slotCurrentIndexChanged(int index)
{if (vlc_mediaPlayer)libvlc_media_player_set_rate(vlc_mediaPlayer, m_lstRate[index]);
}void showWidget::slotActionTriggered(QAction *action)
{if (!vlc_mediaPlayer)return;QString txt = action->data().toString();//指定设备输出pDevList->psz_devicelibvlc_audio_output_device_set(vlc_mediaPlayer, NULL, txt.toStdString().c_str());
}void showWidget::slotActionModuleTriggered(QAction *action)
{if (!vlc_mediaPlayer)return;libvlc_audio_output_channel_t channel = (libvlc_audio_output_channel_t)action->data().toInt();int cc = libvlc_audio_set_channel(vlc_mediaPlayer, channel);action->setIcon(QIcon(":/image/images/point.png"));m_preAction->setIcon(QIcon());m_preAction = action;
}void showWidget::mousePressEvent(QMouseEvent *event)
{switch (event->button()){case Qt::RightButton://this->setWindowState(Qt::WindowMinimized);m_menu->exec(event->globalPos());break;default:QWidget::mousePressEvent(event);}
}//事件回调
void showWidget::vlcEvents(const libvlc_event_t *ev, void *param)
{showWidget *w = (showWidget*)param;//处理不同的事件switch (ev->type) {case libvlc_MediaPlayerTimeChanged:{//qDebug() << "VLC媒体播放器时间已更改";qint64 len = libvlc_media_player_get_time(w->vlc_mediaPlayer);libvlc_time_t lenSec = len / 1000;libvlc_time_t totalLen = libvlc_media_player_get_length(w->vlc_mediaPlayer);libvlc_time_t totalLenSec = totalLen / 1000;int thh, tmm, tss;thh = lenSec / 3600;tmm = (lenSec % 3600) / 60;tss = (lenSec % 60);QTime time(thh, tmm, tss);w->ui.lbCurTime->setText(time.toString("hh:mm:ss"));thh = totalLenSec / 3600;tmm = (totalLenSec % 3600) / 60;tss = (totalLenSec % 60);QTime TotalTime(thh, tmm, tss);w->ui.lbTotalTime->setText(TotalTime.toString("hh:mm:ss"));double pos = (double)lenSec / totalLenSec * 100;w->ui.horizontalSlider->setValue(pos);}break;case libvlc_MediaPlayerEndReached:qDebug() << "VLC播放完毕.";break;case libvlc_MediaPlayerStopped:qDebug() << "VLC停止播放";break;case libvlc_MediaPlayerPlaying:qDebug() << "VLC开始播放";break;case libvlc_MediaPlayerPaused:qDebug() << "VLC暂停播放";break;}
}

更多参考:

libVLC 事件机制-CSDN博客

libVLC windows开发环境搭建-CSDN博客

libVLC 元数据-CSDN博客

libVLC 添加图片和文本水印-CSDN博客

libVLC 音频输出设备切换-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/798954.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java | Leetcode Java题解之第16题最接近的三数之和

题目&#xff1a; 题解&#xff1a; class Solution {public int threeSumClosest(int[] nums, int target) {Arrays.sort(nums);int n nums.length;int best 10000000;// 枚举 afor (int i 0; i < n; i) {// 保证和上一次枚举的元素不相等if (i > 0 && nums…

【精品整理】最新数据安全评估标准合集

最新数据安全评估标准合集&#xff0c;以下是资料的目录&#xff0c;共12份。如需下载&#xff0c;请前往星球查阅和获取&#xff1a;https://t.zsxq.com/18JrHhWtQ 1、网络安全标准实践指南 2、数据安全风险评估方法 3、个人信息安全影响评估指南 4、数据出境安全评估指南 5、…

HAL STM32 定时器PWM DMA输出方式

HAL STM32 定时器PWM DMA输出方式 &#x1f9e8;遗留问题&#xff1a;当配置RCR重复计数器&#xff0c;配置为2时&#xff0c;在定义了3组PWM参数情况下&#xff0c;只能输出第二组参数的PWM波形。&#xff08;HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_1, aCCValue_Buff…

模块化——如何导入模块?(内置模块与自定义模块)

在Node.js中&#xff0c;要导入另一个模块&#xff0c;我们可以使用require函数。这个函数接受一个文件路径参数&#xff0c;并返回导入的模块。 一、require使用注意事项&#xff1a; (1)自己创建的模块&#xff0c;导入时建议写相对路径&#xff0c;不能省略./和../ //我把…

golang web 开发 —— gin 框架 (gorm 链接 mysql)

目录 1. 介绍 2. 环境 3. gin 3.1 gin提供的常见路由 3.2 gin的分组 main.go router.go 代码结构 3.3 gin 提供的Json方法 main.go route.go common.go user.go order.go 3.4 gin框架下如何获取传递来的参数 第一种是GET请求后面直接 /拼上传递的参数 第二种是…

【Lavavel框架】——各目录作用的介绍

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

深入理解C语言:函数栈帧的秘密

文章目录 深入理解C语言&#xff1a;函数栈帧的秘密什么是栈帧&#xff08;Stack Frame&#xff09;&#xff1f;栈帧的创建栈帧的销毁栈帧调试栈帧的工作原理栈帧的实际例子结论 深入理解C语言&#xff1a;函数栈帧的秘密 在软件开发的世界里&#xff0c;函数是构建程序的基本…

css anminate 加载中三个点点动态出现

期待效果&#xff1a; 核心代码&#xff1a; css3 anminate方法 //html <div>加载中<span id"dot">...</span></div>//css <style>   #dot {display: inline-block;width: 1.5em;vertical-align: bottom;overflow: hidden;animati…

NLopt

非线性优化–NLopt (nonlinear optimization)是一个免费的开源的库&#xff0c;提供了很多种非线性优化算的使用接口。 1、其中非常大的优势就是提供多种支持的语言&#xff0c;包括C/ C/ Julia/ Python/ R/ Fortran/ Lua/ OCaml/ Octave等都支持 1. 区别 **COBYLA&#xff0…

MacOS 升级14.4.1后vscode无法远程连接

今天上班第一天&#xff0c;开始提示MacOS可以升级&#xff0c;顺手就点击了升级重启&#xff0c;版本显示 14.4.1 (23E224) 同时今天vscode升级到了1.88 此时大多数的VSCODE远程服务器无法连接&#xff0c;不管用不用VPN都不可以&#xff0c;报错大致包括如下信息 hostname …

xilinx 7系列fpga上电配置

一、前言 Xilinx FPGA通过加载比特流到内部存储单元来进行配置。 Xilinx FPGA存在两种数据配置路径&#xff0c;一种是满足最小引脚需求的串行路径&#xff0c;一种是可用8位、16位或32位来连接到行业的高性能通用接口&#xff0c;如处理器&#xff0c;8位或者16位并行的闪存…

在linux服务器上安装anaconda

遇到问题&#xff1a; 在linux服务器中查看当前有哪些虚拟环境&#xff0c;conda环境用不了&#xff0c;anaconda没有安装&#xff0c;所以要在linux服务器中安装虚拟环境 解决步骤如下&#xff1a; 1.首先下载anaconda的Linux版本的安装包 方法1&#xff1a;官网下载&#…

推荐一个好用的数据库映射架构

SqlSugar ORM 优点: SqlSugar 是 .NET 开源 ORM 框架,由 Fructose 大数据技术团队维护和更新,是开箱即用最易用的 ORM 优点: 【低代码】【高性能】【超简单】【功能综合】【多数据库兼容】【适用产品】 支持 .NET .NET framework.net core3.1.ne5.net6.net7.net8 .net…

在Vue 3中实现页面锁屏功能

可以通过创建一个全屏遮罩层来实现。当需要锁屏时&#xff0c;显示这个遮罩层&#xff1b;当解锁时&#xff0c;隐藏它。下面是一个简单的示例来说明如何实现这个功能&#xff1a; 创建锁屏组件 首先&#xff0c;我们创建一个锁屏组件&#xff08;LockScreen.vue&#xff09;…

【蓝桥杯嵌入式】Cubemx新建工程引脚配置与点亮LED

【蓝桥杯嵌入式】Cubemx新建工程引脚配置与点亮LED cubemx基础配置LED 引脚配置按键配置按键引脚配置定时器扫描配置 工程管理配置点亮LED程序设计keil配置与程序下载 参考博文1&#xff1a;STM32 | 利用STM32CubeMX初始化一个STM32工程 参考博文1&#xff1a;点亮LED灯&#x…

已解决RocketMQ连接报错RemotingConnectException: connect to异常的正确解决方法,亲测有效!!!

已解决RocketMQ连接报错RemotingConnectException: connect to异常的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 问题分析 在使用Apache RocketMQ进行分布式消息传递时&#xff0c;可能会遇到org.apache.rocketmq.remoting.exception.RemotingCon…

【面经】软件开发工程师-后端方向1

面经整理系列&#xff1a; 【面经】软件开发工程师-后端方向1 文章目录 岗位与面经基础1&#xff1a;数据库 & 网络基础2&#xff1a;系统 & 语法模板3&#xff1a;算法 & 项目 岗位与面经 岗位介绍 JD: 美团-软件开发工程师-后端方向-1小时左右 金融服务平台 技…

【C#】版本号

&#x1f4bb; 代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace ConsoleApp16 {internal class Program{static void Main(string[] args){Version version01 new Version("4.0.0…

LeetCode 1315. 祖父节点值为偶数的节点和

解题思路 该节点的父节点的父节点是偶数&#xff0c;则sumsum该节点&#xff0c; 这道题的思路可以等价为该节点为偶数&#xff0c;并且子节点的子节点存在&#xff0c; 则sumsum该节点的子节点的子节点。 相关代码 /*** Definition for a binary tree node.* public class …

Web后端搭建

目录 一 搭建服务器端 1.1安装服务器软件 1.2检查环境是否配置 1.3安装Tomcat 二 创建并发Web项目 2.1创建一个java项目 三 创建Servlet 前端程序如何才能访问到后端程序呢&#xff0c;这时候我们就需要web服务器来解决&#xff1a;将后端程序部署到服务器中&#xff0c…