3#include <QLoggingCategory>
4#include <QMediaDevices>
7#include <QDesktopServices>
11#include "BackendPlayer.h"
13static Q_LOGGING_CATEGORY(log,
"Player.Backend")
18 , m_bScreenShot(false)
23 qDebug(log) << Q_FUNC_INFO;
25 m_pParameters = qobject_cast<CParameterPlayer*>(pOperate->GetParameter());
28 check = connect(&m_VideoSink, &QVideoSink::videoFrameChanged,
29 pOperate->GetVideoSink(), &QVideoSink::videoFrameChanged);
34 &m_VideoSink, SIGNAL(videoFrameChanged(
const QVideoFrame&)),
35 this, SLOT(slotVideoFrameChanged(QVideoFrame)));
40 &m_AudioBufferOutput, &QAudioBufferOutput::audioBufferReceived,
41 this, [&](
const QAudioBuffer &buffer){
43 if(QMediaRecorder::RecordingState != m_Recorder.recorderState())
45 bool bRet = m_AudioBufferInput.sendAudioBuffer(buffer);
49 qDebug(log) <<
"m_AudioBufferInput.sendAudioBuffer fail";
55 check = connect(pOperate, &COperatePlayer::sigStart,
56 this, [&](
bool bStart){
64 pOperate, &COperatePlayer::sigPause,
65 this, [&](
bool bPause){
66 switch (m_pParameters->GetType()) {
67 case CParameterPlayer::TYPE::Camera:
69 if(m_pCamera->isActive())
73 if(!m_pCamera->isActive())
77 case CParameterPlayer::TYPE::Url:
79 if(QMediaPlayer::PlayingState == m_Player.playbackState())
83 if(QMediaPlayer::PausedState == m_Player.playbackState())
92 &m_Player, SIGNAL(positionChanged(qint64)),
93 this, SLOT(slotPositionChanged(qint64)));
96 &m_Player, SIGNAL(durationChanged(qint64)),
97 this, SLOT(slotDurationChanged(qint64)));
99 check = connect(pOperate, SIGNAL(sigChangePosition(qint64)),
100 &m_Player, SLOT(setPosition(qint64)));
102 check = connect(m_pParameters, &CParameterPlayer::sigEnableAudioInput,
103 this, &CBackendPlayer::slotEnableAudioInput);
105 check = connect(m_pParameters, &CParameterPlayer::sigEnableAudioOutput,
106 this, &CBackendPlayer::slotEnableAudioOutput);
110 &m_Player, &QMediaPlayer::errorOccurred,
111 this, [&](QMediaPlayer::Error error,
const QString &errorString){
112 qCritical(log) <<
"Player error occurred:" << error << errorString
113 << m_Player.source();
115 emit sigError(error, errorString);
118 check = connect(&m_Player, &QMediaPlayer::playbackStateChanged,
119 this, [&](QMediaPlayer::PlaybackState state){
120 qDebug(log) <<
"Player state changed:" << state
121 << m_Player.source();
123 if(QMediaPlayer::PlaybackState::PlayingState == state) {
130 if(-1 == m_Player.activeAudioTrack()
131 && m_Player.audioTracks().size() > 0) {
132 m_Player.setActiveAudioTrack(0);
134 if(-1 == m_Player.activeVideoTrack()
135 && m_Player.videoTracks().size() > 0) {
136 m_Player.setActiveVideoTrack(0);
138 if(m_pParameters->GetSubtitle()) {
139 if(m_Player.subtitleTracks().size() > 0) {
141 for(
int i = 0; i < m_Player.subtitleTracks().size(); i++) {
142 auto m = m_Player.subtitleTracks().at(i);
143 QVariant v = m.value(QMediaMetaData::Language);
144 if(!v.isValid())
continue;
145 if(v.toLocale().language() == QLocale::AnyLanguage
146 || v.toLocale().language() == QLocale::system().language()) {
151 m_Player.setActiveSubtitleTrack(nIndex);
159 check = connect(&m_Player, &QMediaPlayer::errorOccurred,
160 pOperate, &COperatePlayer::slotPlaybackError);
162 check = connect(&m_Player, &QMediaPlayer::playbackStateChanged,
163 pOperate, &COperatePlayer::slotPlaybackStateChanged);
165 check = connect(
this, SIGNAL(sigPositionChanged(qint64,qint64)),
166 pOperate, SLOT(slotPositionChanged(qint64,qint64)));
169 check = connect(&m_Recorder, &QMediaRecorder::recorderStateChanged,
170 pOperate, &COperatePlayer::slotRecordStateChanged);
175 check = connect(pOperate, &COperatePlayer::sigScreenShot,
177 m_bScreenShot =
true;
183CBackendPlayer::~CBackendPlayer()
185 qDebug(log) << Q_FUNC_INFO;
190 qDebug(log) << Q_FUNC_INFO;
192 return OnInitReturnValue::NotUseOnProcess;
197 qDebug(log) << Q_FUNC_INFO;
208void CBackendPlayer::slotStart()
210 qDebug(log) << Q_FUNC_INFO;
211 slotEnableAudioInput(m_pParameters->GetEnableAudioInput());
212 slotEnableAudioOutput(m_pParameters->GetEnableAudioOutput());
214 switch (m_pParameters->GetType()) {
215 case CParameterPlayer::TYPE::Camera: {
217 const QList<QCameraDevice> cameras = QMediaDevices::videoInputs();
219 || -1 > m_pParameters->GetCamera()
220 || m_pParameters->GetCamera() > QMediaDevices::videoInputs().size())
222 m_pCamera =
new QCamera(cameras.at(m_pParameters->GetCamera()));
223 emit sigServerName(cameras.at(m_pParameters->GetCamera()).description());
226 m_CaptureSession.setVideoSink(&m_VideoSink);
227 m_CaptureSession.setCamera(m_pCamera);
232 case CParameterPlayer::TYPE::Url: {
233 QString szFile = m_pParameters->GetUrl();
234 QFileInfo fi(szFile);
235 emit sigServerName(fi.fileName());
238 url = QUrl::fromLocalFile(szFile);
239 m_Player.setSource(url);
240 m_Player.setVideoSink(&m_VideoSink);
242 if(m_pParameters->m_Record.GetEnableAudio())
243 m_Player.setAudioBufferOutput(&m_AudioBufferOutput);
247 m_nPosition = m_Player.position();
248 m_nDuration = m_Player.duration();
256void CBackendPlayer::slotStop()
258 qDebug(log) << Q_FUNC_INFO;
259 switch (m_pParameters->GetType()) {
260 case CParameterPlayer::TYPE::Camera:
263 m_CaptureSession.setVideoSink(
nullptr);
265 case CParameterPlayer::TYPE::Url:
267 m_Player.setVideoSink(
nullptr);
268 m_Player.setVideoOutput(
nullptr);
284void CBackendPlayer::slotRecord(
bool bRecord)
286 qDebug(log) << Q_FUNC_INFO << bRecord;
289 if(QMediaRecorder::StoppedState != m_Recorder.recorderState()) {
293 auto &record = m_pParameters->m_Record;
294 switch (m_pParameters->GetType()) {
295 case CParameterPlayer::TYPE::Camera: {
296 record >> m_Recorder;
297 m_CaptureSession.setRecorder(&m_Recorder);
301 case CParameterPlayer::TYPE::Url: {
302 record >> m_Recorder;
303 if(record.GetEnableAudio()) {
304 m_CaptureSession.setAudioBufferInput(&m_AudioBufferInput);
306 qDebug(log) <<
"Record: disable audio";
307 if(record.GetEnableVideo())
308 m_CaptureSession.setVideoFrameInput(&m_VideoFrameInput);
310 qDebug(log) <<
"Record: disable video";
311 m_CaptureSession.setRecorder(&m_Recorder);
318#ifndef HAVE_QVideoWidget
319 emit sigRecordVideo(bRecord, m_pParameters->m_Record.GetVideoFrameRate());
324 if(QMediaRecorder::StoppedState != m_Recorder.recorderState()) {
326 m_CaptureSession.setRecorder(
nullptr);
327 m_CaptureSession.setVideoFrameInput(
nullptr);
328 m_CaptureSession.setAudioBufferInput(
nullptr);
337void CBackendPlayer::slotVideoFrameChanged(
const QVideoFrame &frame)
339#ifndef HAVE_QVideoWidget
340 if(m_Video.width() != frame.width()
341 || m_Video.height() != frame.height())
343 m_Video = QRect(0, 0, frame.width(), frame.height());
344 emit sigSetDesktopSize(m_Video.width(), m_Video.height());
346 QImage img(frame.width(), frame.height(), QImage::Format_ARGB32);
347 QPainter painter(&img);
348 const QVideoFrame::PaintOptions option;
349 QVideoFrame f = frame;
350 f.paint(&painter, m_Video, option);
356 m_bScreenShot =
false;
357 QImage image = frame.toImage();
359 qCritical(log) <<
"frame.toImage() fail";
361 QString szFile = m_pParameters->m_Record.GetImageFile(
true);
362 if(!image.save(szFile,
"PNG"))
364 qCritical(log) <<
"Capture image save to file fail." << szFile;
367 qDebug(log) <<
"Capture image to file:" << szFile;
368 qDebug(log) <<
"End action:" << m_pParameters->m_Record.GetEndAction();
369 switch(m_pParameters->m_Record.GetEndAction())
371 case CParameterRecord::ENDACTION::OpenFile: {
372 bool bRet = QDesktopServices::openUrl(QUrl::fromLocalFile(szFile));
374 qCritical(log) <<
"Fail: Open capture image file" << szFile;
377 case CParameterRecord::ENDACTION::OpenFolder: {
378 QFileInfo fi(szFile);
379 QDesktopServices::openUrl(QUrl::fromLocalFile(fi.absolutePath()));
388#if defined(HAVE_QT6_RECORD) && defined(HAVE_QVideoWidget)
389 if(QMediaRecorder::RecordingState == m_Recorder.recorderState()) {
390 bool bRet = m_VideoFrameInput.sendVideoFrame(frame);
394 qDebug(log) <<
"m_VideoFrameInput.sendVideoFrame fail";
400void CBackendPlayer::slotEnableAudioInput(
bool bEnable)
402 if(bEnable && -1 < m_pParameters->GetAudioInput()
403 && m_pParameters->GetAudioInput() < QMediaDevices::audioInputs().size()) {
404 m_AudioInput.setDevice(QMediaDevices::audioInputs()
405 .at(m_pParameters->GetAudioInput()));
406 m_AudioInput.setMuted(m_pParameters->GetAudioInputMuted());
407 m_AudioInput.setVolume(m_pParameters->GetAudioInputVolume());
408 m_CaptureSession.setAudioInput(&m_AudioInput);
410 bool check = connect(m_pParameters,
411 &CParameterPlayer::sigAudioInputMuted,
412 &m_AudioInput, &QAudioInput::setMuted);
414 check = connect(m_pParameters, &CParameterPlayer::sigAudioInputVolume,
415 &m_AudioInput, &QAudioInput::setVolume);
417 check = connect(m_pParameters, &CParameterPlayer::sigAudioInput,
418 this, [&](
int nIndex) {
420 && nIndex < QMediaDevices::audioInputs().size())
421 m_AudioInput.setDevice(
422 QMediaDevices::audioInputs().at(nIndex));
426 qDebug(log) <<
"m_CaptureSession: disable audio input";
427 m_CaptureSession.setAudioInput(
nullptr);
431void CBackendPlayer::slotEnableAudioOutput(
bool bEnable)
433 if(bEnable && (-1 < m_pParameters->GetAudioOutput()
434 && m_pParameters->GetAudioOutput()
435 < QMediaDevices::audioInputs().size()))
437 m_AudioOutput.setDevice(
438 QMediaDevices::audioOutputs()
439 .at(m_pParameters->GetAudioOutput()));
440 m_AudioOutput.setMuted(m_pParameters->GetAudioOutputMuted());
441 m_AudioOutput.setVolume(m_pParameters->GetAudioOutputVolume());
442 m_AudioOutput.disconnect();
443 bool check = connect(m_pParameters,
444 &CParameterPlayer::sigAudioOutputMuted,
445 &m_AudioOutput, &QAudioOutput::setMuted);
447 check = connect(m_pParameters, &CParameterPlayer::sigAudioOutputVolume,
448 &m_AudioOutput, &QAudioOutput::setVolume);
450 check = connect(m_pParameters, &CParameterPlayer::sigAudioOutput,
451 this, [&](
int nIndex) {
453 && nIndex < QMediaDevices::audioOutputs().size())
454 m_AudioOutput.setDevice(
455 QMediaDevices::audioOutputs().at(nIndex));
458 switch (m_pParameters->GetType()) {
459 case CParameterPlayer::TYPE::Camera:
460 m_CaptureSession.setAudioOutput(&m_AudioOutput);
462 case CParameterPlayer::TYPE::Url:
463 m_Player.setAudioOutput(&m_AudioOutput);
469 m_Player.setAudioOutput(
nullptr);
470 m_CaptureSession.setAudioOutput(
nullptr);
471 m_AudioOutput.disconnect();
475void CBackendPlayer::slotPositionChanged(qint64 pos)
480 qint64 currentInfo = pos / 1000;
481 qint64 duration = m_nDuration / 1000;
483 if (currentInfo || duration) {
484 QTime currentTime((currentInfo / 3600) % 60, (currentInfo / 60) % 60, currentInfo % 60,
485 (currentInfo * 1000) % 1000);
486 QTime totalTime((duration / 3600) % 60, (duration / 60) % 60, duration % 60,
487 (duration * 1000) % 1000);
488 QString format =
"mm:ss";
491 szStr = currentTime.toString(format) +
" / " + totalTime.toString(format);
492 emit sigPositionChanged(m_nPosition, m_nDuration);
497void CBackendPlayer::slotDurationChanged(qint64 duration)
500 m_nDuration = duration;
503void CBackendPlayer::mousePressEvent(QMouseEvent *event)
508void CBackendPlayer::mouseReleaseEvent(QMouseEvent *event)
513void CBackendPlayer::mouseMoveEvent(QMouseEvent *event)
518void CBackendPlayer::wheelEvent(QWheelEvent *event)
523void CBackendPlayer::keyPressEvent(QKeyEvent *event)
528void CBackendPlayer::keyReleaseEvent(QKeyEvent *event)
533void CBackendPlayer::InputMethodEvent(QInputMethodEvent *event)
void sigUpdateRect(const QRect &r, const QImage &image)
通知视图,图像更新
virtual void slotClipBoardChanged()=0
当剪切板发生改变时调用
virtual int OnClean() override
清理
virtual int WakeUp() override
唤醒后台线程。
virtual OnInitReturnValue OnInit() override
初始化
void sigRunning()
当插件开始成功后触发。仅由插件触发
void sigFinished()
停止成功信号。仅由插件触发