Thanks for your answer,
To sum up my application, there is three threads one main which launch the other threads, one to capture the video stream from the camera and i’d like an other to save it in tiff file.
I’m using the nvapi to capture the sdi stream (Redirect Notice)
And when the capture is done i have directly a gltexture with the video stream. If i load back the texture to the cpu, it’s mainly because i don’t know how to save directly a gltexture to a tiff file (That’s why i’m using the libtiff, but to do so i need to retrieve it from te GPUs)
Do you know a way to save directly the gltexture?
(After a quick check, i can’t use glreadpixels as i’m drawing several textures on my framebuffer, that’s why i get the data from each gltexture)
EDIT—
I’m trying the other solution, The main thread launch the capture which require an opengl Context and can launch an other thread to save the texture. For the moment, i only have a white Tiff file as a result. (and i know that my texture is correctly captured because i display the video stream from the camera)
Here is the switch where i make the different action in the main thread (depending on which button is clicked)
switch (message)
{
case WM_CREATE:
buttons[0] = CreateWindow("BUTTON", "Capture", WS_CHILD | WS_VISIBLE, 5, 5, 383, 30, mainWindow, (HMENU) ID_B_STARTCAPTURE, instance, NULL);
buttons[1] = CreateWindow("BUTTON", "Record", WS_CHILD | WS_VISIBLE, 5, 45, 383, 30, mainWindow, (HMENU) ID_B_STARTRECORD,instance, NULL);
return 0;
break;
case WM_COMMAND:
switch(LOWORD(wParam)){
case ID_B_STARTCAPTURE:
{
capture.CaptureCall(gl,mainWindow, instance,CMDLINE , affichage,capture ) ;// Launch the capture thread
capture.launched = true;
} break;
case ID_B_STARTRECORD:
capture.rec[0].Start_StopRecord(capture.m_SDIin.GetTextureObjectHandle(0), capture.launched, capture.m_hDC, capture.m_hRC2);//Launch the save thread
break;
}
return 0;
break;
case WM_DESTROY:
C_anccap::exit = true;
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(mainWindow, message, wParam, lParam);
}
Here is the capture function
int C_anccap::CaptureCall (HGLRC &gl,HWND &father, HINSTANCE hInstance, LPSTR lpCmdLine, int nCmdShow, C_anccap& anccap)
{
HWND g_hWnd;
capture = &anccap;
// Debug console.
SetupConsole();
if(capture->Configure(&lpCmdLine) == E_FAIL)
return FALSE;
if(capture->SetupSDIDevices() == E_FAIL)
return FALSE;
// Calculate the window size based on the incoming and outgoing video signals
capture->CalcWindowSize();
// Create window. Use video dimensions of video initialized above.
// Hack: Compensate for title bar height.
//g_windowHeight += 30;
g_hWnd = capture->SetupWindow(father, hInstance, 0, 0, "NVIDIA Quadro SDI Capture to memory");
// Exit on error.
if (!g_hWnd)
return FALSE;
capture->SetupGL(gl);
if(capture->StartSDIPipeline() == E_FAIL)
return FALSE;
// Show window.
ShowWindow(g_hWnd, nCmdShow);
UpdateWindow(g_hWnd);
wglMakeCurrent(NULL, NULL);
capturethread = std::thread(&C_anccap::LoopAnimation, capture);
}
int C_anccap::LoopAnimation()
{
MSG msg;
// Animation loop.
std::mutex mtx;
while (!C_anccap::exit) {
if (this->CaptureVideo() != GL_FAILURE_NV)
{
this->DisplayVideo();
if (this->rec[0].isStarted) {
mtx.lock();
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, this->rec[0].pixels.get());
mtx.unlock();
auto e =glGetError();
printf("test");
}
}
}
this->Shutdown();
wglMakeCurrent(NULL, NULL);
return FALSE;
}
And this is the saving function:
void Recorder::Start_StopRecord(GLuint Texture, bool launched,HDC &hdc, HGLRC & gl){
if (launched) {
if (isStarted) {
isStarted = false;
recordThread.join();
CloseTifFile();
pixels.release();
}
else {
pixels = std::unique_ptr<int>(new int[width*height]);
OpenTifFile(Texture);
isStarted = true;
recordThread = std::thread(&Recorder::RecordShot, this,&Texture,&hdc,&gl);
}
}
}
void Recorder::RecordShot(GLuint* texture, HDC* hdc, HGLRC* gl){
std::mutex mtx;
mtx.lock();
while (isStarted) {
WriteTif8Bits();
WriteDirectory();
}
mtx.unlock();
pixels.release();
}
void Recorder::OpenTifFile(GLuint &Texture){
char* filename="C:/Users/BOOM/Documents/textures/test3.tiff";
mp_fileTifIn = TIFFOpen(filename,"w");
}
void Recorder::CloseTifFile(){
TIFFClose(mp_fileTifIn);
}
void Recorder::WriteTif8Bits(){
//Setup Tiff Configuration
TIFFSetField(mp_fileTifIn,TIFFTAG_IMAGEWIDTH,width);
TIFFSetField(mp_fileTifIn,TIFFTAG_IMAGELENGTH,height);
TIFFSetField(mp_fileTifIn,TIFFTAG_SAMPLESPERPIXEL,4);
TIFFSetField(mp_fileTifIn,TIFFTAG_BITSPERSAMPLE,8);
TIFFSetField(mp_fileTifIn,TIFFTAG_ROWSPERSTRIP,TIFFDefaultStripSize(mp_fileTifIn,width));
TIFFSetField(mp_fileTifIn,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT);
TIFFSetField(mp_fileTifIn,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG);
TIFFSetField(mp_fileTifIn, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
//Image Reversal
Reverse(pixels.get(), height, width);
//Write one picture
TIFFWriteEncodedStrip(mp_fileTifIn, 0, pixels.get(), height*width * sizeof(int));
}
EDIT 2
I finally get why i had only a white picture, in fact the glgetteximage was badly configured with GL_TEXTURE_2D and my textures are GL_TEXTURE_RECTANGLE_NV; Thanks again for the idea of one thread which execute all opengl action