Skip to content

Commit e591a8a

Browse files
MathieuFavreaualexmo16
authored andcommitted
Open video io in media stream + bug fixes (#104)
1 parent d70c94e commit e591a8a

17 files changed

Lines changed: 134 additions & 60 deletions

c_plus_plus/src/model/stream/media_thread.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,12 @@ void MediaThread::run()
8585
// Set background color of empty display
8686
displayImageBuilder.setDisplayImageColor(emptyDisplay);
8787

88-
// Start audio resources
88+
// Start audio and video resources
8989
audioSource_->open();
9090
audioSink_->open();
9191
positionSource_->open();
92+
videoInput_->open();
93+
videoOutput_->open();
9294

9395
Point<float> fisheyeCenter(videoInputConfig_.resolution.width / 2.f, videoInputConfig_.resolution.height / 2.f);
9496
std::vector<SphericalAngleRect> detections;
@@ -213,10 +215,12 @@ void MediaThread::run()
213215
std::cout << "Error in video thread : " << e.what() << std::endl;
214216
}
215217

216-
// Clean audio resources
218+
// Clean audio and video resources
217219
audioSource_->close();
218220
audioSink_->close();
219221
positionSource_->close();
222+
videoInput_->close();
223+
videoOutput_->close();
220224
delete[] audioBuffer;
221225

222226
// Deallocate display images

c_plus_plus/src/model/stream/utils/threads/thread.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ void Thread::start()
1515
{
1616
if (!isRunning_)
1717
{
18+
join(); // Make sure the thread is truly finished
19+
1820
thread_ = std::make_unique<std::thread>(&Thread::threadExecution, this);
1921
isRunning_ = true;
2022
}
@@ -30,7 +32,7 @@ void Thread::stop()
3032

3133
void Thread::join()
3234
{
33-
if (isRunning_)
35+
if (thread_ != nullptr && thread_->joinable())
3436
{
3537
thread_->join();
3638
}
@@ -52,6 +54,10 @@ void Thread::threadExecution()
5254
{
5355
run();
5456
}
57+
catch (const std::exception& e)
58+
{
59+
std::cout << "Exception during thread execution : " << e.what() << std::endl;
60+
}
5561
catch (...)
5662
{
5763
std::cout << "Unknown exception during thread execution" << std::endl;
@@ -60,5 +66,4 @@ void Thread::threadExecution()
6066
isAbortRequested_ = false;
6167
isRunning_ = false;
6268
}
63-
6469
} // namespace Model

c_plus_plus/src/model/stream/video/detection/detection_thread.cpp

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -35,54 +35,72 @@ void DetectionThread::run()
3535
Dim2<int> detectionResolution(detector_->getInputImageDim());
3636
Point<float> fisheyeCenter(resolution.width / 2.f, resolution.height / 2.f);
3737

38-
std::vector<DewarpingParameters> dewarpingParams = getDetectionDewarpingParameters(resolution, dewarpCount_);
39-
std::vector<ImageFloat> detectionImages = getDetectionImages(detectionResolution, dewarpCount_);
40-
std::vector<DewarpingMapping> dewarpingMappings =
41-
getDewarpingMappings(dewarpingParams, resolution, detectionResolution, dewarpCount_);
38+
std::vector<DewarpingParameters> dewarpingParams;
39+
std::vector<ImageFloat> detectionImages;
40+
std::vector<DewarpingMapping> dewarpingMappings;
4241
std::vector<SphericalAngleRect> detections;
4342

44-
std::cout << "DetectionThread loop started" << std::endl;
45-
46-
while (!isAbortRequested())
43+
try
4744
{
48-
// Make sure a new image is actually in the buffer
49-
while (!imageBuffer_->getAndClearSwapCount() && !isAbortRequested())
50-
{
51-
std::this_thread::sleep_for(std::chrono::milliseconds(1));
52-
}
45+
// Allocate and prepare objects for dewarping and detection
46+
dewarpingParams = getDetectionDewarpingParameters(resolution, dewarpCount_);
47+
detectionImages = getDetectionImages(detectionResolution, dewarpCount_);
48+
dewarpingMappings = getDewarpingMappings(dewarpingParams, resolution, detectionResolution, dewarpCount_);
5349

54-
// We lock the image so we can use it without it being overwritten
55-
imageBuffer_->lockInUse();
56-
const Image& image = imageBuffer_->getLocked();
50+
std::cout << "DetectionThread loop started" << std::endl;
5751

58-
// Dewarp each view, detect on each view and concatenate the results
59-
for (int i = 0; i < dewarpCount_; ++i)
52+
while (!isAbortRequested())
6053
{
61-
dewarper_->dewarpImage(image, detectionImages[i], dewarpingMappings[i]);
62-
synchronizer_->sync();
63-
const std::vector<Rectangle> viewDetections = detector_->detectInImage(detectionImages[i]);
54+
// Make sure a new image is actually in the buffer
55+
while (!imageBuffer_->getAndClearSwapCount() && !isAbortRequested())
56+
{
57+
std::this_thread::sleep_for(std::chrono::milliseconds(1));
58+
}
6459

65-
for (const Rectangle& detection : viewDetections)
60+
// No need to do a detection if thread is aborted
61+
if (isAbortRequested())
6662
{
67-
detections.push_back(getAngleRectFromDewarpedImageRectangle(
68-
detection, dewarpingParams[i], detectionImages[i], fisheyeCenter, dewarpingConfig_.fisheyeAngle));
63+
break;
6964
}
70-
}
7165

72-
bool success = false;
66+
// We lock the image so we can use it without it being overwritten
67+
imageBuffer_->lockInUse();
68+
const Image& image = imageBuffer_->getLocked();
7369

74-
// Output the detections, if queue is full keep trying...
75-
while (!success && !isAbortRequested())
76-
{
77-
success = detectionQueue_->try_enqueue(std::move(detections));
70+
// Dewarp each view, detect on each view and concatenate the results
71+
for (int i = 0; i < dewarpCount_; ++i)
72+
{
73+
dewarper_->dewarpImage(image, detectionImages[i], dewarpingMappings[i]);
74+
synchronizer_->sync();
75+
const std::vector<Rectangle> viewDetections = detector_->detectInImage(detectionImages[i]);
76+
77+
for (const Rectangle& detection : viewDetections)
78+
{
79+
detections.push_back(getAngleRectFromDewarpedImageRectangle(detection, dewarpingParams[i],
80+
detectionImages[i], fisheyeCenter,
81+
dewarpingConfig_.fisheyeAngle));
82+
}
83+
}
7884

79-
if (!success)
85+
bool success = false;
86+
87+
// Output the detections, if queue is full keep trying...
88+
while (!success && !isAbortRequested())
8089
{
81-
std::this_thread::sleep_for(std::chrono::milliseconds(1));
90+
success = detectionQueue_->try_enqueue(std::move(detections));
91+
92+
if (!success)
93+
{
94+
std::this_thread::sleep_for(std::chrono::milliseconds(1));
95+
}
8296
}
83-
}
8497

85-
detections.clear(); // Just making sure...
98+
detections.clear(); // Just making sure... Should be empty because of the std::move
99+
}
100+
}
101+
catch (const std::exception& e)
102+
{
103+
std::cout << "Error in detection thread : " << e.what() << std::endl;
86104
}
87105

88106
objectFactory_->deallocateObjectVector(detectionImages);

c_plus_plus/src/model/stream/video/impl/implementation_factory.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ std::unique_ptr<IImageConverter> ImplementationFactory::getImageConverter()
182182
return imageConverter;
183183
}
184184

185-
std::unique_ptr<IVideoInput> ImplementationFactory::getFileImageReader(const std::string& imageFilePath,
185+
std::unique_ptr<IVideoInput> ImplementationFactory::getImageFileReader(const std::string& imageFilePath,
186186
ImageFormat format)
187187
{
188188
std::unique_ptr<IVideoInput> fileImageReader = nullptr;

c_plus_plus/src/model/stream/video/impl/implementation_factory.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class ImplementationFactory
2929
std::unique_ptr<ISynchronizer> getSynchronizer();
3030
std::unique_ptr<ISynchronizer> getDetectionSynchronizer();
3131
std::unique_ptr<IImageConverter> getImageConverter();
32-
std::unique_ptr<IVideoInput> getFileImageReader(const std::string& imageFilePath, ImageFormat format);
32+
std::unique_ptr<IVideoInput> getImageFileReader(const std::string& imageFilePath, ImageFormat format);
3333
std::unique_ptr<IVideoInput> getCameraReader(const VideoConfig& cameraConfig);
3434

3535
private:

c_plus_plus/src/model/stream/video/input/camera_reader.cpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,36 +25,41 @@ CameraReader::CameraReader(const VideoConfig& videoConfig, std::size_t bufferCou
2525
: videoConfig_(videoConfig)
2626
, images_(bufferCount, Image(videoConfig.resolution.width, videoConfig.resolution.height, videoConfig.imageFormat))
2727
, buffer_({})
28+
, fd_(-1)
2829
{
29-
fd_ = open(videoConfig_.deviceName.c_str(), O_RDWR);
30+
buffer_.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
31+
buffer_.memory = V4L2_MEMORY_MMAP;
32+
}
33+
34+
void CameraReader::open()
35+
{
36+
fd_ = ::open(videoConfig_.deviceName.c_str(), O_RDWR);
3037

3138
if (fd_ == ERROR_CODE)
3239
{
3340
throw std::runtime_error("Could not open camera " + videoConfig_.deviceName);
3441
}
3542

36-
buffer_.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
37-
buffer_.memory = V4L2_MEMORY_MMAP;
38-
3943
checkCaps();
4044
setImageFormat();
41-
requestBuffers(bufferCount);
45+
requestBuffers(images_.size());
4246

4347
// Queue a first capture for fast read
4448
v4l2_buffer buffer = buffer_;
4549
buffer.index = images_.current().index;
4650
queueCapture(buffer);
4751
}
4852

49-
CameraReader::~CameraReader()
53+
void CameraReader::close()
5054
{
5155
for (std::size_t i = 0; i < images_.size(); ++i)
5256
{
5357
unmapBuffer(images_.current());
5458
images_.next();
5559
}
5660

57-
close(fd_);
61+
::close(fd_);
62+
fd_ = -1;
5863
}
5964

6065
const Image& CameraReader::readImage()
@@ -81,12 +86,12 @@ void CameraReader::queueCapture(v4l2_buffer& buffer)
8186
{
8287
if (xioctl(VIDIOC_QBUF, &buffer) == ERROR_CODE)
8388
{
84-
perror("Failed to querry buffer");
89+
throw std::runtime_error("Failed to querry camera buffer");
8590
}
8691

8792
if (xioctl(VIDIOC_STREAMON, &buffer.type) == ERROR_CODE)
8893
{
89-
perror("Failed to capture image");
94+
throw std::runtime_error("Failed to capture camera image");
9095
}
9196
}
9297

@@ -103,12 +108,12 @@ void CameraReader::dequeueCapture(v4l2_buffer& buffer)
103108

104109
if (result == ERROR_CODE)
105110
{
106-
perror("Error waiting for Frame");
111+
throw std::runtime_error("Error waiting for camera frame");
107112
}
108113

109114
if (xioctl(VIDIOC_DQBUF, &buffer) == ERROR_CODE)
110115
{
111-
perror("Failed to retrieve Frame");
116+
throw std::runtime_error("Failed to retrieve camera frame");
112117
}
113118
}
114119

c_plus_plus/src/model/stream/video/input/camera_reader.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ class CameraReader : public IVideoInput
1313
{
1414
public:
1515
CameraReader(const VideoConfig& cameraConfig, std::size_t bufferCount);
16-
virtual ~CameraReader();
1716

17+
void open() override;
18+
void close() override;
1819
const Image& readImage() override;
1920

2021
protected:

c_plus_plus/src/model/stream/video/input/cuda/cuda_camera_reader.cu

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,6 @@ CudaCameraReader::CudaCameraReader(const VideoConfig& videoConfig)
1515
}
1616

1717
checkCuda(cudaStreamCreate(&stream_));
18-
19-
// Read a frame to prepare the next read
20-
nextImage_ = &CameraReader::readImage();
21-
cudaMemcpyAsync(nextImage_->deviceData, nextImage_->hostData, nextImage_->size, cudaMemcpyHostToDevice, stream_);
2218
}
2319

2420
CudaCameraReader::~CudaCameraReader()
@@ -32,6 +28,15 @@ CudaCameraReader::~CudaCameraReader()
3228
cudaStreamDestroy(stream_);
3329
}
3430

31+
void CudaCameraReader::open()
32+
{
33+
CameraReader::open();
34+
35+
// Read a frame to prepare the next read
36+
nextImage_ = &CameraReader::readImage();
37+
cudaMemcpyAsync(nextImage_->deviceData, nextImage_->hostData, nextImage_->size, cudaMemcpyHostToDevice, stream_);
38+
}
39+
3540
const Image& CudaCameraReader::readImage()
3641
{
3742
if (nextImage_ == nullptr)

c_plus_plus/src/model/stream/video/input/cuda/cuda_camera_reader.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class CudaCameraReader : public CameraReader
1414
explicit CudaCameraReader(const VideoConfig& videoConfig);
1515
virtual ~CudaCameraReader();
1616

17+
void open() override;
1718
const Image& readImage() override;
1819

1920
private:

c_plus_plus/src/model/stream/video/input/i_video_input.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ class IVideoInput
99
{
1010
public:
1111
virtual ~IVideoInput() = default;
12+
virtual void open() = 0;
13+
virtual void close() = 0;
1214
virtual const Image& readImage() = 0;
1315
};
1416

0 commit comments

Comments
 (0)