diff --git a/BUILD/Binaries/Win32/Spout.dll b/BUILD/Binaries/Win32/Spout.dll index f27be4dd..62c5b1a5 100644 Binary files a/BUILD/Binaries/Win32/Spout.dll and b/BUILD/Binaries/Win32/Spout.dll differ diff --git a/BUILD/Binaries/Win32/Spout.lib b/BUILD/Binaries/Win32/Spout.lib index 4d3d0de2..5f7fe590 100644 Binary files a/BUILD/Binaries/Win32/Spout.lib and b/BUILD/Binaries/Win32/Spout.lib differ diff --git a/BUILD/Binaries/Win32/SpoutDX.dll b/BUILD/Binaries/Win32/SpoutDX.dll index 10132588..c0e247c5 100644 Binary files a/BUILD/Binaries/Win32/SpoutDX.dll and b/BUILD/Binaries/Win32/SpoutDX.dll differ diff --git a/BUILD/Binaries/Win32/SpoutDX.lib b/BUILD/Binaries/Win32/SpoutDX.lib index 4f5d524e..2d9c435a 100644 Binary files a/BUILD/Binaries/Win32/SpoutDX.lib and b/BUILD/Binaries/Win32/SpoutDX.lib differ diff --git a/BUILD/Binaries/Win32/SpoutLibrary.dll b/BUILD/Binaries/Win32/SpoutLibrary.dll index 590922ce..226852ba 100644 Binary files a/BUILD/Binaries/Win32/SpoutLibrary.dll and b/BUILD/Binaries/Win32/SpoutLibrary.dll differ diff --git a/BUILD/Binaries/Win32/SpoutLibrary.lib b/BUILD/Binaries/Win32/SpoutLibrary.lib index 4f48a5fc..e50762da 100644 Binary files a/BUILD/Binaries/Win32/SpoutLibrary.lib and b/BUILD/Binaries/Win32/SpoutLibrary.lib differ diff --git a/BUILD/Binaries/Win32/Spout_static.lib b/BUILD/Binaries/Win32/Spout_static.lib index dfc96c55..a2212284 100644 Binary files a/BUILD/Binaries/Win32/Spout_static.lib and b/BUILD/Binaries/Win32/Spout_static.lib differ diff --git a/BUILD/Binaries/x64/Spout.dll b/BUILD/Binaries/x64/Spout.dll index 187507dd..f6f42cd2 100644 Binary files a/BUILD/Binaries/x64/Spout.dll and b/BUILD/Binaries/x64/Spout.dll differ diff --git a/BUILD/Binaries/x64/Spout.lib b/BUILD/Binaries/x64/Spout.lib index de2b8823..c6a73ca4 100644 Binary files a/BUILD/Binaries/x64/Spout.lib and b/BUILD/Binaries/x64/Spout.lib differ diff --git a/BUILD/Binaries/x64/SpoutDX.dll b/BUILD/Binaries/x64/SpoutDX.dll index 27b6868d..29d249b0 100644 Binary files a/BUILD/Binaries/x64/SpoutDX.dll and b/BUILD/Binaries/x64/SpoutDX.dll differ diff --git a/BUILD/Binaries/x64/SpoutDX.lib b/BUILD/Binaries/x64/SpoutDX.lib index 527dae92..7e7e96e6 100644 Binary files a/BUILD/Binaries/x64/SpoutDX.lib and b/BUILD/Binaries/x64/SpoutDX.lib differ diff --git a/BUILD/Binaries/x64/SpoutLibrary.dll b/BUILD/Binaries/x64/SpoutLibrary.dll index 8b5710b8..d21a54e0 100644 Binary files a/BUILD/Binaries/x64/SpoutLibrary.dll and b/BUILD/Binaries/x64/SpoutLibrary.dll differ diff --git a/BUILD/Binaries/x64/SpoutLibrary.lib b/BUILD/Binaries/x64/SpoutLibrary.lib index 7c4b1945..2d98897b 100644 Binary files a/BUILD/Binaries/x64/SpoutLibrary.lib and b/BUILD/Binaries/x64/SpoutLibrary.lib differ diff --git a/BUILD/Binaries/x64/Spout_static.lib b/BUILD/Binaries/x64/Spout_static.lib index b4441ee6..92f1b7f2 100644 Binary files a/BUILD/Binaries/x64/Spout_static.lib and b/BUILD/Binaries/x64/Spout_static.lib differ diff --git a/SPOUTSDK/Examples/ofSpoutExample/Source/ofSpoutSender/Graphics/ofApp.cpp b/SPOUTSDK/Examples/ofSpoutExample/Source/ofSpoutSender/Graphics/ofApp.cpp index aabd617f..862b33d8 100644 --- a/SPOUTSDK/Examples/ofSpoutExample/Source/ofSpoutSender/Graphics/ofApp.cpp +++ b/SPOUTSDK/Examples/ofSpoutExample/Source/ofSpoutSender/Graphics/ofApp.cpp @@ -190,12 +190,21 @@ void ofApp::draw() { // Send fbo // The fbo must be bound for read. // The invert option is false because the fbo is already flipped in y. + // The fbo size can be different to the application window for a fixed sender size. + // Disable the code in WindowResized() if you want this. sender.SendFbo(myFbo.getId(), senderwidth, senderheight, false); myFbo.end(); // - - - - - - - - - - - - - - - - - // Send texture (fastest method) + // Show the result sized to the application window + myFbo.draw(0, 0, ofGetWidth(), ofGetHeight()); + + // Send the application window (default framebuffer). + // The window width and height must be used if myFbo size is different. + // sender.SendFbo(0, ofGetWidth(), ofGetHeight(), false); + + // Send texture // sender.SendTexture(myFbo.getTexture().getTextureData().textureID, // myFbo.getTexture().getTextureData().textureTarget, // senderwidth, senderheight, false); @@ -204,9 +213,6 @@ void ofApp::draw() { // myFbo.readToPixels(myPixels); // readToPixels is slow - but this is just an example // sender.SendImage(myPixels.getData(),senderwidth, senderheight, GL_RGBA, false); - // Show the result sized to the application window - myFbo.draw(0, 0, ofGetWidth(), ofGetHeight()); - // Show what it is sending ofSetColor(255); std::string str = "Sending as : "; diff --git a/SPOUTSDK/Examples/ofSpoutExample/src/ofApp.cpp b/SPOUTSDK/Examples/ofSpoutExample/src/ofApp.cpp index aabd617f..862b33d8 100644 --- a/SPOUTSDK/Examples/ofSpoutExample/src/ofApp.cpp +++ b/SPOUTSDK/Examples/ofSpoutExample/src/ofApp.cpp @@ -190,12 +190,21 @@ void ofApp::draw() { // Send fbo // The fbo must be bound for read. // The invert option is false because the fbo is already flipped in y. + // The fbo size can be different to the application window for a fixed sender size. + // Disable the code in WindowResized() if you want this. sender.SendFbo(myFbo.getId(), senderwidth, senderheight, false); myFbo.end(); // - - - - - - - - - - - - - - - - - // Send texture (fastest method) + // Show the result sized to the application window + myFbo.draw(0, 0, ofGetWidth(), ofGetHeight()); + + // Send the application window (default framebuffer). + // The window width and height must be used if myFbo size is different. + // sender.SendFbo(0, ofGetWidth(), ofGetHeight(), false); + + // Send texture // sender.SendTexture(myFbo.getTexture().getTextureData().textureID, // myFbo.getTexture().getTextureData().textureTarget, // senderwidth, senderheight, false); @@ -204,9 +213,6 @@ void ofApp::draw() { // myFbo.readToPixels(myPixels); // readToPixels is slow - but this is just an example // sender.SendImage(myPixels.getData(),senderwidth, senderheight, GL_RGBA, false); - // Show the result sized to the application window - myFbo.draw(0, 0, ofGetWidth(), ofGetHeight()); - // Show what it is sending ofSetColor(255); std::string str = "Sending as : "; diff --git a/SPOUTSDK/SpoutDirectX/SpoutDX/Binaries/Examples/Tutorial04.exe b/SPOUTSDK/SpoutDirectX/SpoutDX/Binaries/Examples/Tutorial04.exe index 42ba2fbd..a4b9f916 100644 Binary files a/SPOUTSDK/SpoutDirectX/SpoutDX/Binaries/Examples/Tutorial04.exe and b/SPOUTSDK/SpoutDirectX/SpoutDX/Binaries/Examples/Tutorial04.exe differ diff --git a/SPOUTSDK/SpoutDirectX/SpoutDX/Binaries/Examples/Tutorial07.exe b/SPOUTSDK/SpoutDirectX/SpoutDX/Binaries/Examples/Tutorial07.exe index e0099949..0449eb46 100644 Binary files a/SPOUTSDK/SpoutDirectX/SpoutDX/Binaries/Examples/Tutorial07.exe and b/SPOUTSDK/SpoutDirectX/SpoutDX/Binaries/Examples/Tutorial07.exe differ diff --git a/SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX.cpp b/SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX.cpp index 20ce4e6d..81e11866 100644 --- a/SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX.cpp +++ b/SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX.cpp @@ -100,6 +100,11 @@ // 29.04.21 - Change IsFrameNew() to return frame class global. // 10.06.21 - Remove Memoryshare struct and replace with SpoutSharedMemory object // Update data functions +// 01.07.21 - ReadPixelData - add swap r/b argument +// 04.07.21 - GetSenderCount, GetSender pass through to sendernames class. +// - Destructor : do not release receiver connected sender name. +// 20.07.21 - Correct GetSender to include max size +// Add SendBackBuffer // // ==================================================================================== /* @@ -170,10 +175,20 @@ spoutDX::spoutDX() spoutDX::~spoutDX() { - ReleaseSender(); - ReleaseReceiver(); + if (m_bConnected) { + // Receiver object + // Do not release the connected sender name + ReleaseReceiver(); + } + else { + // Sender object (or receiver not connected. i.e. not initialized) + // Release the sender name if initialized + ReleaseSender(); + } + CloseDirectX11(); memorybuffer.Close(); + } //--------------------------------------------------------- @@ -366,6 +381,31 @@ void spoutDX::ReleaseSender() } +//--------------------------------------------------------- +// Function: SendBackbuffer +// Get the swap chain's back buffer to a texture for sending. +// Assumes a single render target view. +// Refer to SendTexture for compatible formats. +// +bool spoutDX::SendBackBuffer() +{ + if (m_pImmediateContext) { + ID3D11RenderTargetView *rendertarget = nullptr; + m_pImmediateContext->OMGetRenderTargets(1, &rendertarget, nullptr); + if (rendertarget) { + ID3D11Resource* pBackBufferResource = nullptr; + rendertarget->GetResource(&pBackBufferResource); + if (pBackBufferResource) { + // SendTexture checks for DirectX initialization + // and handles sender creation and re-sizing. + SendTexture(reinterpret_cast(pBackBufferResource)); + return true; + } + } + } + return false; +} + //--------------------------------------------------------- // Function: SendTexture // Send DirectX11 texture @@ -693,7 +733,7 @@ bool spoutDX::ReceiveImage(unsigned char * pixels, // Copy from the sender's shared texture to the first staging texture m_pImmediateContext->CopyResource(m_pStaging[m_Index], m_pSharedTexture); // Map and read from the second while the first is occupied - ReadPixelData(m_pStaging[m_NextIndex], pixels, width, height, bRGB, bInvert); + ReadPixelData(m_pStaging[m_NextIndex], pixels, width, height, bRGB, bInvert, false); } // Allow access to the shared texture frame.AllowTextureAccess(m_pSharedTexture); @@ -888,11 +928,7 @@ bool spoutDX::WaitFrameSync(const char *SenderName, DWORD dwTimeout) // Number of senders int spoutDX::GetSenderCount() { - std::set SenderNameSet; - if (sendernames.GetSenderNames(&SenderNameSet)) { - return((int)SenderNameSet.size()); - } - return 0; + return sendernames.GetSenderCount(); } //--------------------------------------------------------- @@ -900,29 +936,7 @@ int spoutDX::GetSenderCount() // Sender item name in the sender names set bool spoutDX::GetSender(int index, char* sendername, int sendernameMaxSize) { - std::set SenderNameSet; - std::set::iterator iter; - std::string namestring; - char name[256]; - int i; - - if (sendernames.GetSenderNames(&SenderNameSet)) { - if (SenderNameSet.size() < (unsigned int)index) { - return false; - } - i = 0; - for (iter = SenderNameSet.begin(); iter != SenderNameSet.end(); iter++) { - namestring = *iter; // the name string - strcpy_s(name, 256, namestring.c_str()); // the 256 byte name char array - if (i == index) { - strcpy_s(sendername, sendernameMaxSize, name); // the passed name char array - break; - } - i++; - } - return true; - } - return false; + return sendernames.GetSender(index, sendername, sendernameMaxSize); } //--------------------------------------------------------- @@ -1798,53 +1812,67 @@ void spoutDX::CreateReceiver(const char * SenderName, unsigned int width, unsign // // A class device and context must have been created using OpenDirectX11() // -bool spoutDX::ReadPixelData(ID3D11Texture2D* pStagingTexture, unsigned char* pixels, - unsigned int width, unsigned int height, bool bRGB, bool bInvert) +// bRGB - pixel data is RGB instead of RGBA +// bInvert - flip the image +// bSwap - swap red/blue (BGRA/RGBA). Not available for re-sample +// +bool spoutDX::ReadPixelData(ID3D11Texture2D* pStagingSource, unsigned char* destpixels, + unsigned int width, unsigned int height, bool bRGB, bool bInvert, bool bSwap) { - if (!m_pImmediateContext || !pStagingTexture || !pixels) + if (!m_pImmediateContext || !pStagingSource || !destpixels) return false; - // Map the resource so we can access the pixels + // Map the staging texture resource so we can access the pixels D3D11_MAPPED_SUBRESOURCE mappedSubResource; // Make sure all commands are done before mapping the staging texture m_pImmediateContext->Flush(); // Map waits for GPU access - HRESULT hr = m_pImmediateContext->Map(pStagingTexture, 0, D3D11_MAP_READ, 0, &mappedSubResource); + HRESULT hr = m_pImmediateContext->Map(pStagingSource, 0, D3D11_MAP_READ, 0, &mappedSubResource); if (SUCCEEDED(hr)) { // Copy the staging texture pixels to the user buffer if (!bRGB) { - // RGBA buffer + // RGBA pixel buffer // TODO : test rgba-rgba resample + // TODO : rgba2bgraResample if (width != m_Width || height != m_Height) { - spoutcopy.rgba2rgbaResample(mappedSubResource.pData, pixels, m_Width, m_Height, mappedSubResource.RowPitch, width, height, bInvert); + spoutcopy.rgba2rgbaResample(mappedSubResource.pData, destpixels, m_Width, m_Height, mappedSubResource.RowPitch, width, height, bInvert); } else { - spoutcopy.rgba2rgba(mappedSubResource.pData, pixels, width, height, mappedSubResource.RowPitch, bInvert); + if(bSwap) + spoutcopy.rgba2bgra(mappedSubResource.pData, destpixels, width, height, mappedSubResource.RowPitch, bInvert); + else + spoutcopy.rgba2rgba(mappedSubResource.pData, destpixels, width, height, mappedSubResource.RowPitch, bInvert); } } - else if (m_dwFormat == 28) { - // RGB buffer + else if (m_dwFormat == 28) { // DXGI_FORMAT_R8G8B8A8_UNORM + // RGBA texture - RGB/BGR pixel buffer // If the texture format is RGBA it has to be converted to BGR by the staging texture copy if (width != m_Width || height != m_Height) { - spoutcopy.rgba2bgrResample(mappedSubResource.pData, pixels, m_Width, m_Height, mappedSubResource.RowPitch, width, height, bInvert); + if(bSwap) + spoutcopy.rgba2rgbResample(mappedSubResource.pData, destpixels, m_Width, m_Height, mappedSubResource.RowPitch, width, height, bInvert); + else + spoutcopy.rgba2bgrResample(mappedSubResource.pData, destpixels, m_Width, m_Height, mappedSubResource.RowPitch, width, height, bInvert); } else { - spoutcopy.rgba2bgr(mappedSubResource.pData, pixels, m_Width, m_Height, mappedSubResource.RowPitch, bInvert); + if (bSwap) + spoutcopy.rgba2rgb(mappedSubResource.pData, destpixels, m_Width, m_Height, mappedSubResource.RowPitch, bInvert); + else + spoutcopy.rgba2bgr(mappedSubResource.pData, destpixels, m_Width, m_Height, mappedSubResource.RowPitch, bInvert); } } else { // Used for SpoutCam to receive RGB images if (width != m_Width || height != m_Height) { - spoutcopy.rgba2rgbResample(mappedSubResource.pData, pixels, m_Width, m_Height, mappedSubResource.RowPitch, width, height, bInvert, m_bMirror, m_bSwapRB); + spoutcopy.rgba2rgbResample(mappedSubResource.pData, destpixels, m_Width, m_Height, mappedSubResource.RowPitch, width, height, bInvert, m_bMirror, m_bSwapRB); } else { // Approx 5 msec at 1920x1080 - spoutcopy.rgba2rgb(mappedSubResource.pData, pixels, m_Width, m_Height, mappedSubResource.RowPitch, bInvert, m_bMirror, m_bSwapRB); + spoutcopy.rgba2rgb(mappedSubResource.pData, destpixels, m_Width, m_Height, mappedSubResource.RowPitch, bInvert, m_bMirror, m_bSwapRB); } } - m_pImmediateContext->Unmap(pStagingTexture, 0); + m_pImmediateContext->Unmap(pStagingSource, 0); return true; } // endif DX11 map OK diff --git a/SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX.h b/SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX.h index f00b5caf..573ee2db 100644 --- a/SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX.h +++ b/SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX.h @@ -71,6 +71,8 @@ class SPOUT_DLLEXP spoutDX { void SetSenderFormat(DXGI_FORMAT format); // Close sender and free resources void ReleaseSender(); + // Send the back buffer + bool SendBackBuffer(); // Send a texture bool SendTexture(ID3D11Texture2D* pTexture); // Send an image @@ -199,7 +201,7 @@ class SPOUT_DLLEXP spoutDX { bool CreateDX11texture(ID3D11Device* pd3dDevice, unsigned int width, unsigned int height, DXGI_FORMAT format, ID3D11Texture2D** ppTexture); - + // // Data sharing // @@ -268,8 +270,11 @@ protected : bool ReceiveSenderData(); void CreateReceiver(const char * sendername, unsigned int width, unsigned int height, DWORD dwFormat); - // Read pixels via staging texture - bool ReadPixelData(ID3D11Texture2D* pStagingTexture, unsigned char* pixels, unsigned int width, unsigned int height, bool bRGB, bool bInvert); + // Read pixels from a staging texture + bool ReadPixelData(ID3D11Texture2D* pStagingSource, unsigned char* destpixels, + unsigned int width, unsigned int height, bool bRGB, bool bInvert, bool bSwap); + + // Create staging textures bool CheckStagingTextures(unsigned int width, unsigned int height, DWORD dwFormat = DXGI_FORMAT_B8G8R8A8_UNORM); bool CreateDX11StagingTexture(unsigned int width, unsigned int height, DXGI_FORMAT format, ID3D11Texture2D** pStagingTexture); diff --git a/SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX12/D3D12TriangleSender/D3D12HelloTriangle.cpp b/SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX12/D3D12TriangleSender/D3D12HelloTriangle.cpp index 6d5eff99..36e716b0 100644 --- a/SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX12/D3D12TriangleSender/D3D12HelloTriangle.cpp +++ b/SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX12/D3D12TriangleSender/D3D12HelloTriangle.cpp @@ -333,16 +333,10 @@ void D3D12HelloTriangle::OnRender() sender.SendDX11Resource(m_wrappedBackBuffers[m_frameIndex].Get()); // Present the frame. - ThrowIfFailed(m_swapChain->Present(1, 0)); + ThrowIfFailed(m_swapChain->Present(1, 0)); WaitForPreviousFrame(); - // - // SPOUT - fps control - // - // "sender.HoldFps(60);" can be used to hold a target frame rate - e.g. 60 or 30fps. - // Here it's not required because "Present(1, 0)" synchronizes to vertical blank. - } diff --git a/SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX9/Tut02_Vertices_Receiver/Vertices.cpp b/SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX9/Tut02_Vertices_Receiver/Vertices.cpp index 7cdf3b47..51bc6099 100644 --- a/SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX9/Tut02_Vertices_Receiver/Vertices.cpp +++ b/SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX9/Tut02_Vertices_Receiver/Vertices.cpp @@ -263,14 +263,6 @@ VOID Render() // Present the backbuffer contents to the display g_pd3dDevice->Present(NULL, NULL, NULL, NULL); - // - // SPOUT - fps control - // - // Hold a target frame rate - e.g. 60 or 30fps - // This is not necessary if the application already has fps control. - // If frame count is enabled, receivers will detect the sender fps - // sender.HoldFps(30); - } diff --git a/SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX9/Tut02_Vertices_Sender/Vertices.cpp b/SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX9/Tut02_Vertices_Sender/Vertices.cpp index de3554bc..b72c9509 100644 --- a/SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX9/Tut02_Vertices_Sender/Vertices.cpp +++ b/SPOUTSDK/SpoutDirectX/SpoutDX/SpoutDX9/Tut02_Vertices_Sender/Vertices.cpp @@ -271,14 +271,6 @@ VOID Render() // Present the backbuffer contents to the display g_pd3dDevice->Present(NULL, NULL, NULL, NULL); - // - // SPOUT - fps control - // - // Hold a target frame rate - e.g. 60 or 30fps - // This is not necessary if the application already has fps control. - // If frame count is enabled, receivers will detect the sender fps - // sender.HoldFps(30); - } diff --git a/SPOUTSDK/SpoutDirectX/SpoutDX/Tutorial04/Tutorial04.cpp b/SPOUTSDK/SpoutDirectX/SpoutDX/Tutorial04/Tutorial04.cpp index 39d72fb7..67ae1ebc 100644 --- a/SPOUTSDK/SpoutDirectX/SpoutDX/Tutorial04/Tutorial04.cpp +++ b/SPOUTSDK/SpoutDirectX/SpoutDX/Tutorial04/Tutorial04.cpp @@ -121,7 +121,7 @@ int WINAPI wWinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, // // Optionally enable logging to catch Spout warnings and errors - // OpenSpoutConsole(); // Console only for debugging + OpenSpoutConsole(); // Console only for debugging // EnableSpoutLog(); // Log to console // EnableSpoutLogFile("Tutorial04.log"); // Log to file // SetSpoutLogLevel(SPOUT_LOG_WARNING); // show only warnings and errors @@ -308,6 +308,7 @@ HRESULT InitDevice() // Graphics adapter selection requires a class device. // Don't forget to comment out the application device creation below + // =============================================================== if (sender.OpenDirectX11()) { // Set the application device and context to those created in the SpoutDX class @@ -318,6 +319,7 @@ HRESULT InitDevice() return 0; } // =============================================================== + /* // =============================================================== @@ -730,9 +732,6 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam //-------------------------------------------------------------------------------------- void Render() { - // - // SPOUT - // if (sender.IsInitialized()) { // Has the window changed size? if (!IsIconic(g_hWnd)) { @@ -796,28 +795,33 @@ void Render() // SPOUT // - // Get the swap chain's backbuffer to a texture for sending + // Option 1 + // Send the swap chain's back buffer. + // A single render target view is assumed. + // Sending functions handle sender creation and resizing. + // sender.SendBackBuffer(); + + // Option 2 + // Send a texture. + // In this example, we get the back buffer but the texture can be independent. ID3D11Texture2D* pBackBuffer = nullptr; HRESULT hr = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast(&pBackBuffer)); if (SUCCEEDED(hr)) { - // SendTexture handles sender creation and resizing sender.SendTexture(pBackBuffer); } - + // // Present our back buffer to our front buffer - // - g_pSwapChain->Present( 0, 0 ); - // // SPOUT - fps control // - // Hold a target frame rate/ e.g. 60 or 30fps - // use numerator an denominator e.g. 30000/2001 = 29.97 fps - // Here you could also use a different Present method such as - // "Present( 1, 0 )" to synchronize with vertical blank. - // Build with different options to explore. - sender.HoldFps(60); + // Here the frame rate can be extremely high. + // To avoid exessive processing, hold a target frame rate + // using a different sync interval for the Present method + // to synchronize with vertical blank, typically 60 fps. + // g_pSwapChain->Present( 0, 0 ); + g_pSwapChain->Present(1, 0); + } diff --git a/SPOUTSDK/SpoutDirectX/SpoutDX/Tutorial07/Tutorial07.cpp b/SPOUTSDK/SpoutDirectX/SpoutDX/Tutorial07/Tutorial07.cpp index f448d55a..f7db0082 100644 --- a/SPOUTSDK/SpoutDirectX/SpoutDX/Tutorial07/Tutorial07.cpp +++ b/SPOUTSDK/SpoutDirectX/SpoutDX/Tutorial07/Tutorial07.cpp @@ -589,34 +589,34 @@ HRESULT InitDevice() SimpleVertex vertices[] = { { XMFLOAT3( -1.0f, 1.0f, -1.0f ), XMFLOAT2( 1.0f, 0.0f ) }, - { XMFLOAT3( 1.0f, 1.0f, -1.0f ), XMFLOAT2( 0.0f, 0.0f ) }, - { XMFLOAT3( 1.0f, 1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, - { XMFLOAT3( -1.0f, 1.0f, 1.0f ), XMFLOAT2( 1.0f, 1.0f ) }, + { XMFLOAT3( 1.0f, 1.0f, -1.0f ), XMFLOAT2( 0.0f, 0.0f ) }, + { XMFLOAT3( 1.0f, 1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, + { XMFLOAT3( -1.0f, 1.0f, 1.0f ), XMFLOAT2( 1.0f, 1.0f ) }, { XMFLOAT3( -1.0f, -1.0f, -1.0f ), XMFLOAT2( 0.0f, 0.0f ) }, - { XMFLOAT3( 1.0f, -1.0f, -1.0f ), XMFLOAT2( 1.0f, 0.0f ) }, - { XMFLOAT3( 1.0f, -1.0f, 1.0f ), XMFLOAT2( 1.0f, 1.0f ) }, - { XMFLOAT3( -1.0f, -1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, + { XMFLOAT3( 1.0f, -1.0f, -1.0f ), XMFLOAT2( 1.0f, 0.0f ) }, + { XMFLOAT3( 1.0f, -1.0f, 1.0f ), XMFLOAT2( 1.0f, 1.0f ) }, + { XMFLOAT3( -1.0f, -1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, - { XMFLOAT3( -1.0f, -1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, + { XMFLOAT3( -1.0f, -1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, { XMFLOAT3( -1.0f, -1.0f, -1.0f ), XMFLOAT2( 1.0f, 1.0f ) }, - { XMFLOAT3( -1.0f, 1.0f, -1.0f ), XMFLOAT2( 1.0f, 0.0f ) }, - { XMFLOAT3( -1.0f, 1.0f, 1.0f ), XMFLOAT2( 0.0f, 0.0f ) }, + { XMFLOAT3( -1.0f, 1.0f, -1.0f ), XMFLOAT2( 1.0f, 0.0f ) }, + { XMFLOAT3( -1.0f, 1.0f, 1.0f ), XMFLOAT2( 0.0f, 0.0f ) }, - { XMFLOAT3( 1.0f, -1.0f, 1.0f ), XMFLOAT2( 1.0f, 1.0f ) }, + { XMFLOAT3( 1.0f, -1.0f, 1.0f ), XMFLOAT2( 1.0f, 1.0f ) }, { XMFLOAT3( 1.0f, -1.0f, -1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, - { XMFLOAT3( 1.0f, 1.0f, -1.0f ), XMFLOAT2( 0.0f, 0.0f ) }, - { XMFLOAT3( 1.0f, 1.0f, 1.0f ), XMFLOAT2( 1.0f, 0.0f ) }, + { XMFLOAT3( 1.0f, 1.0f, -1.0f ), XMFLOAT2( 0.0f, 0.0f ) }, + { XMFLOAT3( 1.0f, 1.0f, 1.0f ), XMFLOAT2( 1.0f, 0.0f ) }, { XMFLOAT3( -1.0f, -1.0f, -1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, - { XMFLOAT3( 1.0f, -1.0f, -1.0f ), XMFLOAT2( 1.0f, 1.0f ) }, - { XMFLOAT3( 1.0f, 1.0f, -1.0f ), XMFLOAT2( 1.0f, 0.0f ) }, - { XMFLOAT3( -1.0f, 1.0f, -1.0f ), XMFLOAT2( 0.0f, 0.0f ) }, + { XMFLOAT3( 1.0f, -1.0f, -1.0f ), XMFLOAT2( 1.0f, 1.0f ) }, + { XMFLOAT3( 1.0f, 1.0f, -1.0f ), XMFLOAT2( 1.0f, 0.0f ) }, + { XMFLOAT3( -1.0f, 1.0f, -1.0f ), XMFLOAT2( 0.0f, 0.0f ) }, { XMFLOAT3( -1.0f, -1.0f, 1.0f ), XMFLOAT2( 1.0f, 1.0f ) }, - { XMFLOAT3( 1.0f, -1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, - { XMFLOAT3( 1.0f, 1.0f, 1.0f ), XMFLOAT2( 0.0f, 0.0f ) }, - { XMFLOAT3( -1.0f, 1.0f, 1.0f ), XMFLOAT2( 1.0f, 0.0f ) }, + { XMFLOAT3( 1.0f, -1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, + { XMFLOAT3( 1.0f, 1.0f, 1.0f ), XMFLOAT2( 0.0f, 0.0f ) }, + { XMFLOAT3( -1.0f, 1.0f, 1.0f ), XMFLOAT2( 1.0f, 0.0f ) }, }; D3D11_BUFFER_DESC bd = {}; @@ -1013,16 +1013,16 @@ void Render() // // Present our back buffer to our front buffer // - g_pSwapChain->Present( 0, 0 ); - // // SPOUT - fps control // - // Hold a target frame rate - e.g. 60 or 30fps. - // Here you could also use a different Present method such as - // "Present( 1, 0 )" to synchronize with vertical blank. - // Build with different options to explore. - receiver.HoldFps(60); + // Here the frame rate can be extremely high. + // To avoid exessive processing, hold a target frame rate + // using a different sync interval for the Present method + // to synchronize with vertical blank, typically 60 fps. + // g_pSwapChain->Present( 0, 0 ); + g_pSwapChain->Present(1, 0); + } diff --git a/SPOUTSDK/SpoutGL/Spout.cpp b/SPOUTSDK/SpoutGL/Spout.cpp index d96c54fa..4abbd420 100644 --- a/SPOUTSDK/SpoutGL/Spout.cpp +++ b/SPOUTSDK/SpoutGL/Spout.cpp @@ -200,6 +200,9 @@ // 24.04.21 - ReceiveTexture - return if flagged for update // only if there is a texture to receive into. // 10.05.21 - ReceiveTexture - allow for the possibility of 2.006 memoryshare sender. +// 22.06.21 - Move code for GetSenderCount and GetSender to SpoutSenderNames class +// 03.07.21 - Use changed SpoutSenderNames "GetSender" function name. +// 04.07.21 - Additional code comments concerning update in ReceiveTexture. // // ==================================================================================== /* @@ -744,6 +747,9 @@ bool Spout::ReceiveTexture(GLuint TextureID, GLuint TextureTarget, bool bInvert, // Let the application know m_bConnected = true; + // If the connected sender sharehandle or name is different, + // the receiver is re-initialized and m_bUpdated is set true + // so that the application re-allocates the receiving texture. if (m_bUpdated) { // If the sender is new or changed, reset shared textures if (m_bTextureShare) { @@ -1013,41 +1019,15 @@ bool Spout::WaitFrameSync(const char *SenderName, DWORD dwTimeout) // Number of senders int Spout::GetSenderCount() { - std::set SenderNameSet; - if (sendernames.GetSenderNames(&SenderNameSet)) { - return((int)SenderNameSet.size()); - } - return 0; + return sendernames.GetSenderCount(); } //--------------------------------------------------------- // Function: GetSender // Sender item name in the sender names set -bool Spout::GetSender(int index, char* sendername, int sendernameMaxSize) +bool Spout::GetSender(int index, char* sendername, int MaxSize) { - std::set SenderNameSet; - std::set::iterator iter; - std::string namestring; - char name[256]; - int i; - - if (sendernames.GetSenderNames(&SenderNameSet)) { - if (SenderNameSet.size() < (unsigned int)index) { - return false; - } - i = 0; - for (iter = SenderNameSet.begin(); iter != SenderNameSet.end(); iter++) { - namestring = *iter; // the name string - strcpy_s(name, 256, namestring.c_str()); // the 256 byte name char array - if (i == index) { - strcpy_s(sendername, sendernameMaxSize, name); // the passed name char array - break; - } - i++; - } - return true; - } - return false; + return sendernames.GetSender(index, sendername, MaxSize); } //--------------------------------------------------------- @@ -2019,6 +1999,7 @@ bool Spout::ReceiveSenderData() // We have a valid share handle if (m_dxShareHandle) { + // Get a new shared texture pointer (m_pSharedTexture) if (!spoutdx.OpenDX11shareHandle(spoutdx.GetDX11Device(), &m_pSharedTexture, dxShareHandle)) { // If this fails, something is wrong. @@ -2047,6 +2028,22 @@ bool Spout::ReceiveSenderData() // Connected and intialized // Sender name, width, height, format, texture pointer and share handle have been retrieved + // LJ DEBUG + // printf(" m_dxShareHandle = 0x%7X : m_pSharedTexture = 0x%7X\n", PtrToUint(m_dxShareHandle), PtrToUint(m_pSharedTexture)); + + // ID3D11Texture2D * texturePointer = m_pSharedTexture; + // D3D11_TEXTURE2D_DESC td; + // texturePointer->GetDesc(&td); + // printf("td.Format = %d\n", td.Format); // 87 + // printf("td.Width = %d\n", td.Width); + // printf("td.Height = %d\n", td.Height); + // printf("td.MipLevels = %d\n", td.MipLevels); + // printf("td.Usage = %d\n", td.Usage); + // printf("td.ArraySize = %d\n", td.ArraySize); + // printf("td.SampleDesc = %d\n", (int)td.SampleDesc); + // printf("td.BindFlags = %d\n", td.BindFlags); + // printf("td.MiscFlags = %d\n", td.MiscFlags); // D3D11_RESOURCE_MISC_SHARED + // The application can now access and copy the sender texture return true; @@ -2063,7 +2060,6 @@ bool Spout::CheckSpoutPanel(char *sendername, int maxchars) { // If SpoutPanel has been activated, test if the user has clicked OK if (m_bSpoutPanelOpened) { // User has activated spout panel - SharedTextureInfo TextureInfo; HANDLE hMutex = NULL; DWORD dwExitCode; @@ -2120,6 +2116,7 @@ bool Spout::CheckSpoutPanel(char *sendername, int maxchars) return bRet; } // SpoutPanel has not been opened + return false; } diff --git a/SPOUTSDK/SpoutGL/SpoutCommon.h b/SPOUTSDK/SpoutGL/SpoutCommon.h index cebad5b0..24f898b4 100644 --- a/SPOUTSDK/SpoutGL/SpoutCommon.h +++ b/SPOUTSDK/SpoutGL/SpoutCommon.h @@ -57,7 +57,7 @@ // This definition enables legacy OpenGL rendering code // used for shared texture Draw functions in SpoutGLDXinterop.cpp // Disabled by default for OpenGL 4 compliance -#define legacyOpenGL +// #define legacyOpenGL // Common utility functions namespace #include "SpoutUtils.h" diff --git a/SPOUTSDK/SpoutGL/SpoutCopy.cpp b/SPOUTSDK/SpoutGL/SpoutCopy.cpp index a2862f80..4a13c4d8 100644 --- a/SPOUTSDK/SpoutGL/SpoutCopy.cpp +++ b/SPOUTSDK/SpoutGL/SpoutCopy.cpp @@ -52,6 +52,8 @@ 26.10.20 - Add rgb2bgra with dest pitch 09.12.20 - Correct movsd line pitch in RemovePadding 13.03.21 - Change CopyPixels and FlipBuffer to accept GL_LUMINANCE + 09.07.21 - memcpy_sse2 - return for null dst or src + */ #include "SpoutCopy.h" @@ -191,6 +193,10 @@ void spoutCopy::RemovePadding(const unsigned char *source, unsigned char *dest, // void spoutCopy::memcpy_sse2(void* dst, const void* src, size_t Size) const { + + if (!dst || !src) + return; + auto pSrc = static_cast(src); // Source buffer auto pDst = static_cast(dst); // Destination buffer unsigned int n = (unsigned int)Size >> 7; // Counter = size divided by 128 (8 * 128bit registers) diff --git a/SPOUTSDK/SpoutGL/SpoutDirectX.cpp b/SPOUTSDK/SpoutGL/SpoutDirectX.cpp index fd2bee9b..3233c6c0 100644 --- a/SPOUTSDK/SpoutGL/SpoutDirectX.cpp +++ b/SPOUTSDK/SpoutGL/SpoutDirectX.cpp @@ -90,6 +90,7 @@ // 09.12.20 - CloseDirectX11() in destructor // 27.12.20 - Change all hex printf to 0x%.7X with PtrToUint helper // 20.02.21 - Add zero width/height check to CreateDX11Texture +// 19.06.21 - Remove output check from FindNVIDIA // // ==================================================================================== /* @@ -599,21 +600,19 @@ bool spoutDirectX::OpenDX11shareHandle(ID3D11Device* pDevice, ID3D11Texture2D** } - /* // Can get sender format here - ID3D11Texture2D * texturePointer = *ppSharedTexture; - D3D11_TEXTURE2D_DESC td; - texturePointer->GetDesc(&td); - printf("td.Format = %d\n", td.Format); // 87 - printf("td.Width = %d\n", td.Width); - printf("td.Height = %d\n", td.Height); - printf("td.MipLevels = %d\n", td.MipLevels); - printf("td.Usage = %d\n", td.Usage); - printf("td.ArraySize = %d\n", td.ArraySize); - printf("td.SampleDesc = %d\n", td.SampleDesc); - printf("td.BindFlags = %d\n", td.BindFlags); - printf("td.MiscFlags = %d\n", td.MiscFlags); // D3D11_RESOURCE_MISC_SHARED - */ + // ID3D11Texture2D * texturePointer = *ppSharedTexture; + // D3D11_TEXTURE2D_DESC td; + // texturePointer->GetDesc(&td); + // printf("td.Format = %d\n", td.Format); // 87 + // printf("td.Width = %d\n", td.Width); + // printf("td.Height = %d\n", td.Height); + // printf("td.MipLevels = %d\n", td.MipLevels); + // printf("td.Usage = %d\n", td.Usage); + // printf("td.ArraySize = %d\n", td.ArraySize); + // printf("td.SampleDesc = %d\n", td.SampleDesc); + // printf("td.BindFlags = %d\n", td.BindFlags); + // printf("td.MiscFlags = %d\n", td.MiscFlags); // D3D11_RESOURCE_MISC_SHARED return true; @@ -703,7 +702,8 @@ int spoutDirectX::GetAdapter() } -// FOR DEBUGGING +// For purposes where NVIDIA hardware acceleration is used +// e.g. FFmpeg bool spoutDirectX::FindNVIDIA(int &nAdapter) { IDXGIFactory1* _dxgi_factory1; @@ -720,10 +720,10 @@ bool spoutDirectX::FindNVIDIA(int &nAdapter) // printf("spoutDirectX::FindNVIDIA - Adapter(%d) : %S\n", i, desc.Description ); DXGI_OUTPUT_DESC desc_out; IDXGIOutput* p_output = nullptr; - if(adapter1_ptr->EnumOutputs(0, &p_output ) == DXGI_ERROR_NOT_FOUND) { + // if(adapter1_ptr->EnumOutputs(0, &p_output ) == DXGI_ERROR_NOT_FOUND) { // printf(" No outputs\n"); - continue; - } + // continue; + // } for ( UINT32 j = 0; adapter1_ptr->EnumOutputs( j, &p_output ) != DXGI_ERROR_NOT_FOUND; j++ ) { if (p_output) { diff --git a/SPOUTSDK/SpoutGL/SpoutFrameCount.cpp b/SPOUTSDK/SpoutGL/SpoutFrameCount.cpp index 9d4a2126..f1077397 100644 --- a/SPOUTSDK/SpoutGL/SpoutFrameCount.cpp +++ b/SPOUTSDK/SpoutGL/SpoutFrameCount.cpp @@ -37,6 +37,7 @@ // SetFrameSync/WaitFrameSync/OpenFrameSync/CloseFrameSync // 07.04.21 - CloseFrameSync public for use by other classes // 17.04.21 - WaitFrameSync - close handle on error +// 21.07.21 - Remove debug comment // // ==================================================================================== // @@ -317,7 +318,8 @@ void spoutFrameCount::SetNewFrame() SpoutLogError("spoutFrameCount::SetNewFrame - ReleaseSemaphore failed"); } else { - m_FrameCount++; // Increment the sender frame count + // Increment the sender frame count + m_FrameCount++; // Update the sender fps calculations for the new frame UpdateSenderFps(1); } @@ -490,7 +492,7 @@ void spoutFrameCount::HoldFps(int fps) #ifdef USE_CHRONO // Initialize frame time at target rate - if (m_millisForFrame < 0.01) { + if (m_millisForFrame < 0.001) { m_millisForFrame = 1000.0 / framerate; // msec per frame *m_FrameStartPtr = std::chrono::steady_clock::now(); SpoutLogNotice("spoutFrameCount::HoldFps(%.2f)", framerate); @@ -623,12 +625,12 @@ bool spoutFrameCount::CheckAccess() // Typically 2-3 microseconds. // 10 receivers - no increase. // Note that NVIDIA "Threaded optimization" can cause delay - // for WaitForSingleObject and is set OFF by SpoutSettinngs - + // for WaitForSingleObject and can be set OFF by SpoutSettinngs DWORD dwWaitResult = WaitForSingleObject(m_hAccessMutex, 67); // timeout 4 frames at 60fps switch (dwWaitResult) { case WAIT_OBJECT_0 : // The state of the object is signalled. + // The thread got ownership of the mutex return true; case WAIT_ABANDONED: SpoutLogError("spoutFrameCount::CheckAccess - WAIT_ABANDONED"); @@ -871,6 +873,7 @@ void spoutFrameCount::UpdateSenderFps(long framecount) m_lastFrame = thisFrame; #endif } + } // ----------------------------------------------- diff --git a/SPOUTSDK/SpoutGL/SpoutGL.cpp b/SPOUTSDK/SpoutGL/SpoutGL.cpp index b41a8ee8..d7b494d7 100644 --- a/SPOUTSDK/SpoutGL/SpoutGL.cpp +++ b/SPOUTSDK/SpoutGL/SpoutGL.cpp @@ -47,6 +47,7 @@ // 09.06.21 - Add CreateMemoryBuffer, DeleteMemoryBuffer // Revise and test data functions // All data functions return false if 2.006 memoryshare mode. +// 26.07.21 - Remove memorysize check from GetMemoryBufferSize for receiver // // ==================================================================================== /* @@ -1386,12 +1387,14 @@ bool spoutGL::SetSharedTextureData(GLuint TextureID, GLuint TextureTarget, unsig status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if (status == GL_FRAMEBUFFER_COMPLETE_EXT) { if (m_bBLITavailable) { - if (bInvert) + if (bInvert) { // copy from one framebuffer to the other while flipping upside down glBlitFramebufferEXT(0, 0, width, height, 0, height, width, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST); - else + } + else { // Do not flip during blit glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } } else { // No fbo blit extension @@ -1674,7 +1677,6 @@ bool spoutGL::UnloadTexturePixels(GLuint TextureID, GLuint TextureTarget, } - // // Copy OpenGL to DirectX 11 texture via CPU where the GL/DX interop is not available // @@ -2006,7 +2008,7 @@ bool spoutGL::CreateMemoryBuffer(const char *name, int length) _itoa_s(length, reinterpret_cast(pBuffer), 16, 10); memoryshare.Unlock(); - SpoutLogNotice("spoutGL::CreateMemoryBuffer - created shared memory buffer %d bytes", (length+32)); + SpoutLogNotice("spoutGL::CreateMemoryBuffer - created shared memory buffer %d bytes", length); return true; } @@ -2043,9 +2045,6 @@ bool spoutGL::DeleteMemoryBuffer() // int spoutGL::GetMemoryBufferSize(const char *name) { - if (!m_bInitialized) - return 0; - // A writer has created the map and recorded the data length in the first 16 bytes. // Another 16 bytes is added to allow for a terminating NULL. (See CreateMemoryBuffer) // The remaining length is the number of bytes available for data transfer. diff --git a/SPOUTSDK/SpoutGL/SpoutGL.h b/SPOUTSDK/SpoutGL/SpoutGL.h index 73ad54f9..3828d55f 100644 --- a/SPOUTSDK/SpoutGL/SpoutGL.h +++ b/SPOUTSDK/SpoutGL/SpoutGL.h @@ -292,7 +292,7 @@ protected : unsigned int width, unsigned int height, unsigned int pitch, unsigned char* data, GLenum glFormat = GL_RGBA, bool bInvert = false, GLuint HostFBO = 0); - + // OpenGL <-> DX11 // WriteDX11texture - public // ReadDX11texture - public diff --git a/SPOUTSDK/SpoutGL/SpoutSenderNames.cpp b/SPOUTSDK/SpoutGL/SpoutSenderNames.cpp index be4c7bb1..c2cccf72 100644 --- a/SPOUTSDK/SpoutGL/SpoutSenderNames.cpp +++ b/SPOUTSDK/SpoutGL/SpoutSenderNames.cpp @@ -72,6 +72,12 @@ 27.02.21 - Change SetSenderCPUmode name to SetSenderID 09.04.21 - Add GetSender to retrieve class sender. Remove SenderDebug + 22.06.21 - Restore 2.006 GetSenderNames function + 03.07.21 - Change GetSenderNames to GetSender to align with Spout class. + Change existing GetSender to FindSenderName. + - Change duplicate FindSenderName to FindSender overload + testing function + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Copyright (c) 2014-2021, Lynn Jarvis. All rights reserved. @@ -386,6 +392,34 @@ int spoutSenderNames::GetSenderCount() { return 0; } +bool spoutSenderNames::GetSender(int index, char* sendername, int sendernameMaxSize) +{ + std::set SenderNameSet; + std::set::iterator iter; + std::string namestring; + char name[256]; + int i; + + if (GetSenderNames(&SenderNameSet)) { + if (SenderNameSet.size() < (unsigned int)index) { + return false; + } + i = 0; + for (iter = SenderNameSet.begin(); iter != SenderNameSet.end(); iter++) { + namestring = *iter; // the name string + strcpy_s(name, 256, namestring.c_str()); // the 256 byte name char array + if (i == index) { + strcpy_s(sendername, sendernameMaxSize, name); // the passed name char array + break; + } + i++; + } + return true; + } + return false; + +} + // Get sender info given a sender index and knowing the sender count // index - in // sendername - out @@ -827,8 +861,9 @@ bool spoutSenderNames::FindSender(char *sendername, unsigned int &width, unsigne } // end FindSender -// Get sender in this class -bool spoutSenderNames::GetSender(const char* sendername) +// Find a sender in the class names set +// Used for testing - may be removed +bool spoutSenderNames::FindSender(const char* sendername) { std::string namestring = sendername; if (m_senders->find(namestring) != m_senders->end()) diff --git a/SPOUTSDK/SpoutGL/SpoutSenderNames.h b/SPOUTSDK/SpoutGL/SpoutSenderNames.h index b9e67111..b6a69273 100644 --- a/SPOUTSDK/SpoutGL/SpoutSenderNames.h +++ b/SPOUTSDK/SpoutGL/SpoutSenderNames.h @@ -111,9 +111,12 @@ class SPOUT_DLLEXP spoutSenderNames { bool GetSenderNames(std::set *sendernames); // Number of senders in the list int GetSenderCount(); + // Sender item name + bool GetSender(int index, char* sendername, int MaxSize = 256); // Information about a sender from an index into the list bool GetSenderNameInfo(int index, char* sendername, int sendernameMaxSize, unsigned int &width, unsigned int &height, HANDLE &dxShareHandle); + // // Maximum number of senders allowed in the list // Applies for versions 2.005 and after @@ -167,8 +170,8 @@ class SPOUT_DLLEXP spoutSenderNames { bool CheckSender (const char* sendername, unsigned int &width, unsigned int &height, HANDLE &hSharehandle, DWORD &dwFormat); // Find a sender and return details bool FindSender (char* sendername, unsigned int &width, unsigned int &height, HANDLE &hSharehandle, DWORD &dwFormat); - // Get sender in this class - bool GetSender(const char* sendername); + // Find a sender in the class names set + bool FindSender (const char* sendername); // Release orphaned senders void CleanSenders(); diff --git a/SPOUTSDK/SpoutGL/SpoutUtils.cpp b/SPOUTSDK/SpoutGL/SpoutUtils.cpp index db559166..05c19140 100644 --- a/SPOUTSDK/SpoutGL/SpoutUtils.cpp +++ b/SPOUTSDK/SpoutGL/SpoutUtils.cpp @@ -71,6 +71,9 @@ Bring the main window to the top again 07.05.21 - Remove noisy warning from ReadPathFromRegistry 09.06.21 - Update Version to "2.007.002" + 26.07.21 - Update Version to "2.007.003" + + */ #include "SpoutUtils.h" @@ -638,7 +641,7 @@ namespace spoututils { #ifdef USE_CHRONO end = std::chrono::steady_clock::now(); double elapsed = static_cast(std::chrono::duration_cast(end - start).count()); - // printf(" elapsed [%.4f] msec\n", elapsed / 1000.0); + printf(" elapsed [%.4f] msec\n", elapsed / 1000.0); // printf("elapsed [%.3f] u/sec\n", elapsed); return elapsed; #else diff --git a/SPOUTSDK/SpoutLibrary/Binaries/Win32/SpoutLibrary.dll b/SPOUTSDK/SpoutLibrary/Binaries/Win32/SpoutLibrary.dll index 24dd738b..226852ba 100644 Binary files a/SPOUTSDK/SpoutLibrary/Binaries/Win32/SpoutLibrary.dll and b/SPOUTSDK/SpoutLibrary/Binaries/Win32/SpoutLibrary.dll differ diff --git a/SPOUTSDK/SpoutLibrary/Binaries/Win32/SpoutLibrary.h b/SPOUTSDK/SpoutLibrary/Binaries/Win32/SpoutLibrary.h index f0c0ffc6..7602715a 100644 --- a/SPOUTSDK/SpoutLibrary/Binaries/Win32/SpoutLibrary.h +++ b/SPOUTSDK/SpoutLibrary/Binaries/Win32/SpoutLibrary.h @@ -48,7 +48,9 @@ #endif // Local log level definitions -enum LogLevel { +// SpoutLogLevel conflicts with previous definition +// LogLevel is too generic +enum LibLogLevel { SPOUT_LOG_SILENT, SPOUT_LOG_VERBOSE, SPOUT_LOG_NOTICE, @@ -177,13 +179,19 @@ struct SPOUTLIBRARY virtual bool WaitFrameSync(const char *SenderName, DWORD dwTimeout = 0) = 0; // - // Memory sharing + // Data sharing // // Write data virtual bool WriteMemoryBuffer(const char *sendername, const char* data, int length) = 0; // Read data virtual int ReadMemoryBuffer(const char* sendername, char* data, int maxlength) = 0; + // Create a shared memory buffer + virtual bool CreateMemoryBuffer(const char *name, int length) = 0; + // Delete a shared memory buffer + virtual bool DeleteMemoryBuffer() = 0; + // Get the number of bytes available for data transfer + virtual int GetMemoryBufferSize(const char *name) = 0; // // Log utilities @@ -210,7 +218,7 @@ struct SPOUTLIBRARY // SPOUT_LOG_WARNING - Something might go wrong // SPOUT_LOG_ERROR - Something did go wrong // SPOUT_LOG_FATAL - Something bad happened - virtual void SetSpoutLogLevel(LogLevel level) = 0; + virtual void SetSpoutLogLevel(LibLogLevel level) = 0; // General purpose log virtual void SpoutLog(const char* format, ...) = 0; // Verbose - show log for SPOUT_LOG_VERBOSE or above diff --git a/SPOUTSDK/SpoutLibrary/Binaries/Win32/SpoutLibrary.lib b/SPOUTSDK/SpoutLibrary/Binaries/Win32/SpoutLibrary.lib index 103b344b..e50762da 100644 Binary files a/SPOUTSDK/SpoutLibrary/Binaries/Win32/SpoutLibrary.lib and b/SPOUTSDK/SpoutLibrary/Binaries/Win32/SpoutLibrary.lib differ diff --git a/SPOUTSDK/SpoutLibrary/Binaries/x64/SpoutLibrary.dll b/SPOUTSDK/SpoutLibrary/Binaries/x64/SpoutLibrary.dll index a481b9b0..d21a54e0 100644 Binary files a/SPOUTSDK/SpoutLibrary/Binaries/x64/SpoutLibrary.dll and b/SPOUTSDK/SpoutLibrary/Binaries/x64/SpoutLibrary.dll differ diff --git a/SPOUTSDK/SpoutLibrary/Binaries/x64/SpoutLibrary.h b/SPOUTSDK/SpoutLibrary/Binaries/x64/SpoutLibrary.h index f0c0ffc6..7602715a 100644 --- a/SPOUTSDK/SpoutLibrary/Binaries/x64/SpoutLibrary.h +++ b/SPOUTSDK/SpoutLibrary/Binaries/x64/SpoutLibrary.h @@ -48,7 +48,9 @@ #endif // Local log level definitions -enum LogLevel { +// SpoutLogLevel conflicts with previous definition +// LogLevel is too generic +enum LibLogLevel { SPOUT_LOG_SILENT, SPOUT_LOG_VERBOSE, SPOUT_LOG_NOTICE, @@ -177,13 +179,19 @@ struct SPOUTLIBRARY virtual bool WaitFrameSync(const char *SenderName, DWORD dwTimeout = 0) = 0; // - // Memory sharing + // Data sharing // // Write data virtual bool WriteMemoryBuffer(const char *sendername, const char* data, int length) = 0; // Read data virtual int ReadMemoryBuffer(const char* sendername, char* data, int maxlength) = 0; + // Create a shared memory buffer + virtual bool CreateMemoryBuffer(const char *name, int length) = 0; + // Delete a shared memory buffer + virtual bool DeleteMemoryBuffer() = 0; + // Get the number of bytes available for data transfer + virtual int GetMemoryBufferSize(const char *name) = 0; // // Log utilities @@ -210,7 +218,7 @@ struct SPOUTLIBRARY // SPOUT_LOG_WARNING - Something might go wrong // SPOUT_LOG_ERROR - Something did go wrong // SPOUT_LOG_FATAL - Something bad happened - virtual void SetSpoutLogLevel(LogLevel level) = 0; + virtual void SetSpoutLogLevel(LibLogLevel level) = 0; // General purpose log virtual void SpoutLog(const char* format, ...) = 0; // Verbose - show log for SPOUT_LOG_VERBOSE or above diff --git a/SPOUTSDK/SpoutLibrary/Binaries/x64/SpoutLibrary.lib b/SPOUTSDK/SpoutLibrary/Binaries/x64/SpoutLibrary.lib index f18c6fcf..2d98897b 100644 Binary files a/SPOUTSDK/SpoutLibrary/Binaries/x64/SpoutLibrary.lib and b/SPOUTSDK/SpoutLibrary/Binaries/x64/SpoutLibrary.lib differ diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibrary.cpp b/SPOUTSDK/SpoutLibrary/SpoutLibrary.cpp index 02eb130c..17e8f917 100644 --- a/SPOUTSDK/SpoutLibrary/SpoutLibrary.cpp +++ b/SPOUTSDK/SpoutLibrary/SpoutLibrary.cpp @@ -62,7 +62,9 @@ // Re-build 32/64 bit - VS2017 / MT // 24.04.21 - ReceiveTexture - return if flagged for update // 10.06.21 - Re-build 32/64 bit - VS2017 / MT - +// 20.07.21 - Change generic local log level definition to avoid +// conflict with other libraries and applications. +// 25.07.21 Re-build 32/64 bit - VS2017 / Multi-threaded DLL (/MD) // /* Copyright (c) 2016-2021, Lynn Jarvis. All rights reserved. @@ -449,7 +451,7 @@ class SPOUTImpl : public SPOUTLIBRARY bool WaitFrameSync(const char *SenderName, DWORD dwTimeout = 0); // - // Group: Memory sharing + // Group: Data sharing // // General purpose data exchange functions using shared memory. // These functions can be used in addition to texture sharing. @@ -568,7 +570,7 @@ class SPOUTImpl : public SPOUTLIBRARY // Function: SetSpoutLogLevel // Set the current log level - void SetSpoutLogLevel(LogLevel level); + void SetSpoutLogLevel(LibLogLevel level); // Function: SpoutLog // General purpose log @@ -1145,7 +1147,7 @@ void SPOUTImpl::DisableSpoutLog() spoututils::DisableSpoutLog(); } -void SPOUTImpl::SetSpoutLogLevel(LogLevel level) +void SPOUTImpl::SetSpoutLogLevel(LibLogLevel level) { spoututils::SetSpoutLogLevel((SpoutLogLevel)level); } diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibrary.h b/SPOUTSDK/SpoutLibrary/SpoutLibrary.h index e0d615fd..7602715a 100644 --- a/SPOUTSDK/SpoutLibrary/SpoutLibrary.h +++ b/SPOUTSDK/SpoutLibrary/SpoutLibrary.h @@ -48,7 +48,9 @@ #endif // Local log level definitions -enum LogLevel { +// SpoutLogLevel conflicts with previous definition +// LogLevel is too generic +enum LibLogLevel { SPOUT_LOG_SILENT, SPOUT_LOG_VERBOSE, SPOUT_LOG_NOTICE, @@ -216,7 +218,7 @@ struct SPOUTLIBRARY // SPOUT_LOG_WARNING - Something might go wrong // SPOUT_LOG_ERROR - Something did go wrong // SPOUT_LOG_FATAL - Something bad happened - virtual void SetSpoutLogLevel(LogLevel level) = 0; + virtual void SetSpoutLogLevel(LibLogLevel level) = 0; // General purpose log virtual void SpoutLog(const char* format, ...) = 0; // Verbose - show log for SPOUT_LOG_VERBOSE or above diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/readme.txt b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/README_FIRST.TXT similarity index 67% rename from SPOUTSDK/SpoutLibrary/SpoutLibraryExample/readme.txt rename to SPOUTSDK/SpoutLibrary/SpoutLibraryExample/README_FIRST.TXT index 769f61e6..c099a625 100644 --- a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/readme.txt +++ b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/README_FIRST.TXT @@ -12,7 +12,6 @@ C:\OPENFRAMEWORKS SpoutLibraryExample <- copy the entire example folder here (under "apps\myApps") ofSpoutLibrary.sln ofSpoutLibrary.vcxproj - ofSpoutLibrary.vcxproj.filters src <- SpoutLibrary.h and source files bin <- SpoutLibrary.dll and data files libs <- SpoutLibrary.lib @@ -22,5 +21,13 @@ Open the solution file with Visual Studio 2017, set to "Release" and build. Source files The "src" folder contains files for a Sender example. -The "Sources" folder contains files for both Sender and Receiver. -For the one you want copy "ofApp.h" and "ofApp.cpp" to the "src" folder and "Rebuild". +The "Sources" folder contains files for : + Sender + Receiver + Dynamic (Bare bones sender with dynamic load of SpoutLibrary) +For the one you want copy the source files to the "src" folder and "Rebuild". + +Binaries + +your compiled example will be in the "bin" folder. There are also pre-built binaries that you can test with. + diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/Source/Dynamic/SpoutLibraryLoader.h b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/Source/Dynamic/SpoutLibraryLoader.h new file mode 100644 index 00000000..8295e0e1 --- /dev/null +++ b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/Source/Dynamic/SpoutLibraryLoader.h @@ -0,0 +1,134 @@ +// +// SpoutLibraryLoader.h +// +// Dynamic load of SpoutLibrary.dll +// +// Use this if SpoutLibrary.lib is not compatible with your compiler, +// or to allow user update of SpoutLibrary.dll if the disributed library +// build has been updated with SDK updates but the functions have not changed. +// + +/* + Copyright (c) 2021, Lynn Jarvis. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#pragma once + +#ifndef __SpoutLibraryLoader__ +#define __SpoutLibraryLoader__ + +#include "SpoutLibrary.h" +#include +#include +#pragma comment(lib, "Shlwapi.lib") // for path functions + +struct SpoutLibraryLoader +{ + +public: + + SpoutLibraryLoader() {}; + ~SpoutLibraryLoader() {}; + + // + // Load SpoutLibrary.dll dynamically + // + // The dll file must be in the same folder as the executable. + // The dll type (Win32 or x64) must match the executable. + // + SPOUTLIBRARY * LoadSpoutLibrary() + { + // + // To avoid anti-virus false positive detections, SpoutLibrary.dll is + // distributed compiled as "Multi-threaded DLL (/MD)" and requires the + // Visual Studio runtime dlls to be installed on the system. + // Visual C++ 2015, 2017 and 2019 all share the same redistributable files. + // + // https://support.microsoft.com/en-us/topic/the-latest-supported-visual-c-downloads-2647da03-1eea-4433-9aff-95f26a218cc0 + // + // If you build the library yourself, you can use "Multi-threaded (/MT)" + // to embed the runtime in the dll. Then you can remove the following check. + // + + // Check for VS2017 runtime. + // For 64-bit VC++ Redistributable + // HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\x64 + // For 32 - bit VC++ Redistributable + // HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\x86 + HKEY hRegKey = NULL; + LONG regres = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wow6432Node\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes", NULL, KEY_READ, &hRegKey); + if (regres != ERROR_SUCCESS) { + MessageBoxA(NULL, "Could not find VS2017 runtimes\nInstall from the VS2015-2019 folder\nof the Spout distribution.", "Error", MB_OK); + return nullptr; + } + + // + // Look in the executable folder for the dll file. + // + + // Get the executable path. + char filepath[MAX_PATH]; + if (GetModuleFileNameA(NULL, filepath, sizeof(filepath)) == 0) + return nullptr; + + // Remove executable file name and replace with the dll file name + PathRemoveFileSpecA(filepath); + strcat_s(filepath, MAX_PATH, "\\SpoutLibrary.dll"); + + // Now we have the full path of the dll file. + // Does the file exist ? + if (_access(filepath, 0) == -1) + return nullptr; + + // Get a handle to the dll module + hSpoutLib = LoadLibraryA(filepath); + if (hSpoutLib == NULL) + return nullptr; + + // Try to get the address of the function that creates an instance of SpoutLibrary. + // Credit to Newtek NDI (https://www.ndi.tv/) dynamic load example for this code. + SPOUTLIBRARY * (*GetSpout)(void) = nullptr; + *((FARPROC*)&GetSpout) = GetProcAddress(hSpoutLib, "GetSpout"); + if (GetSpout == NULL) + return nullptr; + + // Now we can create an instance of the library and access all the functions in it. + // The dll LoadLibrary handle (hSpoutLib) must be freed on exit using FreeSpoutLibrary() + + return GetSpout(); + } + + void FreeSpoutLibrary() + { + if (hSpoutLib) + FreeLibrary(hSpoutLib); + } + +private: + + HINSTANCE hSpoutLib = nullptr; + +}; + +#endif diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/Source/Dynamic/main.cpp b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/Source/Dynamic/main.cpp new file mode 100644 index 00000000..5b8b2a75 --- /dev/null +++ b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/Source/Dynamic/main.cpp @@ -0,0 +1,46 @@ +#include "ofMain.h" +#include "ofApp.h" + +/* + ========================================================================= + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . + ========================================================================= +*/ + +//-------------------------------------------------------------- +// to change options for console window (Visual Studio) +// +// Properties > Linker > System > Subsystem +// for console : Windows (/SUBSYSTEM:CONSOLE) +// +// for Window : Windows (/SUBSYSTEM:WINDOWS) +// +// Click APPLY and OK. Then make changes to Main as below +//-------------------------------------------------------------- + +// for default console +//======================================================================== +int main() { +// +// for window without console +//======================================================================== +// int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { + + ofSetupOpenGL(640, 360, OF_WINDOW); // <-------- setup the GL context + // this kicks off the running of my app + // can be OF_WINDOW or OF_FULLSCREEN + // pass in width and height too: + ofRunApp( new ofApp()); + +} diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/Source/Dynamic/ofApp.cpp b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/Source/Dynamic/ofApp.cpp new file mode 100644 index 00000000..b21b270f --- /dev/null +++ b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/Source/Dynamic/ofApp.cpp @@ -0,0 +1,117 @@ +/* + + Spout OpenFrameworks SpoutLibrary dll dynamic Load example + + The SpoutLibrary.lib file does not need to be linked during build + + Spout 2.007 + OpenFrameworks 11 + Visual Studio 2017 + + Copyright (C) 2021 Lynn Jarvis. + + ========================================================================= + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . + ========================================================================= +*/ +#include "ofApp.h" + +//-------------------------------------------------------------- +void ofApp::setup(){ + + ofBackground(10, 100, 140); + + // Try to load SpoutLibrary.dll + // The dll file must be in the same folder as the executable. + // The dll type (Win32 or x64) must match that of the executable. + sender = spoutloader.LoadSpoutLibrary(); + if (!sender) { + MessageBoxA(NULL, "SpoutLibrary dll not found", "Error", MB_OK); + ofExit(); + } + + // Now use the library functions as usual + sender->EnableSpoutLog(); + + // Give the sender a name + sender->SetSenderName("OF Spout Dynamic Load Sender"); + + // Also show it on the title bar + ofSetWindowTitle("OF Spout Dynamic Load Sender"); + + // 3D drawing setup for the demo + ofDisableArbTex(); // Needed for ofBox texturing + ofEnableDepthTest(); // enable depth comparisons for the cube + myBoxImage.load("SpoutBox1.png"); // image for the cube texture + rotX = 0.0f; + rotY = 0.0f; + + // Framerate is default 60fps for driver vsync enabled + +} // end setup + + +//-------------------------------------------------------------- +void ofApp::update() { + +} + +//-------------------------------------------------------------- +void ofApp::draw() { + + // Draw graphics + ofClear(10, 100, 140, 255); + ofPushMatrix(); + ofTranslate(ofGetWidth() / 2.0, ofGetHeight() / 2.0, 0); // centre the cube + ofRotateYDeg(rotX); // rotate the cube + ofRotateXDeg(rotY); + myBoxImage.bind(); // bind our box face image + ofDrawBox(0.4*ofGetHeight()); // draw the box + myBoxImage.unbind(); + ofPopMatrix(); + rotX += 0.6; + rotY += 0.6; + + // Send the default framebuffer (SendFbo handles re-sizing) + sender->SendFbo(0, ofGetWidth(), ofGetHeight()); + + // Show what it is sending + ofSetColor(255); + std::string str = "Sending as : "; + str += sender->GetName(); str += " ("; + str += ofToString(sender->GetWidth()); str += "x"; + str += ofToString(sender->GetHeight()); str += ")"; + if (sender->GetFrame() > 0) { + str += " fps "; + str += ofToString((int)roundf(sender->GetFps())); + str += " : frame "; + str += ofToString(sender->GetFrame()); + } + else { + // Openframeworks fps + str += " fps : " + ofToString((int)roundf(ofGetFrameRate())); + } + ofDrawBitmapString(str, 10, 20); + +} + +//-------------------------------------------------------------- +void ofApp::exit() { + // Release the sender on exit + sender->ReleaseSender(); + // Release SpoutLibrary + sender->Release(); + // Free the loaded dll + spoutloader.FreeSpoutLibrary(); +} diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/Source/Dynamic/ofApp.h b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/Source/Dynamic/ofApp.h new file mode 100644 index 00000000..a337a94b --- /dev/null +++ b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/Source/Dynamic/ofApp.h @@ -0,0 +1,43 @@ +/* + + Spout OpenFrameworks dynamic Load example + + Copyright (C) 2021 Lynn Jarvis. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . + +*/ +#pragma once + +#include "ofMain.h" + +// SpoutLibrary dll dynamic loader +// Includes a header for SpoutLibrary +#include "SpoutLibraryLoader.h" + + +class ofApp : public ofBaseApp{ + public: + void setup(); + void update(); + void draw(); + void exit(); + + SpoutLibraryLoader spoutloader; // SpoutLibrary dynamic loader + SPOUTLIBRARY * sender; // A sender object pointer + char sendername[256]; // Sender name + ofImage myBoxImage; // Image for the 3D demo + float rotX, rotY; + +}; diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/Source/Receiver/ofApp.cpp b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/Source/Receiver/ofApp.cpp index 4500fa92..67b58026 100644 --- a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/Source/Receiver/ofApp.cpp +++ b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/Source/Receiver/ofApp.cpp @@ -10,7 +10,7 @@ 3) Tell the linker to input SpoutLibrary.lib to your project For Visual Studio this will be : Project > Properties > Linker > Input - 4) Tell the linker where to find it + 4) Tell the linker where to find it (libs) For Visual Studio this will be : Project > Properties > Linker > General > Aditional library directories diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/Source/Sender/ofApp.cpp b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/Source/Sender/ofApp.cpp index ba127adc..df72f6c3 100644 --- a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/Source/Sender/ofApp.cpp +++ b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/Source/Sender/ofApp.cpp @@ -10,7 +10,7 @@ 3) Tell the linker to input SpoutLibrary.lib to your project For Visual Studio this will be : Project > Properties > Linker > Input - 4) Tell the linker where to find it + 4) Tell the linker where to find it (libs) For Visual Studio this will be : Project > Properties > Linker > General > Aditional library directories diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/SpoutLibraryExample.sln b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/SpoutLibraryExample.sln index 453dfaea..eb78a74e 100644 --- a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/SpoutLibraryExample.sln +++ b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/SpoutLibraryExample.sln @@ -1,8 +1,10 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 +VisualStudioVersion = 15.0.28307.1300 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SpoutLibraryExample", "SpoutLibraryExample.vcxproj", "{7FD42DF7-442E-479A-BA76-D0022F99702A}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openframeworksLib", "..\..\..\..\..\libs\openFrameworksCompiled\project\vs\openframeworksLib.vcxproj", "{5837595D-ACA9-485C-8E76-729040CE4B0B}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openframeworksLib", "..\..\..\libs\openFrameworksCompiled\project\vs\openframeworksLib.vcxproj", "{5837595D-ACA9-485C-8E76-729040CE4B0B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -12,24 +14,25 @@ Global Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7FD42DF7-442E-479A-BA76-D0022F99702A}.Debug|Win32.ActiveCfg = Debug|Win32 - {7FD42DF7-442E-479A-BA76-D0022F99702A}.Debug|Win32.Build.0 = Debug|Win32 - {7FD42DF7-442E-479A-BA76-D0022F99702A}.Debug|x64.ActiveCfg = Debug|x64 - {7FD42DF7-442E-479A-BA76-D0022F99702A}.Debug|x64.Build.0 = Debug|x64 + {7FD42DF7-442E-479A-BA76-D0022F99702A}.Debug|Win32.ActiveCfg = Release|Win32 + {7FD42DF7-442E-479A-BA76-D0022F99702A}.Debug|Win32.Build.0 = Release|Win32 + {7FD42DF7-442E-479A-BA76-D0022F99702A}.Debug|x64.ActiveCfg = Release|Win32 + {7FD42DF7-442E-479A-BA76-D0022F99702A}.Debug|x64.Build.0 = Release|Win32 {7FD42DF7-442E-479A-BA76-D0022F99702A}.Release|Win32.ActiveCfg = Release|Win32 {7FD42DF7-442E-479A-BA76-D0022F99702A}.Release|Win32.Build.0 = Release|Win32 {7FD42DF7-442E-479A-BA76-D0022F99702A}.Release|x64.ActiveCfg = Release|x64 {7FD42DF7-442E-479A-BA76-D0022F99702A}.Release|x64.Build.0 = Release|x64 - {5837595D-ACA9-485C-8E76-729040CE4B0B}.Debug|Win32.ActiveCfg = Debug|Win32 - {5837595D-ACA9-485C-8E76-729040CE4B0B}.Debug|Win32.Build.0 = Debug|Win32 - {5837595D-ACA9-485C-8E76-729040CE4B0B}.Debug|x64.ActiveCfg = Debug|x64 - {5837595D-ACA9-485C-8E76-729040CE4B0B}.Debug|x64.Build.0 = Debug|x64 + {5837595D-ACA9-485C-8E76-729040CE4B0B}.Debug|Win32.ActiveCfg = Release|Win32 + {5837595D-ACA9-485C-8E76-729040CE4B0B}.Debug|Win32.Build.0 = Release|Win32 + {5837595D-ACA9-485C-8E76-729040CE4B0B}.Debug|x64.ActiveCfg = Release|Win32 + {5837595D-ACA9-485C-8E76-729040CE4B0B}.Debug|x64.Build.0 = Release|Win32 {5837595D-ACA9-485C-8E76-729040CE4B0B}.Release|Win32.ActiveCfg = Release|Win32 - {5837595D-ACA9-485C-8E76-729040CE4B0B}.Release|Win32.Build.0 = Release|Win32 {5837595D-ACA9-485C-8E76-729040CE4B0B}.Release|x64.ActiveCfg = Release|x64 - {5837595D-ACA9-485C-8E76-729040CE4B0B}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {17D0298C-0DDC-497C-9D9E-C1F79C4E7F96} + EndGlobalSection EndGlobal diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/SpoutLibraryExample.vcxproj b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/SpoutLibraryExample.vcxproj index 3c3a1935..44dad88b 100644 --- a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/SpoutLibraryExample.vcxproj +++ b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/SpoutLibraryExample.vcxproj @@ -26,7 +26,7 @@ {7FD42DF7-442E-479A-BA76-D0022F99702A} Win32Proj - SpoutLibraryExample + emptyExample @@ -54,19 +54,19 @@ - + - + - + - + @@ -129,8 +129,8 @@ true Console false - %(AdditionalDependencies) - %(AdditionalLibraryDirectories) + SpoutLibrary.lib;%(AdditionalDependencies) + libs;%(AdditionalLibraryDirectories) @@ -174,8 +174,8 @@ true true false - %(AdditionalDependencies) - %(AdditionalLibraryDirectories) + SpoutLibrary.lib;%(AdditionalDependencies) + libs;%(AdditionalLibraryDirectories) @@ -185,7 +185,6 @@ - diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/SpoutLibraryExample.vcxproj.filters b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/SpoutLibraryExample.vcxproj.filters deleted file mode 100644 index 0add6286..00000000 --- a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/SpoutLibraryExample.vcxproj.filters +++ /dev/null @@ -1,36 +0,0 @@ - - - - - src - - - src - - - src - - - src - - - - - {d8376475-7454-4a24-b08a-aac121d3ad6f} - - - - - src - - - src - - - src - - - - - - diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/addons.make b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/addons.make deleted file mode 100644 index e69de29b..00000000 diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/SpoutLibrary.dll b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/SpoutLibrary.dll index 4bd00f19..226852ba 100644 Binary files a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/SpoutLibrary.dll and b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/SpoutLibrary.dll differ diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/SpoutLibraryDynamic.exe b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/SpoutLibraryDynamic.exe new file mode 100644 index 00000000..d6bf7dc2 Binary files /dev/null and b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/SpoutLibraryDynamic.exe differ diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/SpoutLibraryExample.exe b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/SpoutLibraryExample.exe new file mode 100644 index 00000000..490608c3 Binary files /dev/null and b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/SpoutLibraryExample.exe differ diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/ofSpoutLibraryReceiver.exe b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/SpoutLibraryReceiver.exe similarity index 89% rename from SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/ofSpoutLibraryReceiver.exe rename to SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/SpoutLibraryReceiver.exe index 2d25a579..dd2d374d 100644 Binary files a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/ofSpoutLibraryReceiver.exe and b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/SpoutLibraryReceiver.exe differ diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/ofSpoutLibrarySender.exe b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/SpoutLibrarySender.exe similarity index 81% rename from SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/ofSpoutLibrarySender.exe rename to SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/SpoutLibrarySender.exe index 7e9698dd..57dd1bbf 100644 Binary files a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/ofSpoutLibrarySender.exe and b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/bin/SpoutLibrarySender.exe differ diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/libs/SpoutLibrary.dll b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/libs/SpoutLibrary.dll index 4bd00f19..226852ba 100644 Binary files a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/libs/SpoutLibrary.dll and b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/libs/SpoutLibrary.dll differ diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/libs/SpoutLibrary.lib b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/libs/SpoutLibrary.lib index 2f04ba41..e50762da 100644 Binary files a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/libs/SpoutLibrary.lib and b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/libs/SpoutLibrary.lib differ diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/src/SpoutLibrary.h b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/src/SpoutLibrary.h index e0d615fd..7602715a 100644 --- a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/src/SpoutLibrary.h +++ b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/src/SpoutLibrary.h @@ -48,7 +48,9 @@ #endif // Local log level definitions -enum LogLevel { +// SpoutLogLevel conflicts with previous definition +// LogLevel is too generic +enum LibLogLevel { SPOUT_LOG_SILENT, SPOUT_LOG_VERBOSE, SPOUT_LOG_NOTICE, @@ -216,7 +218,7 @@ struct SPOUTLIBRARY // SPOUT_LOG_WARNING - Something might go wrong // SPOUT_LOG_ERROR - Something did go wrong // SPOUT_LOG_FATAL - Something bad happened - virtual void SetSpoutLogLevel(LogLevel level) = 0; + virtual void SetSpoutLogLevel(LibLogLevel level) = 0; // General purpose log virtual void SpoutLog(const char* format, ...) = 0; // Verbose - show log for SPOUT_LOG_VERBOSE or above diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/src/SpoutLibraryLoader.h b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/src/SpoutLibraryLoader.h new file mode 100644 index 00000000..8295e0e1 --- /dev/null +++ b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/src/SpoutLibraryLoader.h @@ -0,0 +1,134 @@ +// +// SpoutLibraryLoader.h +// +// Dynamic load of SpoutLibrary.dll +// +// Use this if SpoutLibrary.lib is not compatible with your compiler, +// or to allow user update of SpoutLibrary.dll if the disributed library +// build has been updated with SDK updates but the functions have not changed. +// + +/* + Copyright (c) 2021, Lynn Jarvis. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#pragma once + +#ifndef __SpoutLibraryLoader__ +#define __SpoutLibraryLoader__ + +#include "SpoutLibrary.h" +#include +#include +#pragma comment(lib, "Shlwapi.lib") // for path functions + +struct SpoutLibraryLoader +{ + +public: + + SpoutLibraryLoader() {}; + ~SpoutLibraryLoader() {}; + + // + // Load SpoutLibrary.dll dynamically + // + // The dll file must be in the same folder as the executable. + // The dll type (Win32 or x64) must match the executable. + // + SPOUTLIBRARY * LoadSpoutLibrary() + { + // + // To avoid anti-virus false positive detections, SpoutLibrary.dll is + // distributed compiled as "Multi-threaded DLL (/MD)" and requires the + // Visual Studio runtime dlls to be installed on the system. + // Visual C++ 2015, 2017 and 2019 all share the same redistributable files. + // + // https://support.microsoft.com/en-us/topic/the-latest-supported-visual-c-downloads-2647da03-1eea-4433-9aff-95f26a218cc0 + // + // If you build the library yourself, you can use "Multi-threaded (/MT)" + // to embed the runtime in the dll. Then you can remove the following check. + // + + // Check for VS2017 runtime. + // For 64-bit VC++ Redistributable + // HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\x64 + // For 32 - bit VC++ Redistributable + // HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\x86 + HKEY hRegKey = NULL; + LONG regres = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wow6432Node\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes", NULL, KEY_READ, &hRegKey); + if (regres != ERROR_SUCCESS) { + MessageBoxA(NULL, "Could not find VS2017 runtimes\nInstall from the VS2015-2019 folder\nof the Spout distribution.", "Error", MB_OK); + return nullptr; + } + + // + // Look in the executable folder for the dll file. + // + + // Get the executable path. + char filepath[MAX_PATH]; + if (GetModuleFileNameA(NULL, filepath, sizeof(filepath)) == 0) + return nullptr; + + // Remove executable file name and replace with the dll file name + PathRemoveFileSpecA(filepath); + strcat_s(filepath, MAX_PATH, "\\SpoutLibrary.dll"); + + // Now we have the full path of the dll file. + // Does the file exist ? + if (_access(filepath, 0) == -1) + return nullptr; + + // Get a handle to the dll module + hSpoutLib = LoadLibraryA(filepath); + if (hSpoutLib == NULL) + return nullptr; + + // Try to get the address of the function that creates an instance of SpoutLibrary. + // Credit to Newtek NDI (https://www.ndi.tv/) dynamic load example for this code. + SPOUTLIBRARY * (*GetSpout)(void) = nullptr; + *((FARPROC*)&GetSpout) = GetProcAddress(hSpoutLib, "GetSpout"); + if (GetSpout == NULL) + return nullptr; + + // Now we can create an instance of the library and access all the functions in it. + // The dll LoadLibrary handle (hSpoutLib) must be freed on exit using FreeSpoutLibrary() + + return GetSpout(); + } + + void FreeSpoutLibrary() + { + if (hSpoutLib) + FreeLibrary(hSpoutLib); + } + +private: + + HINSTANCE hSpoutLib = nullptr; + +}; + +#endif diff --git a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/src/ofApp.cpp b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/src/ofApp.cpp index ba127adc..df72f6c3 100644 --- a/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/src/ofApp.cpp +++ b/SPOUTSDK/SpoutLibrary/SpoutLibraryExample/src/ofApp.cpp @@ -10,7 +10,7 @@ 3) Tell the linker to input SpoutLibrary.lib to your project For Visual Studio this will be : Project > Properties > Linker > Input - 4) Tell the linker where to find it + 4) Tell the linker where to find it (libs) For Visual Studio this will be : Project > Properties > Linker > General > Aditional library directories diff --git a/UPDATES.md b/UPDATES.md index 11e8033d..67b38e37 100644 --- a/UPDATES.md +++ b/UPDATES.md @@ -1,5 +1,41 @@ -14-06-21 -Update Master from Beta branch +===================================\ +26-07-21\ +Update Master from Beta branch.\ +Version 2.007.003 + +Spout.cpp +- 22.06.21 - Move code for GetSenderCount and GetSender to SpoutSenderNames class +- 03.07.21 - Use changed SpoutSenderNames "GetSender" function name. +- 04.07.21 - Additional code comments concerning update in ReceiveTexture. + +SpoutCopy.cpp +- 09.07.21 - memcpy_sse2 - return for null dst or src + +SpoutDirectX.cpp +- 19.06.21 - Remove output check from FindNVIDIA + +SpoutFrameCount.cpp +- 21.07.21 - Remove debug comment + +SpoutGL.cpp +- 26.07.21 - Remove memorysize check from GetMemoryBufferSize for receiver + +SpoutSenderNames.cpp +- 22.06.21 - Restore 2.006 GetSenderNames function +- 03.07.21 - Change GetSenderNames to GetSender to align with Spout class.\ + Change existing GetSender to FindSenderName.\ + Change duplicate FindSenderName to FindSender overload\ + testing function + +SpoutUtils.cpp +- 26.07.21 - Update Version to "2.007.003" + +BUILD binaries updated +- CMake build 32/64bit /MD - requires Visual Studio 2017 runtime to be installed + +===================================\ +14-06-21\ +Update Master from Beta branch\ Version 2.007.002 Spout.cpp