From 02c3d402ac1cf0172eb40abfdaaa69efc5769361 Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Tue, 10 Mar 2020 18:28:18 +0000 Subject: [PATCH] Convert PlayerVideoRec to std::thread --- playervideorec.cc | 84 +++++++++++++++++++++++++++++++---------------- playervideorec.h | 21 +++++++----- 2 files changed, 69 insertions(+), 36 deletions(-) diff --git a/playervideorec.cc b/playervideorec.cc index b5ffa04..75df889 100644 --- a/playervideorec.cc +++ b/playervideorec.cc @@ -116,6 +116,28 @@ int PlayerVideoRec::shutdown() return 1; } +void PlayerVideoRec::threadStart() +{ + playerThreadMutex.lock(); + threadReqQuit = false; + playerThread = std::thread([this] + { + playerThreadMutex.lock(); + playerThreadMutex.unlock(); + threadMethod(); + }); + playerThreadMutex.unlock(); +} + +void PlayerVideoRec::threadStop() +{ + playerThreadMutex.lock(); + threadReqQuit = true; + playerThreadCond.notify_one(); + playerThreadMutex.unlock(); + playerThread.join(); +} + void PlayerVideoRec::setStartFrame(ULONG startFrame) { ULONG nextiframeNumber; @@ -1008,7 +1030,7 @@ void PlayerVideoRec::call(void* caller) stateMutex.unlock(); } - threadSignalNoLock(); + playerThreadCond.notify_one(); } } @@ -1022,12 +1044,15 @@ void PlayerVideoRec::threadMethod() if ((state == S_FFWD) || (state == S_FBWD)) { - if (video->PTSIFramePlayback()) threadPTSFeedScan(); - else threadFeedScan(); - // if this returns then scan hit one end + bool hitEnd; + if (video->PTSIFramePlayback()) hitEnd = threadPTSFeedScan(); + else hitEnd = threadFeedScan(); + + if (!hitEnd) return; // thread wants to exit normally + if (state == S_FFWD) // scan hit the end. stop { - threadCheckExit(); + if (threadReqQuit) return; Message* m = new Message(); // Must be done after this thread finishes, and must break into master mutex m->to = messageReceiver; m->from = this; @@ -1071,13 +1096,15 @@ void PlayerVideoRec::threadFeedPlay() Buffer threadBuffer; + std::unique_lock ul(playerThreadMutex, std::defer_lock); + while(1) { thisRead = 0; writeLength = 0; thisWrite = 0; - threadCheckExit(); + if (threadReqQuit) return; // If we havn't rescanned for a while.. if ((lastRescan + 60) < time(NULL)) @@ -1127,7 +1154,7 @@ void PlayerVideoRec::threadFeedPlay() startup = false; } - threadCheckExit(); + if (threadReqQuit) return; while(writeLength < thisRead) { @@ -1139,13 +1166,13 @@ void PlayerVideoRec::threadFeedPlay() if (!thisWrite) { // demuxer is full and can't take anymore - threadLock(); - if (!threadActive) { threadUnlock(); threadCheckExit(); } - threadWaitForSignal(); - threadUnlock(); + playerThreadMutex.lock(); + if (threadReqQuit) { playerThreadMutex.unlock(); return; } + playerThreadCond.wait(ul); + playerThreadMutex.unlock(); } - threadCheckExit(); + if (threadReqQuit) return; } threadBuffer.release(); @@ -1161,8 +1188,7 @@ void PlayerVideoRec::threadFeedPlay() MILLISLEEP(500); // I think this will solve a race } - threadCheckExit(); - + if (threadReqQuit) return; Message* m = new Message(); // Must be done after this thread finishes, and must break into master mutex m->to = messageReceiver; @@ -1174,7 +1200,7 @@ void PlayerVideoRec::threadFeedPlay() } -void PlayerVideoRec::threadPTSFeedScan() +bool PlayerVideoRec::threadPTSFeedScan() { // This method manipulates the PTS instead of waiting, this is for the android devices, maybe later for windows? @@ -1206,12 +1232,13 @@ void PlayerVideoRec::threadPTSFeedScan() { baseFrameNumber = currentfeedFrameNumber; - threadCheckExit(); + if (threadReqQuit) return false; + if (!vdr->getNextIFrame(baseFrameNumber, direction, &filePos, &iframeNumber, &iframeLength)) - return; + return true; - if (iframeNumber >= lengthFrames) return; - // scan has got to the end of what we knew to be there before we started scanning + if (iframeNumber >= lengthFrames) return true; + // scan has got to the end of what we knew to be there before we started scanning baseFrameNumber = iframeNumber; @@ -1224,10 +1251,10 @@ void PlayerVideoRec::threadPTSFeedScan() if (!vdr->isConnected()) { doConnectionLost(); - break; + return false; } - threadCheckExit(); + if (threadReqQuit) return false; videoLength = demuxer->stripAudio(threadBuffer.ucharp(), amountReceived); demuxer->changeTimes(threadBuffer.ucharp(), videoLength, playtime); @@ -1235,7 +1262,7 @@ void PlayerVideoRec::threadPTSFeedScan() while (!video->displayIFrame(threadBuffer.ucharp(), videoLength)) // the device might block { MILLISLEEP(20); - threadCheckExit(); + if (threadReqQuit) return false; count++; if (count%300==0) { ULLONG cur_time=video->getCurrentTimestamp(); @@ -1264,7 +1291,7 @@ void PlayerVideoRec::threadPTSFeedScan() -void PlayerVideoRec::threadFeedScan() +bool PlayerVideoRec::threadFeedScan() { // This method is actually really simple - get frame from vdr, // spit it at the video chip, wait for a time. Most of the code here @@ -1303,11 +1330,12 @@ void PlayerVideoRec::threadFeedScan() baseFrameNumber = currentFrameNumber; do { - threadCheckExit(); + if (threadReqQuit) return false; + if (!vdr->getNextIFrame(baseFrameNumber, direction, &filePos, &iframeNumber, &iframeLength)) - return; + return true; - if (iframeNumber >= lengthFrames) return; + if (iframeNumber >= lengthFrames) return true; // scan has got to the end of what we knew to be there before we started scanning baseFrameNumber = iframeNumber; @@ -1335,7 +1363,7 @@ void PlayerVideoRec::threadFeedScan() if (!vdr->isConnected() || !amountReceived) { doConnectionLost(); - break; + return false; } #ifndef WIN32 @@ -1350,7 +1378,7 @@ void PlayerVideoRec::threadFeedScan() sleepTime = clock2 + frameTimeOffset - disp_msec - clock1; #endif if (sleepTime < 0) sleepTime = 0; - threadCheckExit(); + if (threadReqQuit) return false; MILLISLEEP(sleepTime); logger->log("Player", Log::DEBUG, "XXX Slept for %d", sleepTime); diff --git a/playervideorec.h b/playervideorec.h index 0ea99c0..f91269d 100644 --- a/playervideorec.h +++ b/playervideorec.h @@ -28,8 +28,8 @@ #endif #include #include - -#include "threadsystem.h" +#include +#include #include "callback.h" #include "defines.h" @@ -49,7 +49,7 @@ class OSDReceiver; class DVBSubtitles; class Channel; -class PlayerVideoRec : public Thread_TYPE, public Callback +class PlayerVideoRec : public Callback { public: PlayerVideoRec(MessageQueue* messageQueue, void* messageReceiver, OSDReceiver* osdReceiver); @@ -120,15 +120,13 @@ class PlayerVideoRec : public Thread_TYPE, public Callback void test2(); #endif - protected: - void threadMethod(); - private: void switchState(UCHAR newState, ULONG jumpFrame=0); + void threadMethod(); void threadFeedPlay(); - void threadFeedScan(); - void threadPTSFeedScan(); + bool threadFeedScan(); + bool threadPTSFeedScan(); void doConnectionLost(); void restartAtFrame(ULONG newFrame); @@ -159,6 +157,13 @@ class PlayerVideoRec : public Thread_TYPE, public Callback std::mutex stateMutex; + std::thread playerThread; + std::mutex playerThreadMutex; + std::condition_variable playerThreadCond; + bool threadReqQuit; + void threadStart(); + void threadStop(); + ULLONG lengthBytes{}; ULONG lengthFrames{}; ULONG currentFrameNumber{}; -- 2.39.2