384 lines
9.8 KiB
C++
384 lines
9.8 KiB
C++
#ifndef RM_PLAYER_H
|
|
#define RM_PLAYER_H
|
|
|
|
#include <QObject>
|
|
#include <qslider.h>
|
|
#include <QElapsedTimer>
|
|
|
|
#include "rm_constants.h"
|
|
#include "rm_include.h"
|
|
#include "rm_player_base.h"
|
|
#include "rm_player_zoom.h"
|
|
|
|
|
|
#define DEBUG_RM_PLAYER 0
|
|
#define USE_RM_D2_PLAYER 0
|
|
#define CAPTURE_DEBUG 0
|
|
|
|
class RMVideoItem;
|
|
class RMFrameSlider;
|
|
|
|
#if (MODEL_BBVIEWER)
|
|
class RMEQWidget;
|
|
#endif
|
|
|
|
#define DEBUG_HIGH_SPEED_STOP 0
|
|
#define REMOVE_CLOCK_UPDATE_WHEN_SEEKING 1
|
|
#define STEP_SEEK_DURATION 34
|
|
|
|
|
|
//extern const int g_PlaySpeed1XIndex;
|
|
|
|
#if (MODEL_BBVIEWER)
|
|
#define PLAY_SPEED_COUNT 5
|
|
#elif (RM_MODEL == RM_MODEL_TYPE_TB4000 || RM_MODEL_EMT_KR)
|
|
#define PLAY_SPEED_COUNT 5
|
|
#else
|
|
#define PLAY_SPEED_COUNT 4
|
|
#endif
|
|
extern float g_PlaySpeedList[PLAY_SPEED_COUNT];
|
|
|
|
extern int DEFAULT_SPEED_INDEX;
|
|
|
|
class RMPlayer : public RMPlayerZoom
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
static RMPlayer* instance()
|
|
{
|
|
static RMPlayer * _instance = 0;
|
|
if ( _instance == NULL ) {
|
|
_instance = new RMPlayer();
|
|
}
|
|
return _instance;
|
|
}
|
|
//#if (USE_LIBRARY_MODE) // 360 DLL
|
|
// static RMPlayer* libraryInstance;
|
|
//#endif //
|
|
#if !(SINGLE_CH_VIEWER)
|
|
// 는 _isSwapped() 와는 별도로 사용자 swap 상태만 확인하기 위해 사용
|
|
bool isSwapped() { return _swaped; }
|
|
#endif
|
|
void stop() override;
|
|
|
|
QString currentTimeString(double* lat, double* lon);
|
|
#if (PENTA_CHANNEL)
|
|
void changeCHMode(RMApp::ChannelMode mode) override;
|
|
#endif
|
|
void updateSpeedForce(qreal speed)
|
|
{
|
|
_speedValue = speed;
|
|
updateSpeed(_speedValue);
|
|
}
|
|
#if !(RM_MODEL == RM_MODEL_TYPE_TB4000)
|
|
void setMuteButton(FMButton* btn) {
|
|
_muteButton = btn;
|
|
}
|
|
#endif // #if !(RM_MODEL == RM_MODEL_TYPE_TB4000)
|
|
void setSlider(QSlider* slider) {
|
|
_slider = slider;
|
|
|
|
// PRESSED -> MOVED -> RELEASED 순서대로 호출 되도록 이벤트 처리해야함
|
|
// 노브가 아닌 지점 CLICK 시에는 Slider는 (Slider)PRESSED 이벤트 만 호출됨 (RMSlider 내부에서 구현)
|
|
// PRESSED 이벤트 발생시 KNOB 가 false 일 경우 released 이벤트 발생하지 않으니 별도의 처리 하지 말아야함
|
|
connect(_slider, SIGNAL(sliderPressedWithKnob(bool)),SLOT(onSliderPress(bool))); // 이벤트 두번씩 발생함
|
|
|
|
connect(_slider, SIGNAL(sliderMoved(int)),SLOT(onSliderMove(int))); // 슬라이더 컨트롤
|
|
connect(_slider, SIGNAL(mouseReleased()),SLOT(onSliderRelease()));
|
|
}
|
|
#if !(RM_MODEL == RM_MODEL_TYPE_TB4000)
|
|
void setVolumeSlider(QSlider* slider) {
|
|
_volumeSlider = slider;
|
|
connect(_volumeSlider, SIGNAL(sliderPressed()), SLOT(onSetVolume()));
|
|
connect(_volumeSlider, SIGNAL(valueChanged(int)), SLOT(onSetVolume()));
|
|
onSetVolume();
|
|
}
|
|
#endif // RM_MODEL_TYPE_TB4000
|
|
|
|
void setSpeedSlider(QSlider* slider, QLabel* label) {
|
|
_speedLabel = label;
|
|
connect(slider, SIGNAL(mouseReleased()),SLOT(onSpeedSliderReleased()));
|
|
connect(slider, SIGNAL(sliderMoved(int)),SLOT(onSpeedSliderMoved(int)));
|
|
}
|
|
|
|
private:
|
|
|
|
// SLIDER 이동중에는 강제 PAUSE
|
|
bool _pauseWhileSeek;
|
|
|
|
QTimer* _captureTimer;
|
|
QTimer* _captureWatcher;
|
|
//#if (SEEK_BY_SLIDER)
|
|
// QTimer* _seekPositionTimer;
|
|
// void startSeekTimer();
|
|
//#endif
|
|
|
|
#if (USE_RM_KEYBOARD_EVENT)
|
|
int _seekAcceleration; // 가속
|
|
QTimer* _seekPressedTimer; // Slider 이동 타이머
|
|
QTimer* _seekReleasedTimer; // Seek Update 타이머
|
|
QTimer* _seekUpdateTimer; // Pressed 중간 Seek Update 타이머
|
|
void startSeekUpdateTimer();
|
|
void stopSeekUpdateTimer() override;
|
|
|
|
bool isSeekProcessing() override
|
|
{
|
|
return (_seekPressedTimer != NULL || _seekReleasedTimer != NULL || _seekUpdateTimer != NULL);
|
|
}
|
|
|
|
//#else
|
|
// QElapsedTimer _stepTimer;
|
|
#endif
|
|
|
|
protected:
|
|
virtual void timerEvent(QTimerEvent *e);
|
|
|
|
public:
|
|
|
|
explicit RMPlayer(QObject *parent = 0);
|
|
|
|
RMVideoItem* getCurrentItem()
|
|
{
|
|
return _currentItem;
|
|
}
|
|
QDateTime currentTime(double* lon = NULL,double* lat = NULL);
|
|
|
|
VIDEO_MODE videoMode()
|
|
{
|
|
return _videoMode;
|
|
}
|
|
|
|
FAV::AVPlayer* playerF()
|
|
{
|
|
return _playerF;
|
|
}
|
|
|
|
QWidget* playWidgetF()
|
|
{
|
|
return _videoOutputF->widget();
|
|
}
|
|
#if ((!SINGLE_CH_VIEWER && !TOGGLE_PLAYER) || DUAL_VIEWER || DUAL_VIDEO_WIDGET)
|
|
QWidget* playWidgetR()
|
|
{
|
|
return _videoOutputR->widget();
|
|
}
|
|
#endif
|
|
|
|
#if !(SINGLE_CH_VIEWER)
|
|
FAV::AVPlayer* playerR()
|
|
{
|
|
return _playerR;
|
|
}
|
|
#endif // #if !(SINGLE_CH_VIEWER)
|
|
|
|
#if (RM_MODEL_360)
|
|
// SWAP 되더라도 메인 Renderer 는 항상 _videoOutputF 임
|
|
FAV::VideoRenderer* mainRenderer() {
|
|
return _videoOutputF;
|
|
}
|
|
FAV::VideoRenderer* renderer360() {
|
|
#if (SINGLE_CH_VIEWER)
|
|
return _videoOutputF;
|
|
#else // SINGLE_CH_VIEWER
|
|
return _swaped ? _videoOutputR : _videoOutputF;
|
|
#endif // SINGLE_CH_VIEWER
|
|
}
|
|
#endif // RM_MODEL_360
|
|
|
|
//void setSliderFrame(RMFrameSlider* frame); // 슬라이더 설정
|
|
#if (MODEL_BBVIEWER)
|
|
void setEQFrame(RMEQWidget* eq);
|
|
#endif
|
|
// 비디오 캡쳐 요청
|
|
bool requestVideoCapture();
|
|
|
|
qreal speedValue()
|
|
{
|
|
return _speedValue;
|
|
}
|
|
#if (SUPPORT_WIDE_MODE)
|
|
/**
|
|
* @brief 현재 재생중인 영상이 WIDE 모드 지원 영상일 경우
|
|
* @return
|
|
*/
|
|
bool itemIsWideMode();
|
|
|
|
/**
|
|
* @brief 현재 재생중인 모드가 WIDE 모드일 경우
|
|
* @return
|
|
*/
|
|
bool isWideMode();
|
|
#endif // SUPPORT_WIDE_MODE
|
|
|
|
#if (RM_TESTING)
|
|
FAV::LibAVFilterVideo* _testFilterF;
|
|
void applyTestFilter(QString filter);
|
|
#endif
|
|
|
|
qint64 titleSeconds; // 슬라이더에 표시된 시간 (Capture 등에서 동기화 처리위해 사용)
|
|
|
|
public slots:
|
|
|
|
void requestVideoCaptureProcess();
|
|
|
|
// Slider Control
|
|
void onSliderPress(bool bKnob);
|
|
void onSliderMove(int value);
|
|
void onSliderRelease();
|
|
|
|
//void onPlotMove(qreal ratio);
|
|
|
|
|
|
// 사용자 정지
|
|
void onUserStop();
|
|
|
|
#if (USE_RM_KEYBOARD_EVENT)
|
|
void onSeekForwardStart();
|
|
void onSeekBackwardStart();
|
|
void onSeekFrameForwardStart();
|
|
#if (PLAY_SYNC_FIX2)
|
|
void onSeekFrameBackwardStart();
|
|
#endif // PLAY_SYNC_FIX2
|
|
void onSeekStepEnd();
|
|
#endif
|
|
|
|
#if (PLAYER_ONLY_LIBRARY_MODE)
|
|
void clear();
|
|
void create();
|
|
#endif // PLAYER_ONLY_LIBRARY_MODE
|
|
|
|
bool prepareForCapture();
|
|
void onCaptureSavedFront(const QString& path);
|
|
|
|
#if !(SINGLE_CH_VIEWER)
|
|
void onCaptureSavedRear(const QString& path);
|
|
void toggleSwap(bool forceEmit = false);
|
|
#endif
|
|
|
|
#if (TRI_CHANNEL || TRI_CHANNEL2)
|
|
void toggleIndoor(bool forceEmit = false); // 후방 <-> 실내
|
|
#endif
|
|
#if (SUPPORT_WIDE_MODE)
|
|
void toggleWide(); // NORMAL <-> WIDE
|
|
#endif // SUPPORT_WIDE_MODE
|
|
|
|
void onSpeedSliderMoved(int position);
|
|
void onSpeedSliderReleased();
|
|
|
|
|
|
private:
|
|
// 재생시간이 AVI:60260 VIDEO(Audio):59281 일 경우
|
|
// 현재 POSITION + step 을
|
|
// 실제 재생시간을 N 분할 하여 사용자가 보기 적합한 간격으로 표시함
|
|
// eg 988.0166667 msec 씩 이동할 경우
|
|
#if (USE_RM_KEYBOARD_EVENT)
|
|
quint64 _stepPosition();
|
|
//#else
|
|
// quint64 _stepPosition(int step=1); // +1,-1
|
|
#endif
|
|
bool _isLastStep();
|
|
|
|
|
|
// 이벤트 블럭처리함
|
|
void blockEvents(int msec,bool b_show_indicator = false);
|
|
|
|
// pause 된 상태에서도 positionChanged 가 계속호출되어 방지용
|
|
// int timeToSliderValue(qint64 time);
|
|
qint64 ratioToSliderValue(qreal ratio);
|
|
|
|
QString _captureDir;
|
|
QList<QString>* _captureFileList;
|
|
|
|
|
|
// 통합관리 + 화면갱신을 위한 seek 구분
|
|
void seek(qint64 pos,bool refresh) override;
|
|
|
|
// 정지된 상태에서 SEEK 를 통해 화면 갱신
|
|
void updatePausedScreen();
|
|
|
|
void seekFrontOnly(qint64 pos,bool refresh);
|
|
#if !(SINGLE_CH_VIEWER)
|
|
void seekRearOnly(qint64 pos,bool refresh);
|
|
#endif
|
|
|
|
// 후방만 갱신
|
|
#if (!(SINGLE_CH_VIEWER || TOGGLE_PLAYER) || PENTA_CHANNEL)
|
|
void updatePausedScreenRearOnly();
|
|
#endif
|
|
void updatePausedScreenFrontOnly();
|
|
void clearCaptureTimer();
|
|
void clearCaptureWatcher();
|
|
|
|
//void clearSliderReleaseTimer();
|
|
|
|
// Rear 는 V+H Flip 모두 지원
|
|
void updateRearFlip();
|
|
#if (RM_MODEL == RM_MODEL_TYPE_TELEBIT)
|
|
void updateFrontFlip();
|
|
#endif
|
|
|
|
// 메인 clock 과 각 player 의 clock 동기화
|
|
void clear_seek_timer();
|
|
void sync_clock();
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
#if (USE_RM_KEYBOARD_EVENT)
|
|
void onSeekUpdate(); // 업데이트 후 타이머 제거하지 않음
|
|
void onSeekLastUpdate(); // 업데이트 후 타이머 제거
|
|
void onSeekPressed();
|
|
#endif
|
|
|
|
#if (CAPTURE_DEBUG)
|
|
void onSeekCapture();
|
|
void onImageCaptured(const QImage& image);
|
|
void onCaptureFailed();
|
|
#endif
|
|
|
|
//#if !(FORCE_SINGLE_PLAYER)
|
|
// 이벤트 블럭 해제 (전후방 swap 중에 별도 이벤트 받지 못하도록 처리)
|
|
void onReleaseBlockEvent();
|
|
//#endif
|
|
|
|
// 캡쳐 대기 완료
|
|
void onReadyForCapture();
|
|
|
|
// 캡쳐 실패
|
|
void onFailToCapture();
|
|
|
|
|
|
|
|
#if (PENTA_CHANNEL)
|
|
void onUpdateCHMode() override;
|
|
#endif // PENTA_CHANNEL
|
|
|
|
|
|
// 동기화 시작 타이머
|
|
void on_sync_timer_restarted();
|
|
|
|
// 처음으로 이동
|
|
void onPlayRestart();
|
|
//----------------------------------------------------------------------------------------------
|
|
signals:
|
|
|
|
|
|
void videoCaptureDone(QList<QString>* list);
|
|
void swapChanged(bool swap);
|
|
|
|
|
|
|
|
#if (H265_SUPPORT)
|
|
void show_indicator(bool show);
|
|
#endif
|
|
|
|
void cancelFullScreen();
|
|
|
|
void userStop();
|
|
};
|
|
|
|
|
|
|
|
#endif // RM_PLAYER_H
|