Skip to content

Commit

Permalink
Add a thread example
Browse files Browse the repository at this point in the history
  • Loading branch information
yushulx committed Dec 19, 2024
1 parent 1c1e04e commit a86480b
Show file tree
Hide file tree
Showing 12 changed files with 230 additions and 32 deletions.
20 changes: 12 additions & 8 deletions litecam/dist/include/Camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,6 @@
#include <wrl/client.h>
#include <dshow.h>

#pragma comment(lib, "mfplat.lib")
#pragma comment(lib, "mf.lib")
#pragma comment(lib, "mfreadwrite.lib")
#pragma comment(lib, "mfuuid.lib")

using Microsoft::WRL::ComPtr;
#elif __linux__
#include <linux/videodev2.h>
#include <fcntl.h>
Expand Down Expand Up @@ -147,6 +141,17 @@ struct CAMERA_API CaptureDeviceInfo

// Exported functions
CAMERA_API std::vector<CaptureDeviceInfo> ListCaptureDevices();
CAMERA_API void ReleaseFrame(FrameData &frame);

void ReleaseFrame(FrameData &frame)
{
if (frame.rgbData)
{
delete[] frame.rgbData;
frame.rgbData = nullptr;
frame.size = 0;
}
}

// Camera class
class CAMERA_API Camera
Expand All @@ -165,15 +170,14 @@ class CAMERA_API Camera

std::vector<MediaTypeInfo> ListSupportedMediaTypes();
FrameData CaptureFrame();
void ReleaseFrame(FrameData &frame);
bool SetResolution(int width, int height);

uint32_t frameWidth;
uint32_t frameHeight;

private:
#ifdef _WIN32
ComPtr<IMFSourceReader> reader;
void *reader;

bool initialized;
void InitializeMediaFoundation();
Expand Down
Binary file modified litecam/dist/lib/linux/liblitecam.so
Binary file not shown.
Binary file added litecam/dist/lib/windows/debug/litecam.dll
Binary file not shown.
Binary file added litecam/dist/lib/windows/debug/litecam.lib
Binary file not shown.
Binary file modified litecam/dist/lib/windows/release/litecam.dll
Binary file not shown.
Binary file modified litecam/dist/lib/windows/release/litecam.lib
Binary file not shown.
2 changes: 1 addition & 1 deletion litecam/examples/barcode/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ int main()
}
}

camera.ReleaseFrame(frame);
ReleaseFrame(frame);
}

camera.Release();
Expand Down
204 changes: 204 additions & 0 deletions litecam/examples/barcode/main_thread.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <atomic>

#include "template.h"
#include "DynamsoftCaptureVisionRouter.h"
#include "DynamsoftUtility.h"
#include "Camera.h"
#include "CameraPreview.h"

using namespace dynamsoft::license;
using namespace dynamsoft::cvr;
using namespace dynamsoft::dbr;
using namespace dynamsoft::utility;
using namespace dynamsoft::basic_structures;

// Thread-safe queue for processing results
template <typename T>
class ThreadSafeQueue
{
private:
std::queue<T> queue;
std::mutex mtx;
std::condition_variable cv;

public:
void Push(const T &item)
{
std::lock_guard<std::mutex> lock(mtx);
queue.push(item);
cv.notify_one();
}

bool Pop(T &item)
{
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [this]()
{ return !queue.empty(); });

if (!queue.empty())
{
item = queue.front();
queue.pop();
return true;
}
return false;
}

bool Empty()
{
std::lock_guard<std::mutex> lock(mtx);
return queue.empty();
}
};

// Structure to store processing results
struct ProcessingResult
{
std::vector<std::vector<std::pair<int, int>>> contours;
std::vector<std::string> texts;
};

// Global running flag
std::atomic<bool> running{true};

void ProcessFrames(CCaptureVisionRouter *cvr, ThreadSafeQueue<FrameData> &frameQueue, ThreadSafeQueue<ProcessingResult> &resultQueue)
{
while (running)
{
FrameData frame;
if (frameQueue.Pop(frame))
{
if (frame.rgbData == nullptr)
{
continue;
}

ProcessingResult result;

CImageData data(frame.size,
frame.rgbData,
frame.width,
frame.height,
frame.width * 3,
IPF_RGB_888,
0, 0);
CCapturedResult *captureResult = cvr->Capture(&data, "");

if (captureResult)
{
CDecodedBarcodesResult *barcodeResult = captureResult->GetDecodedBarcodesResult();
if (barcodeResult)
{
int count = barcodeResult->GetItemsCount();
for (int i = 0; i < count; i++)
{
const CBarcodeResultItem *barcodeResultItem = barcodeResult->GetItem(i);
CPoint *points = barcodeResultItem->GetLocation().points;

std::vector<std::pair<int, int>> corners = {
{points[0][0], points[0][1]},
{points[1][0], points[1][1]},
{points[2][0], points[2][1]},
{points[3][0], points[3][1]}};

result.contours.push_back(corners);
result.texts.push_back(barcodeResultItem->GetText());
}
}

resultQueue.Push(result);

captureResult->Release();
}

ReleaseFrame(frame);
}
}
}

int main()
{
// Initialize license
char szErrorMsg[256];
if (CLicenseManager::InitLicense("DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ==", szErrorMsg, 256) != EC_OK)
{
std::cerr << szErrorMsg << std::endl;
return -1;
}

// Initialize Capture Vision Router
CCaptureVisionRouter *cvr = new CCaptureVisionRouter;
if (cvr->InitSettings(jsonString.c_str(), szErrorMsg, 256) != EC_OK)
{
std::cerr << "Error initializing CVR: " << szErrorMsg << std::endl;
return -1;
}

// Instantiate Camera
Camera camera;
if (!camera.Open(0))
{
std::cerr << "Failed to open camera." << std::endl;
return -1;
}

// Instantiate Camera Window
CameraWindow window(camera.frameWidth, camera.frameHeight, "Camera Stream");
if (!window.Create())
{
std::cerr << "Failed to create window." << std::endl;
return -1;
}
window.Show();

// Thread-safe frame and result queues
ThreadSafeQueue<FrameData> frameQueue;
ThreadSafeQueue<ProcessingResult> resultQueue;

// Start processing thread
std::thread processingThread(ProcessFrames, cvr, std::ref(frameQueue), std::ref(resultQueue));

// Main loop for frame capture and drawing
CameraWindow::Color textColor = {255, 0, 0};

while (window.WaitKey('q'))
{
// Capture a frame
FrameData frame = camera.CaptureFrame();
if (frame.rgbData)
{
// Display the frame
window.ShowFrame(frame.rgbData, frame.width, frame.height);

// Push frame to processing queue
frameQueue.Push(frame);

// Draw contours and texts if results are available
ProcessingResult result;
if (!resultQueue.Empty() && resultQueue.Pop(result))
{
for (size_t i = 0; i < result.contours.size(); ++i)
{
window.DrawContour(result.contours[i]);
window.DrawText(result.texts[i], result.contours[i][0].first, result.contours[i][0].second, 24, textColor);
}
}
}
}

running = false;

// Wait for processing thread to finish
processingThread.join();

camera.Release();
delete cvr;

return 0;
}
12 changes: 11 additions & 1 deletion litecam/include/Camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,17 @@ struct CAMERA_API CaptureDeviceInfo

// Exported functions
CAMERA_API std::vector<CaptureDeviceInfo> ListCaptureDevices();
CAMERA_API void ReleaseFrame(FrameData &frame);

void ReleaseFrame(FrameData &frame)
{
if (frame.rgbData)
{
delete[] frame.rgbData;
frame.rgbData = nullptr;
frame.size = 0;
}
}

// Camera class
class CAMERA_API Camera
Expand All @@ -159,7 +170,6 @@ class CAMERA_API Camera

std::vector<MediaTypeInfo> ListSupportedMediaTypes();
FrameData CaptureFrame();
void ReleaseFrame(FrameData &frame);
bool SetResolution(int width, int height);

uint32_t frameWidth;
Expand Down
10 changes: 0 additions & 10 deletions litecam/src/CameraLinux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,6 @@
#include <string>
#include <map>

void Camera::ReleaseFrame(FrameData &frame)
{
if (frame.rgbData)
{
delete[] frame.rgbData;
frame.rgbData = nullptr;
frame.size = 0;
}
}

bool Camera::Open(int cameraIndex)
{
std::string devicePath = "/dev/video" + std::to_string(cameraIndex);
Expand Down
10 changes: 0 additions & 10 deletions litecam/src/CameraWindows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,6 @@ const wchar_t *GetSubtypeName(const GUID &subType)
return guidString;
}

void Camera::ReleaseFrame(FrameData &frame)
{
if (frame.rgbData)
{
delete[] frame.rgbData;
frame.rgbData = nullptr;
frame.size = 0;
}
}

Camera::Camera() : reader(nullptr), frameWidth(640), frameHeight(480), initialized(false)
{
InitializeMediaFoundation();
Expand Down
4 changes: 2 additions & 2 deletions litecam/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ int main()
saveFrameAsJPEG(frame.rgbData, camera.frameWidth, camera.frameHeight, filename);
}

camera.ReleaseFrame(frame);
ReleaseFrame(frame);
#ifdef _WIN32
Sleep(500);
#else
Expand Down Expand Up @@ -127,7 +127,7 @@ int main()
window.DrawText("Hello, Camera!", 50, 50, 24, textColor);
}

camera.ReleaseFrame(frame);
ReleaseFrame(frame);
}

camera.Release();
Expand Down

0 comments on commit a86480b

Please sign in to comment.