Compare commits

4 Commits

3 changed files with 90 additions and 30 deletions

View File

@ -43,7 +43,6 @@ target_link_libraries(webcam PRIVATE
engine engine
framework framework
opencv_world300 opencv_world300
opencv_ts300
extern extern
Ws2_32 Ws2_32

View File

@ -9,6 +9,8 @@
#include "opencv2\opencv.hpp" #include "opencv2\opencv.hpp"
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <filesystem>
using namespace GS; using namespace GS;
using namespace GS::Script; using namespace GS::Script;
@ -36,10 +38,12 @@ void ProcessWebcamThread::Execute() {
bool temp_not_finish = true; bool temp_not_finish = true;
bool temp_pause = true; bool temp_pause = true;
bool temp_record_frame = false; bool temp_record_frame = false;
current_frame_clock = 0.0;
//construction LUT pour synchro avec la clock squirrel //construction LUT pour synchro avec la clock squirrel
std::ofstream lutFile(outputVideoName+"_lut.bin", std::ios::binary); std::ofstream lutFile(outputVideoName+"_lut.bin", std::ios::binary);
__LOG_CAM__ << "NEW RECORDING THREAD "<<videoIndex<<" LAUNCHED \n"; __LOG_CAM__ << "NEW RECORDING THREAD "<<videoIndex<<" LAUNCHED \n";
int frame_index = 0;
while (temp_not_finish) { while (temp_not_finish) {
mutex_not_finish.Lock(); mutex_not_finish.Lock();
@ -57,7 +61,7 @@ void ProcessWebcamThread::Execute() {
if (temp_pause || !temp_record_frame) if (temp_pause || !temp_record_frame)
Platform::Get().Sleep(10); Platform::Get().Sleep(10);
else{ else{
InputVideo->read(*im); InputVideo->read(*im);
outputVideo->write(*im); outputVideo->write(*im);
lutFile.write(reinterpret_cast<const char*>(&current_frame_clock),sizeof(float)); lutFile.write(reinterpret_cast<const char*>(&current_frame_clock),sizeof(float));
@ -68,6 +72,8 @@ void ProcessWebcamThread::Execute() {
im->release(); im->release();
lutFile.close(); lutFile.close();
Platform::Get().Sleep(50); // Laisser le fichier se finaliser
delete im; delete im;
} }
//********************************************************* //*********************************************************
@ -97,12 +103,27 @@ HRESULT EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum)
return hr; return hr;
} }
int DisplayDeviceInformation(IEnumMoniker *pEnum) std::string BstrToString(BSTR bstr)
{
if (!bstr) return std::string();
int len = WideCharToMultiByte(CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL);
if (len <= 0) return std::string();
std::string result(len - 1, '\0'); // -1 pour exclure le \0 final
WideCharToMultiByte(CP_UTF8, 0, bstr, -1, &result[0], len, NULL, NULL);
return result;
}
std::vector<int> DisplayDeviceInformation(IEnumMoniker *pEnum)
{ {
IMoniker *pMoniker = NULL; IMoniker *pMoniker = NULL;
int return_id_device = -1; int return_id_device = -1;
int counter_device = 0; int counter_device = 0;
std::vector<int> camera_ids;
while (pEnum->Next(1, &pMoniker, NULL) == S_OK) while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
{ {
IPropertyBag *pPropBag; IPropertyBag *pPropBag;
@ -124,10 +145,24 @@ int DisplayDeviceInformation(IEnumMoniker *pEnum)
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
printf("%S\n", var.bstrVal);
if (wcscmp(var.bstrVal, L"MMP SDK") != 0 && wcscmp(var.bstrVal, L"Oculus Rift") != 0 && wcscmp(var.bstrVal, L"HTC Vive") != 0) std::string name = BstrToString(var.bstrVal);
printf("%S\n", var.bstrVal);
__LOG_CAM__<<"FOUND CAM ID "<<counter_device<<" NAME "<<name.c_str()<<"\n";
if (
wcsstr(var.bstrVal, L"MMP SDK") == nullptr &&
wcsstr(var.bstrVal, L"Oculus Rift") == nullptr &&
wcsstr(var.bstrVal, L"HTC Vive") == nullptr &&
wcsstr(var.bstrVal, L"RealSense") == nullptr &&
wcsstr(var.bstrVal, L"OBS") == nullptr
){
camera_ids.push_back(counter_device);
return_id_device = counter_device; return_id_device = counter_device;
}
__LOG_CAM__<<"RETURN DEVICE ID "<<return_id_device<<"\n";
VariantClear(&var); VariantClear(&var);
} }
@ -154,7 +189,8 @@ int DisplayDeviceInformation(IEnumMoniker *pEnum)
pMoniker->Release(); pMoniker->Release();
++counter_device; ++counter_device;
} }
return return_id_device;
return camera_ids;
} }
@ -172,7 +208,7 @@ bool Webcam::Open(int width_, int height_) {
height = height_; height = height_;
int id_device = -1; std::vector<int> id_devices;
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
@ -181,23 +217,38 @@ bool Webcam::Open(int width_, int height_) {
hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum); hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
id_device = DisplayDeviceInformation(pEnum); id_devices = DisplayDeviceInformation(pEnum);
pEnum->Release(); pEnum->Release();
} }
CoUninitialize(); CoUninitialize();
} }
if (id_device == -1)
if (id_devices.size() == 0)
return false; return false;
InputVideo = new VideoCapture(0);
InputVideo = new VideoCapture();
int device_id = -1;
for (int i = 0; i < id_devices.size(); i++)
{
InputVideo->open(id_devices[i]);
if(InputVideo->isOpened()){
device_id = id_devices[i];
break;
}
}
if(device_id == -1)
return false;
__LOG_CAM__ << "OPEN CAM ID "<<device_id <<"\n";
InputVideo->set(CV_CAP_PROP_FRAME_WIDTH, width); InputVideo->set(CV_CAP_PROP_FRAME_WIDTH, width);
InputVideo->set(CV_CAP_PROP_FRAME_HEIGHT, height); InputVideo->set(CV_CAP_PROP_FRAME_HEIGHT, height);
InputVideo->set(CAP_PROP_FPS, webcam_fps); InputVideo->set(CAP_PROP_FPS, webcam_fps);
if (!InputVideo->isOpened())
return false;
outputVideo = new VideoWriter; outputVideo = new VideoWriter;
ReplayInputVideo = new VideoCapture(); ReplayInputVideo = new VideoCapture();
@ -220,6 +271,8 @@ void Webcam::Reset(bool _reset_video) {
} }
void Webcam::RecordFrame(float _clock) { void Webcam::RecordFrame(float _clock) {
if (!thread_process)
return;
thread_process->mutex_record_frame.Lock(); thread_process->mutex_record_frame.Lock();
thread_process->record_frame = true; thread_process->record_frame = true;
thread_process->current_frame_clock = _clock; thread_process->current_frame_clock = _clock;
@ -231,8 +284,7 @@ void Webcam::ResetVideo() {
std::stringstream video_name; std::stringstream video_name;
video_name << "./webcam_record_" << index_save_video << ".avi"; video_name << "./webcam_record_" << index_save_video << ".avi";
// set the codec fourcc // set the codec fourcc
unsigned int ex = outputVideo->fourcc('X', 'V', 'I', 'D'); unsigned int ex = outputVideo->fourcc('M', 'J', 'P', 'G');
outputVideo->set(VIDEOWRITER_PROP_QUALITY, 70);
outputVideo->open(video_name.str(), ex, webcam_fps, Size(width, height), true); outputVideo->open(video_name.str(), ex, webcam_fps, Size(width, height), true);
if (!outputVideo->isOpened()) if (!outputVideo->isOpened())
@ -268,10 +320,14 @@ void Webcam::setPause(bool pause) {
bool thread_pause = thread_process->pause; bool thread_pause = thread_process->pause;
thread_process->mutex_pause.Unlock(); thread_process->mutex_pause.Unlock();
thread_process->mutex_pause.Lock();
thread_process->pause = pause;
thread_process->mutex_pause.Unlock();
if (!thread_pause && pause) { if (!thread_pause && pause) {
__LOG_CAM__ <<"B\n"; __LOG_CAM__ <<"B\n";
Close(); Close();
Platform::Get().Sleep(50); // Laisser le fichier se finaliser
__LOG_CAM__ << "REPLAY INPUT RELEASE ./webcam_record_" << index_replay_video << ".avi\n "; __LOG_CAM__ << "REPLAY INPUT RELEASE ./webcam_record_" << index_replay_video << ".avi\n ";
ReplayInputVideo->release(); ReplayInputVideo->release();
index_replay_video = index_save_video - 1; index_replay_video = index_save_video - 1;
@ -312,11 +368,14 @@ void Webcam::Close() {
thread_process = nullptr; thread_process = nullptr;
} }
ReplayInputVideo->release(); if(ReplayInputVideo)
ReplayInputVideo->release();
} }
uchar *Webcam::SetFrame(float clock, GS::String record_name , int record_index) { uchar *Webcam::SetFrame(float clock, GS::String record_name , int record_index) {
//create buffer from lut //create buffer from lut
bool is_the_last_record = record_index == index_save_video - 1 ;
if(video_times.size() == 0){ if(video_times.size() == 0){
//charger lut dans video_times //charger lut dans video_times
__LOG_CAM__ << "Chargement LUT: "<<record_name<<"_"<<record_index<<"_lut.bin\n"; __LOG_CAM__ << "Chargement LUT: "<<record_name<<"_"<<record_index<<"_lut.bin\n";
@ -327,7 +386,6 @@ uchar *Webcam::SetFrame(float clock, GS::String record_name , int record_index)
if (!lutFile.is_open()) if (!lutFile.is_open())
{ {
__LOG_CAM__ << "Cannot open LUT file: " << record_name<<"_lut.bin\n"; __LOG_CAM__ << "Cannot open LUT file: " << record_name<<"_lut.bin\n";
return NULL;
} }
video_times.clear(); video_times.clear();
@ -340,30 +398,31 @@ uchar *Webcam::SetFrame(float clock, GS::String record_name , int record_index)
lutFile.seekg(size - static_cast<std::streamoff>(sizeof(float))); lutFile.seekg(size - static_cast<std::streamoff>(sizeof(float)));
lutFile.read(reinterpret_cast<char*>(&end_time), sizeof(float)); lutFile.read(reinterpret_cast<char*>(&end_time), sizeof(float));
__LOG_CAM__ <<"end: "<<(float)end_time<<" asked clock: "<<clock<<"\n"; __LOG_CAM__ <<"end: "<<(float)end_time<<" asked clock: "<<clock<<"\n";
//read la derniere et premiere clock //read la derniere et premiere clock
lutFile.seekg(0); lutFile.seekg(0);
float start_time; float start_time;
lutFile.read(reinterpret_cast<char*>(&start_time), sizeof(float)); lutFile.read(reinterpret_cast<char*>(&start_time), sizeof(float));
if(clock < start_time){ if(clock < start_time){
__LOG_CAM__ << "clock < start_time\n"; __LOG_CAM__ << "clock < start_time\n";
lutFile.close(); lutFile.close();
return NULL; return NULL;
} }
else if(clock > end_time){ else if(clock > end_time && !is_the_last_record){
__LOG_CAM__ << "clock > end_time\n"; __LOG_CAM__ << "clock > end_time\n";
lutFile.close(); lutFile.close();
return SetFrame(clock,record_name,record_index+1); //recursive search forward return SetFrame(clock,record_name,record_index+1); //recursive search forward
} }
if (record_index != index_replay_video) { if (record_index != index_replay_video) {
__LOG_H__ << "Changing video\n"; __LOG_CAM__ << "Changing video\n";
index_replay_video = record_index; index_replay_video = record_index;
std::stringstream video_name; std::stringstream video_name;
video_name << record_name << "_" << index_replay_video << ".avi"; video_name << record_name << "_" << index_replay_video << ".avi";
__LOG_H__ << record_name << "_" << index_replay_video << ".avi"; __LOG_CAM__ << record_name << "_" << index_replay_video << ".avi\n";
ReplayInputVideo->release(); ReplayInputVideo->release();
ReplayInputVideo->open(video_name.str()); ReplayInputVideo->open(video_name.str());
} }
@ -383,7 +442,8 @@ uchar *Webcam::SetFrame(float clock, GS::String record_name , int record_index)
return NULL; return NULL;
//force reset if clock not in range //force reset if clock not in range
if(clock < video_times[0] || clock > video_times[video_times.size() -1]){ if(clock < video_times[0] || (clock > video_times[video_times.size() -1] && !is_the_last_record)){
__LOG_CAM__ << "CLEAR \n";
video_times.clear(); video_times.clear();
return SetFrame(clock, record_name , 0); return SetFrame(clock, record_name , 0);
} }
@ -392,26 +452,26 @@ uchar *Webcam::SetFrame(float clock, GS::String record_name , int record_index)
if (it == video_times.begin()) if (it == video_times.begin())
{ {
// clock before first frame
__LOG_CAM__ << "clock before first frame\n"; __LOG_CAM__ << "clock before first frame\n";
//SetFrame(clock,record_name-1)
return nullptr; return nullptr;
} }
size_t index = std::distance(video_times.begin(), it) - 1; size_t index = std::distance(video_times.begin(), it) - 1;
if (!ReplayInputVideo || !ReplayInputVideo->isOpened()) if (!ReplayInputVideo || !ReplayInputVideo->isOpened())
{ {
__LOG_CAM__ << "ReplayInputVideo not opened\n"; __LOG_CAM__ << "ReplayInputVideo not opened\n";
return NULL; return NULL;
} }
__LOG_CAM__ << "Index found "<<index<<"for clock "<<clock<<"\n";
int frameCount = (int)ReplayInputVideo->get(cv::CAP_PROP_FRAME_COUNT) - 1;
ReplayInputVideo->set(cv::CAP_PROP_POS_FRAMES, index); ReplayInputVideo->set(cv::CAP_PROP_POS_FRAMES, index);
if (!ReplayInputVideo->read(*ReplayImframe)) if (!ReplayInputVideo->read(*ReplayImframe))
{ {
__LOG_CAM__ << "Failed to read frame at index " << index << "\n"; __LOG_CAM__ << "Failed to read frame at index " << index << "\n";
return NULL; return NULL;
} }
cv::cvtColor(*ReplayImframe, *ReplayIm, CV_BGR2RGBA, 4); cv::cvtColor(*ReplayImframe, *ReplayIm, CV_BGR2RGBA, 4);

View File

@ -71,6 +71,7 @@ private:
int index_save_video; int index_save_video;
int index_replay_video; int index_replay_video;
std::vector<float> video_times; std::vector<float> video_times;
cv::VideoCapture *ReplayInputVideo; cv::VideoCapture *ReplayInputVideo;
cv::Mat* ReplayIm; cv::Mat* ReplayIm;