I have written a basic server in C++ that runs in an infinite while loop. It receives signals from a client to do things. The main process that I want is to initiate or stop some tracking software that I have written.
I would like the server to still be able to receive signals while the tracking software is being run (e.g. if a stop signal was given). I figured that the best way to do this would be to create a separate thread for the tracking software, so that is what I did:
void Server::tracking(Command c)
{
//I have since changed this method. The new implementation is below
//switch(c) {
// case START:
// player = VideoPlayer();
// player.setTrackStatus(true);
// t = std::thread(&Server::track, this);
// t.detach();
// break;
// case STOP:
// player.setTrackStatus(false);
// break;
// default:
// break;
//}
}
Server::track
just calls player.run()
VideoPlayer
is the class that contains the main tracking loop. The track status is what determines whether or not the tracking loop continues to execute.
This works fine the first time I run it, it is able to start the tracking and stop it. The problem arises when I try to send another "START" signal without restarting the server.
I have narrowed down the problem to the cv::namedWindow
function.
Here is the start of the VideoPlayer
class:
void VideoPlayer::run(void)
{
//I have since changed this method. The new implementation is below
//initVC();
//openStream();
}
initVC()
is where I create the namedWindow
and openStream
contains the main tracking loop. Here is initVC
(which is where I believe the problem lies):
void VideoPlayer::initVC()
{
if(!capture.open("cut.mp4")) {
throw "Cannot open video stream";
}
std::cout << "flag 1" << std::endl;
cv::namedWindow("Tracker", CV_WINDOW_AUTOSIZE);
std::cout << "flag 2" << std::endl;
}
I have found that on the second run (i.e. tracking has been started and stopped and the server has not been closed and reopened), that flag 2
never gets run. I also found that, if I omit namedWindow
then the program stops before imshow()
. It might also be worth noting that the program doesn't crash, it just seems to pause.
I have a feeling that I am doing something wrong with the threading, because I have never used threads in C++ before.
Thanks!
EDIT: I have been attempting to add some of the changes suggested by @Dom, however I am still having a similar issue to before. I will post some additional code below with comments to try to explain.
Server::tracking:
This is meant to initiate tracking based on the command received from the client.
void Server::tracking(Command c)
{
switch(c) {
case START:
if(!isRunning) {
player = make_unique<VideoPlayer>();
isRunning = true;
player->setTrackStatus(isRunning);
}
else {
std::lock_guard<std::mutex> lock(mtx);
}
break;
case STOP:
if(isRunning) {
player->terminate();
player->exit(); //Destroys OpenCV stuff
player->joinThread();
player = nullptr;
isRunning = false;
}
else {
std::lock_guard<std::mutex> lock(mtx);
}
break;
default:
break;
}
}
VideoPlayer Constructor:
VideoPlayer::VideoPlayer () : trackStatus(true)
{
tracker = Tracker(); //A separate class, related to the data from the tracked
//object. Not relevant to the current question
track_t = std::thread(&VideoPlayer::run, this);
return;
}
VideoPlayer::run:
void VideoPlayer::run(void)
{
std::lock_guard<std::mutex> lock(mtx);
initVC(); //Initialises the OpenCV VideoCapture
openStream(); //Contains the main tracking code
return;
}
VideoPlayer::openStream:
void VideoPlayer::openStream()
{
while(trackStatus) {
... //tracking stuff
}
return;
}
VideoPlayer::terminate:
void VideoPlayer::terminate()
{
track = false;
std::lock_guard<std::mutex> lock(mtx);
}
VideoPlayer::joinThread:
void VideoPlayer::joinThread()
{
if(track_t.joinable()) {
std::cout << "flag 1" << std::endl;
track_t.join();
std::cout << "flag 2" << std::endl; //It fails here on my second "run"
return;
}
}
Basically, my program stops just before the track_t.join(), the second time I run the tracking (without restarting the server). flag 1
and flag 2
print the first time that I run the tracking. All of the OpenCV components appear to have been disposed of correctly. If I then try to open the tracking again, firstly, the tracking doesn't seem to start (but the program doesn't crash), and then if I try to stop the tracking, it prints flag 1
but then stops indefinitely without printing flag 2
Sorry for the lengthy post. I hope this gives a bit more context to what I'm trying to achieve