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)
Remote desktop interface.
void sigUpdateRect(const QRect &r, const QImage &image)
Notify the CFrmView update image.
virtual void slotClipBoardChanged()=0
Be called when the clip board change.
virtual int OnClean() override
Clean.
virtual int WakeUp() override
Wake up backend thread(background thread).
virtual OnInitReturnValue OnInit() override
Initialization.
void sigRunning()
Emitted when the plugin is successfully started.
void sigFinished()
Successful stopped signal.