diff --git a/litecam/dist/include/Camera.h b/litecam/dist/include/Camera.h index 3877163..7d34388 100644 --- a/litecam/dist/include/Camera.h +++ b/litecam/dist/include/Camera.h @@ -29,12 +29,6 @@ #include #include -#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 #include @@ -147,6 +141,17 @@ struct CAMERA_API CaptureDeviceInfo // Exported functions CAMERA_API std::vector 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 @@ -165,7 +170,6 @@ class CAMERA_API Camera std::vector ListSupportedMediaTypes(); FrameData CaptureFrame(); - void ReleaseFrame(FrameData &frame); bool SetResolution(int width, int height); uint32_t frameWidth; @@ -173,7 +177,7 @@ class CAMERA_API Camera private: #ifdef _WIN32 - ComPtr reader; + void *reader; bool initialized; void InitializeMediaFoundation(); diff --git a/litecam/dist/lib/linux/liblitecam.so b/litecam/dist/lib/linux/liblitecam.so index 9a5d503..9989428 100644 Binary files a/litecam/dist/lib/linux/liblitecam.so and b/litecam/dist/lib/linux/liblitecam.so differ diff --git a/litecam/dist/lib/windows/debug/litecam.dll b/litecam/dist/lib/windows/debug/litecam.dll new file mode 100644 index 0000000..eafc545 Binary files /dev/null and b/litecam/dist/lib/windows/debug/litecam.dll differ diff --git a/litecam/dist/lib/windows/debug/litecam.lib b/litecam/dist/lib/windows/debug/litecam.lib new file mode 100644 index 0000000..577ef0a Binary files /dev/null and b/litecam/dist/lib/windows/debug/litecam.lib differ diff --git a/litecam/dist/lib/windows/release/litecam.dll b/litecam/dist/lib/windows/release/litecam.dll index 972327c..4c01145 100644 Binary files a/litecam/dist/lib/windows/release/litecam.dll and b/litecam/dist/lib/windows/release/litecam.dll differ diff --git a/litecam/dist/lib/windows/release/litecam.lib b/litecam/dist/lib/windows/release/litecam.lib index 8327b36..577ef0a 100644 Binary files a/litecam/dist/lib/windows/release/litecam.lib and b/litecam/dist/lib/windows/release/litecam.lib differ diff --git a/litecam/examples/barcode/main.cpp b/litecam/examples/barcode/main.cpp index dcbcc3c..ecd2ed7 100644 --- a/litecam/examples/barcode/main.cpp +++ b/litecam/examples/barcode/main.cpp @@ -100,7 +100,7 @@ int main() } } - camera.ReleaseFrame(frame); + ReleaseFrame(frame); } camera.Release(); diff --git a/litecam/examples/barcode/main_thread.cpp b/litecam/examples/barcode/main_thread.cpp new file mode 100644 index 0000000..49c2e9e --- /dev/null +++ b/litecam/examples/barcode/main_thread.cpp @@ -0,0 +1,204 @@ +#include +#include +#include +#include +#include +#include +#include + +#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 +class ThreadSafeQueue +{ +private: + std::queue queue; + std::mutex mtx; + std::condition_variable cv; + +public: + void Push(const T &item) + { + std::lock_guard lock(mtx); + queue.push(item); + cv.notify_one(); + } + + bool Pop(T &item) + { + std::unique_lock 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 lock(mtx); + return queue.empty(); + } +}; + +// Structure to store processing results +struct ProcessingResult +{ + std::vector>> contours; + std::vector texts; +}; + +// Global running flag +std::atomic running{true}; + +void ProcessFrames(CCaptureVisionRouter *cvr, ThreadSafeQueue &frameQueue, ThreadSafeQueue &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> 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 frameQueue; + ThreadSafeQueue 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; +} diff --git a/litecam/include/Camera.h b/litecam/include/Camera.h index bb531d7..7d34388 100644 --- a/litecam/include/Camera.h +++ b/litecam/include/Camera.h @@ -141,6 +141,17 @@ struct CAMERA_API CaptureDeviceInfo // Exported functions CAMERA_API std::vector 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 @@ -159,7 +170,6 @@ class CAMERA_API Camera std::vector ListSupportedMediaTypes(); FrameData CaptureFrame(); - void ReleaseFrame(FrameData &frame); bool SetResolution(int width, int height); uint32_t frameWidth; diff --git a/litecam/src/CameraLinux.cpp b/litecam/src/CameraLinux.cpp index d2dcddd..9b4929e 100644 --- a/litecam/src/CameraLinux.cpp +++ b/litecam/src/CameraLinux.cpp @@ -4,16 +4,6 @@ #include #include -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); diff --git a/litecam/src/CameraWindows.cpp b/litecam/src/CameraWindows.cpp index e5829e1..2a2d668 100644 --- a/litecam/src/CameraWindows.cpp +++ b/litecam/src/CameraWindows.cpp @@ -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(); diff --git a/litecam/src/main.cpp b/litecam/src/main.cpp index 9529bf8..6f908e1 100644 --- a/litecam/src/main.cpp +++ b/litecam/src/main.cpp @@ -84,7 +84,7 @@ int main() saveFrameAsJPEG(frame.rgbData, camera.frameWidth, camera.frameHeight, filename); } - camera.ReleaseFrame(frame); + ReleaseFrame(frame); #ifdef _WIN32 Sleep(500); #else @@ -127,7 +127,7 @@ int main() window.DrawText("Hello, Camera!", 50, 50, 24, textColor); } - camera.ReleaseFrame(frame); + ReleaseFrame(frame); } camera.Release();