多t体支持是Qt不可或缺的一部分。但是Qt除了提供直观的GUI界面之外,它还提供访问摄像头和收音机功能所需的API。这使得我们可以完全用Qt自身,不用第三方库就可以写一个视频播放器或者音乐播放器。这对于一些入门者来说似乎很有魅力,我本人在接触到Qt之后就用多媒体技术编写了一个音乐播放器,那时候的我还编写了一个简易版的QQ,装在了女友和自己电脑上。
在Qt多媒体(MultiMedia)中存在两个大的模块——Qt Multimedia,提供了针对音视频的底层API;Qt Multimedia Widgets,提供了简易直观的多媒体窗体。在使用时,需要包含这两个模块对应的头文件,当然还是建议用到什么包含什么。
#include
#include
对于Qt pro工程的话,需要将支持添加在Qt的pro文件中:
QT += multimedia multimediawidgets
对于windows VS用户,你需要在Qt VS tool中勾选上这两个模块支持。
Qt多媒体涉及的类有:
类 |
描述 |
QAudioOutput |
将音频数据发送到音频输出设备 |
QAudioRecorder |
记录来自音频源的媒体内容。 |
QCamera |
访问相机取景器。 |
QCameraImageCapture |
用相机拍摄静止图像。 |
QMediaRecorder |
记录来自摄像机或收音机调谐器源的媒体内容。 |
QMediaPlayer |
从源播放媒体。 |
QMediaPlaylist |
要播放的媒体列表。 |
QRadioTuner |
接入无线电设备。 |
QAbstractVideoSurface |
视频演示的基类。 |
Qt Multimedia提供了一系列音频类,涵盖了音频输入,输出和处理的低级和高级方法。要播放非简单的媒体或音频文件,未压缩的音频,可以使用QMediaPlayer类。该QMediaPlayer类也能够播放视频。压缩音频格式确实取决于操作系统环境,以及用户可能安装了哪些媒体插件。下面的例子显示了简单的播放mp3的方法:
player = new QMediaPlayer;
// ...
player->setMedia(QUrl::fromLocalFile("/Users/me/Music/coolsong.mp3"));
player->setVolume(50);
player->play();
或者通过播放列表播放,甚至是远程(网络)上的歌曲:
player = new QMediaPlayer;
playlist = new QMediaPlaylist(player);
playlist->addMedia(QUrl("http://example.com/myfile1.mp3"));
playlist->addMedia(QUrl("http://example.com/myfile2.mp3"));
// ...
playlist->setCurrentIndex(1);
player->play();
为了将音频记录到文件,可以使用QAudioRecorder类压缩来自输入设备的音频数据并进行记录。
audioRecorder = new QAudioRecorder;
QAudioEncoderSettings audioSettings;
audioSettings.setCodec("audio/amr");
audioSettings.setQuality(QMultimedia::HighQuality);
audioRecorder->setEncodingSettings(audioSettings);
audioRecorder->setOutputLocation(QUrl::fromLocalFile("test.amr"));
audioRecorder->record();
除了上述对声音设备的原始访问之外,QSoundEffect类还提供了一种更高级别的声音播放方式。这些类允许您指定WAV格式文件,然后可以在必要时以低延迟播放。您可以调整播放声音效果的循环次数,以及效果的音量(或静音)。
QAudioProbe类允许您监视正在由更高级的类,如QMediaPlayer,QCamera和QAudioRecorder播放或录制的音频数据。您可以用setSource简单地指向这些类的对象,并在音频缓冲区接收它们。这对于一些音频处理任务很有用,尤其是对于可视化或调整增益。注意,您无法修改缓冲区,缓冲区的到达时间可能与媒体管道处理缓冲区的时间略有不同。
audioRecorder = new QAudioRecorder;
QAudioEncoderSettings audioSettings;
audioSettings.setCodec("audio/amr");
audioSettings.setQuality(QMultimedia::HighQuality);
audioRecorder->setEncodingSettings(audioSettings);
audioRecorder->setOutputLocation(QUrl::fromLocalFile("test.amr"));
audioProbe = new QAudioProbe(this);
if (audioProbe->setSource(audioRecorder)) {
// Probing succeeded, audioProbe->isValid() should be true.
connect(audioProbe, SIGNAL(audioBufferProbed(QAudioBuffer)),
this, SLOT(calculateLevel(QAudioBuffer)));
}
audioRecorder->record();
// Now audio buffers being recorded should be signaled
// by the probe, so we can do things like calculating the
// audio power level, or performing a frequency transform
Qt Multimedia提供了用于对音频输入和输出设备进行原始访问的类,允许应用程序从麦克风等设备接收原始数据,并将原始数据写入扬声器或其他输出设备。通常,这些类不执行任何音频解码或其他处理,但是它们可以支持不同类型的原始音频数据。
QAudioOutput类提供了原始音频数据输出,而QAudioInput提供原始音频数据输入。这两类都有可调节的缓冲区和延迟,因此它们既适用于低延迟的用例(如游戏或VOIP)又适用于高延迟的用例(如音乐播放)。可用的硬件确定哪些音频输出和输入可用。
在某些情况下,您可能希望解码压缩的音频文件并自己做进一步处理(例如,混合多个样本或使用自定义数字信号处理算法)。QAudioDecoder支持解码来自QIODevice实例的本地文件或数据流。
QAudioFormat desiredFormat;
desiredFormat.setChannelCount(2);
desiredFormat.setCodec("audio/x-raw");
desiredFormat.setSampleType(QAudioFormat::UnSignedInt);
desiredFormat.setSampleRate(48000);
desiredFormat.setSampleSize(16);
QAudioDecoder *decoder = new QAudioDecoder(this);
decoder->setAudioFormat(desiredFormat);
decoder->setSourceFilename("level1.mp3");
connect(decoder, SIGNAL(bufferReady()), this, SLOT(readBuffer()));
decoder->start();
// Now wait for bufferReady() signal and call decoder->read()
Qt多媒体提供用于播放和处理视频数据的高级C ++类和低级C ++类。这些类中的某些类也与相机和音频类别重叠,这可能很有用。
与音频类似,您可以使用QMediaPlayer类简单的解码视频文件,并使用QVideoWidget,QGraphicsVideoItem或自定义类显示它。
player = new QMediaPlayer;
playlist = new QMediaPlaylist(player);
playlist->addMedia(QUrl("http://example.com/myclip1.mp4"));
playlist->addMedia(QUrl("http://example.com/myclip2.mp4"));
videoWidget = new QVideoWidget;
player->setVideoOutput(videoWidget);
videoWidget->show();
playlist->setCurrentIndex(1);
player->play();
或者,用QGraphicsVideoItem显示它:
player = new QMediaPlayer(this);
QGraphicsVideoItem *item = new QGraphicsVideoItem;
player->setVideoOutput(item);
graphicsView->scene()->addItem(item);
graphicsView->show();
player->setMedia(QUrl("http://example.com/myclip4.ogv"));
player->play();
Qt Multimedia提供了许多底层类,使处理视频帧变得更加容易。这些类主要用于编写处理视频或摄像机视频帧的代码,QVideoFrame类封装了视频帧允许内容被映射到系统内存,用于进一步处理,而类QAbstractVideoSurface允许您接收从这些QMediaPlayer和QCamera发送来的视频帧。可以通过下面的框架实现一个自定义接受类MyVideoSurface。然后在player时调用player->setVideoOutput(myVideoSurface)。
class MyVideoSurface : public QAbstractVideoSurface
{
QList supportedPixelFormats(
QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const
{
Q_UNUSED(handleType);
// Return the formats you will support
return QList() << QVideoFrame::Format_RGB565;
}
bool present(const QVideoFrame &frame)
{
Q_UNUSED(frame);
// Handle the frame and do your processing
return true;
}
};
您可以将QMediaRecorder类与其他类结合使用,以将视频录制到磁盘。主要是与相机一起使用,因此有关更多信息,参见下面的相机描述。
当使用诸如QMediaPlayer,QMediaRecorder或QCamera之类的其他类时,可以使用QVideoProbe类访问这些类的视频帧。创建高级媒体类后,可以通过setSource指向该实例。这对于在正常渲染视频时执行一些视频处理任务(例如条形码识别或对象检测)很有用。同样的,您不能使用此类影响视频帧,另外,它们的到达时间可能与渲染时间略有不同。
camera = new QCamera;
viewfinder = new QCameraViewfinder();
camera->setViewfinder(viewfinder);
camera->setCaptureMode(QCamera::CaptureVideo);
videoProbe = new QVideoProbe(this);
if (videoProbe->setSource(camera)) {
// Probing succeeded, videoProbe->isValid() should be true.
connect(videoProbe, SIGNAL(videoFrameProbed(QVideoFrame)),
this, SLOT(detectBarcodes(QVideoFrame)));
}
camera->start();
// Viewfinder frames should now also be emitted by
// the video probe, even in still image capture mode.
// Another alternative is to install the probe on a
// QMediaRecorder connected to the camera to get the
// recorded frames, if they are different from the
// viewfinder frames.
Qt MultiMedia API提供了许多与摄像头相关的类,因此您可以从移动设备摄像头或网络摄像头访问图像和视频。在使用相机API之前,您应该检查相机在运行时是否可用。如果没有,则可以例如在应用程序中禁用与相机相关的功能。要在代码中执行此检查,请使用QCameraInfo :: availableCameras()函数,如以下示例所示:
bool checkCameraAvailability()
{
if (QCameraInfo::availableCameras().count() > 0)
return true;
else
return false;
}
确定摄像机是否可用后,使用QCamera类访问它。当有多个摄像机可用时,您可以指定要使用的摄像机。
QList cameras = QCameraInfo::availableCameras();
foreach (const QCameraInfo &cameraInfo, cameras) {
if (cameraInfo.deviceName() == "mycamera")
camera = new QCamera(cameraInfo);
}
您还可以通过摄像机在系统上的物理位置而不是设备ID选择摄像机。这在经常具有前置和后置摄像头的移动设备上很有用。
camera = new QCamera(QCamera::FrontFace);
如果未指定设备ID和位置,则将使用默认摄像机。在台式机平台上,默认相机由用户在系统设置中设置。在移动设备上,后置摄像头通常是默认摄像头。你可以在枚举QCameraInfo :: defaultCamera得到有关使用默认的摄像头信息。
尽管并非绝对必要,但能够看到相机所指向的位置通常很有用。大多数数码相机允许以较低的分辨率(通常最大为相机显示屏的尺寸)从相机传感器馈送图像,因此您可以以较低分辨率拍摄视频,然后切换到较慢但较高分辨率的模式以拍摄照片。您的选择取决于您使用的是Widgets还是QGraphicsView。当是Widgets时,使用QCameraViewfinder类,当是 QGraphicsView显示控件时,使用QGraphicsVideoItem。
camera = new QCamera;
viewfinder = new QCameraViewfinder;
camera->setViewfinder(viewfinder);
viewfinder->show();
camera->start(); // to start the viewfinder
对于高级用法(例如图像检测),还可以从QAbstractVideoSurface派生并将其设置为QCamera对象的取景器。在这种情况下,您将需要自己渲染取景器图像。
camera = new QCamera;
mySurface = new MyVideoSurface;
camera->setViewfinder(mySurface);
camera->start();
// MyVideoSurface::present(..) will be called with viewfinder frames
在移动设备上,取景器图像可能并不总是沿您期望的方向。这些设备上的摄像头传感器通常是横向安装的,而屏幕的自然方向是纵向的。这会导致图像根据设备方向而出现横向或倒置。为了在屏幕上反映用户实际看到的内容,应确保将取景器框架始终旋转到正确的方向,同时考虑到摄像头传感器的方向和当前的显示方向。
// Assuming a QImage has been created from the QVideoFrame that needs to be presented
QImage videoFrame;
QCameraInfo cameraInfo(camera); // needed to get the camera sensor position and orientation
// Get the current display orientation
const QScreen *screen = QGuiApplication::primaryScreen();
const int screenAngle = screen->angleBetween(screen->nativeOrientation(), screen->orientation());
int rotation;
if (cameraInfo.position() == QCamera::BackFace) {
rotation = (cameraInfo.orientation() - screenAngle) % 360;
} else {
// Front position, compensate the mirror
rotation = (360 - cameraInfo.orientation() + screenAngle) % 360;
}
// Rotate the frame so it always shows in the correct orientation
videoFrame = videoFrame.transformed(QTransform().rotate(rotation));
设置取景器并找到可拍照的东西后,要捕获图像,我们需要初始化一个新的QCameraImageCapture对象。然后所需要做的就是启动相机,锁定相机,以使物体对准焦点,并且在发生图像捕捉时设置与取景器相同的条件,捕捉图像,最后解锁相机以准备下一张照片。
imageCapture = new QCameraImageCapture(camera);
camera->setCaptureMode(QCamera::CaptureStillImage);
camera->start(); // Viewfinder frames start flowing
//半按快门按钮
camera->searchAndLock();
//在快门按钮按下
imageCapture->capture();
//在快门按钮上释放
camera->unlock();
如果要录制视频,需要使用QMediaRecorder对象。我们需要像以前一样创建一个相机对象,但是这次同时还创建一个取景器,我们还将初始化一个QMediaRecorder对象。
camera = new QCamera;
recorder = new QMediaRecorder(camera);
camera->setCaptureMode(QCamera::CaptureVideo);
camera->start();
//按下快门按钮
recorder->record();
// 稍后,或再次按下快门
recorder->stop();
可以将来自mediaRecorder的信号连接到插槽,以对录制状态的更改或错误事件做出反应。录制本身从调用mediaRecorder 的record()函数开始,这将导致发出stateChanged()信号。录制过程可以通过record(),stop()和setMuted()接口改变其过程。
聚焦(和缩放)主要由QCameraFocus类管理。QCameraFocus允许开发人员通过FocusMode和FocusPointMode的枚举设置常规策略。FocusMode处理诸如AutoFocus,ContinuousFocus和InfinityFocus之类的设置,而FocusPointMode处理视图内用于自动聚焦模式的各个聚焦区域。FocusPointMode支持面部识别(相机在其中支持),中心对焦和可以指定对焦点的自定义对焦。
有许多设置会影响撞击相机传感器的光量,从而影响最终图像的质量。QCameraExposure类允许您调整这些设置。您可以使用此类来实现一些技术,例如通过锁定曝光参数(使用QCamera :: searchAndLock())来实现高动态范围(HDR)照片,或者通过设置具有小光圈的慢快门速度来实现运动模糊。
在图像处理方面,QCameraImageProcessing类可以对图像进行常见的图像处理。这包括白平衡(或色温),对比度,饱和度,锐化和去噪。大多数相机都支持所有这些设置的自动设置,因此除非用户需要特定设置,否则无需调整它们。
诸如图像捕获和自动聚焦之类的各种操作是异步发生的。只要相机支持,通常可以通过开始新操作来取消这些操作。对于图像捕获,可以通过调用cancelCapture()取消操作。对于自动对焦,可以通过调用QCamera :: unlock(QCamera :: LockFocus)来完成自动曝光或白平衡消除。
Qt多媒体API提供了许多与收音机相关的类,用于控制系统的无线电调谐器,并为无线电台提供对无线电数据系统(RDS)信息的访问。Radio API包含两个单独的组件。收音机调谐器QRadioTuner,用于处理收音机硬件的控制以及调谐。另一个是收音机数据组件,QRadioData,可访问RDS信息。
需要注意,radio实际的支持取决于基础系统,并且仅当系统收音机调谐器支持RDS时才适用。
radio = new QRadioTuner;
connect(radio, SIGNAL(frequencyChanged(int)), this, SLOT(freqChanged(int)));
if (radio->isBandSupported(QRadioTuner::FM)) {
radio->setBand(QRadioTuner::FM);
radio->setFrequency(yourRadioStationFrequency);
radio->setVolume(100);
radio->start();
}
Radio对象在bandChanged(), frequencyChanged(), stereoStatusChanged(), searchingChanged(), signalStrengthChanged(), volumeChanged(), mutedChanged().时都会触发信号,可以用来实现相应的功能。
上述描述和例子中或多多少涉及了Qt Multimedia Widgets的相关类,这里把他们列出来:
QCameraViewfinder |
相机取景器控件 |
QGraphicsVideoItem |
显示由QMediaObject产生的视频的图形项 |
QVideoWidget |
展示媒体对象产生的视频的控件 |
QVideoWidgetControl |
实施视频控件的媒体控件 |
典型应用:
// QCameraViewfinder
camera = new QCamera;
viewfinder = new QCameraViewfinder();
viewfinder->show();
camera->setViewfinder(viewfinder);
imageCapture = new QCameraImageCapture(camera);
camera->setCaptureMode(QCamera::CaptureStillImage);
camera->start();
// QGraphicsVideoItem
player = new QMediaPlayer(this);
QGraphicsVideoItem *item = new QGraphicsVideoItem;
player->setVideoOutput(item);
graphicsView->scene()->addItem(item);
graphicsView->show();
player->setMedia(QUrl("http://example.com/myclip4.ogv"));
player->play();
// QVideoWidget
player = new QMediaPlayer;
playlist = new QMediaPlaylist(player);
playlist->addMedia(QUrl("http://example.com/myclip1.mp4"));
playlist->addMedia(QUrl("http://example.com/myclip2.mp4"));
videoWidget = new QVideoWidget;
player->setVideoOutput(videoWidget);
videoWidget->show();
playlist->setCurrentIndex(1);
player->play();
// QVideoWidgetControl
QVideoWidgetControl *widgetControl = mediaService->requestControl();
layout->addWidget(widgetControl->videoWidget());
这里给出一个比较综合的例子:https://download.csdn.net/download/bjtuwayne/12044747