Skip to content

Commit

Permalink
create capturing API for streaming/etc.
Browse files Browse the repository at this point in the history
  • Loading branch information
Gargaj committed Dec 1, 2016
1 parent 85d261e commit 48cea07
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 105 deletions.
13 changes: 12 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,18 @@ elseif (MSVC)
set(BZC_PROJECT_INCLUDES ${CMAKE_SOURCE_DIR}/data/windows ${BZC_PROJECT_INCLUDES})
endif ()

set(BZC_PROJECT_SRCS ${BZC_PROJECT_SRCS} ${BZC_PLATFORM_SRCS} ${BZC_RESOURCES_DATA})
if (MSVC AND BONZOMATIC_NDI)
set(BZC_CAPTURE_SRCS
${CMAKE_SOURCE_DIR}/src/capturing/Capture_NDI.cpp
)
else ()
set(BZC_CAPTURE_SRCS
${CMAKE_SOURCE_DIR}/src/capturing/Capture_Dummy.cpp
)
endif ()
source_group("Bonzomatic\\Capture" FILES ${BZC_CAPTURE_SRCS})

set(BZC_PROJECT_SRCS ${BZC_PROJECT_SRCS} ${BZC_PLATFORM_SRCS} ${BZC_RESOURCES_DATA} ${BZC_CAPTURE_SRCS})

set(BZC_PROJECT_INCLUDES ${CMAKE_SOURCE_DIR}/src ${BZC_PROJECT_INCLUDES})

Expand Down
7 changes: 7 additions & 0 deletions src/Capture.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Capture
{
void LoadSettings(jsonxx::Object & o);
bool Open(RENDERER_SETTINGS & settings);
void CaptureFrame();
void Close();
}
19 changes: 19 additions & 0 deletions src/capturing/Capture_Dummy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include "jsonxx.h"
#include "Renderer.h"

namespace Capture
{
void LoadSettings(jsonxx::Object & o)
{
}
bool Open(RENDERER_SETTINGS & settings)
{
return true;
}
void CaptureFrame()
{
}
void Close()
{
}
}
107 changes: 107 additions & 0 deletions src/capturing/Capture_NDI.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#include <Processing.NDI.Lib.h>
#include <string>
#include "jsonxx.h"
#include "Renderer.h"

namespace Capture
{
std::string sNDIConnectionString;
float fNDIFrameRate = 60.0;
std::string sNDIIdentifier;
bool bNDIProgressive = true;
bool bNDIEnabled = true;
unsigned int * pBuffer[2] = { NULL, NULL };
unsigned int nBufferIndex = 0;
NDIlib_video_frame_t pNDIFrame;
NDIlib_send_instance_t pNDI_send;

void LoadSettings(jsonxx::Object & o)
{
if (o.has<jsonxx::Object>("ndi"))
{
if (o.get<jsonxx::Object>("ndi").has<jsonxx::Boolean>("enabled"))
bNDIEnabled = o.get<jsonxx::Object>("ndi").get<jsonxx::Boolean>("enabled");
if (o.get<jsonxx::Object>("ndi").has<jsonxx::String>("connectionString"))
sNDIConnectionString = o.get<jsonxx::Object>("ndi").get<jsonxx::String>("connectionString");
if (o.get<jsonxx::Object>("ndi").has<jsonxx::String>("identifier"))
sNDIIdentifier = o.get<jsonxx::Object>("ndi").get<jsonxx::String>("identifier");
if (o.get<jsonxx::Object>("ndi").has<jsonxx::Number>("frameRate"))
fNDIFrameRate = o.get<jsonxx::Object>("ndi").get<jsonxx::Number>("frameRate");
if (o.get<jsonxx::Object>("ndi").has<jsonxx::Boolean>("progressive"))
bNDIProgressive = o.get<jsonxx::Object>("ndi").get<jsonxx::Boolean>("progressive");
}
}
bool Open(RENDERER_SETTINGS & settings)
{
if (bNDIEnabled)
{
if (!NDIlib_initialize())
{
printf("[Capture] Cannot initialize NDI");
return false;
}

NDIlib_send_create_t pNDICreateDesc;
sNDIIdentifier = "BONZOMATIC" + (sNDIIdentifier.length() ? (" - " + sNDIIdentifier) : "");
pNDICreateDesc.p_ndi_name = sNDIIdentifier.c_str();
pNDICreateDesc.p_groups = NULL;
pNDICreateDesc.clock_video = true;
pNDICreateDesc.clock_audio = false;

pNDI_send = NDIlib_send_create(&pNDICreateDesc);
if (!pNDI_send)
{
printf("[Capture] Cannot create NDI source");
return false;
}

NDIlib_metadata_frame_t pNDIConnType;
pNDIConnType.length = sNDIConnectionString.length();
pNDIConnType.timecode = NDIlib_send_timecode_synthesize;
pNDIConnType.p_data = (char*)sNDIConnectionString.c_str();

NDIlib_send_add_connection_metadata(pNDI_send, &pNDIConnType);

pNDIFrame.xres = settings.nWidth;
pNDIFrame.yres = settings.nHeight;
pNDIFrame.FourCC = NDIlib_FourCC_type_BGRA;
pNDIFrame.frame_rate_N = fNDIFrameRate * 100;
pNDIFrame.frame_rate_D = 100;
pNDIFrame.picture_aspect_ratio = settings.nWidth / (float)settings.nHeight;
pNDIFrame.frame_format_type = bNDIProgressive ? NDIlib_frame_format_type_progressive : NDIlib_frame_format_type_interleaved;
pNDIFrame.timecode = NDIlib_send_timecode_synthesize;
pBuffer[0] = new unsigned int[settings.nWidth * settings.nHeight * 4];
pBuffer[1] = new unsigned int[settings.nWidth * settings.nHeight * 4];
pNDIFrame.p_data = NULL;
pNDIFrame.line_stride_in_bytes = settings.nWidth * 4;
}
return true;
}
void CaptureFrame()
{
if (pBuffer[0] && pBuffer[1])
{
pNDIFrame.p_data = (unsigned char*)pBuffer[ nBufferIndex ];
nBufferIndex = (nBufferIndex + 1) & 1;
if (Renderer::GrabFrame( pNDIFrame.p_data ))
{
unsigned int * p = (unsigned int *)pNDIFrame.p_data;
for(int i=0; i < pNDIFrame.xres * pNDIFrame.yres; i++)
p[i] = (p[i] & 0x00FF00) | ((p[i] >> 16) & 0xFF) | ((p[i] & 0xFF) << 16) | 0xFF000000;
NDIlib_send_send_video_async(pNDI_send, &pNDIFrame);
}
}
}
void Close()
{
if (pBuffer[0] && pBuffer[1])
{
NDIlib_send_send_video_async(pNDI_send, NULL); // stop async thread

delete[] pBuffer[0];
delete[] pBuffer[1];
NDIlib_send_destroy(pNDI_send);
NDIlib_destroy();
}
}
}
112 changes: 8 additions & 104 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@
#include "Misc.h"
#include "UniConversion.h"
#include "jsonxx.h"
#include "Capture.h"

#ifdef WIN32
#include <windows.h>
#ifdef BONZOMATIC_ENABLE_NDI
#include <Processing.NDI.Lib.h>
#endif
#endif

void ReplaceTokens( std::string &sDefShader, const char * sTokenBegin, const char * sTokenName, const char * sTokenEnd, std::vector<std::string> &tokens )
Expand Down Expand Up @@ -131,14 +129,6 @@ int main()
float fFFTSmoothingFactor = 0.9f; // higher value, smoother FFT
float fFFTSlightSmoothingFactor = 0.6f; // higher value, smoother FFT

#ifdef BONZOMATIC_ENABLE_NDI
std::string sNDIConnectionString;
float fNDIFrameRate = 60.0;
std::string sNDIIdentifier;
bool bNDIProgressive = true;
bool bNDIEnabled = true;
#endif // BONZOMATIC_ENABLE_NDI

char szConfig[65535];
FILE * fConf = fopen("config.json","rb");
if (fConf)
Expand Down Expand Up @@ -205,21 +195,12 @@ int main()
midiRoutes.insert( std::make_pair( it->second->number_value_, it->first ) );
}
}
#ifdef BONZOMATIC_ENABLE_NDI
if (o.has<jsonxx::Object>("ndi"))
{
if (o.get<jsonxx::Object>("ndi").has<jsonxx::Boolean>("enabled"))
bNDIEnabled = o.get<jsonxx::Object>("ndi").get<jsonxx::Boolean>("enabled");
if (o.get<jsonxx::Object>("ndi").has<jsonxx::String>("connectionString"))
sNDIConnectionString = o.get<jsonxx::Object>("ndi").get<jsonxx::String>("connectionString");
if (o.get<jsonxx::Object>("ndi").has<jsonxx::String>("identifier"))
sNDIIdentifier = o.get<jsonxx::Object>("ndi").get<jsonxx::String>("identifier");
if (o.get<jsonxx::Object>("ndi").has<jsonxx::Number>("frameRate"))
fNDIFrameRate = o.get<jsonxx::Object>("ndi").get<jsonxx::Number>("frameRate");
if (o.get<jsonxx::Object>("ndi").has<jsonxx::Boolean>("progressive"))
bNDIProgressive = o.get<jsonxx::Object>("ndi").get<jsonxx::Boolean>("progressive");
}
#endif // BONZOMATIC_ENABLE_NDI
Capture::LoadSettings( o );
}
if ( !Capture::Open( settings ) )
{
printf("Initializing capture system failed!\n");
return 0;
}

Renderer::Texture * texFFT = Renderer::Create1DR32Texture( FFT_SIZE );
Expand Down Expand Up @@ -302,59 +283,6 @@ int main()
static float fftDataIntegrated[FFT_SIZE];
memset(fftDataIntegrated, 0, sizeof(float) * FFT_SIZE);

// if we want to do some sort of frame capturing code
// (for e.g. sending frames through the network)
// we'd do it here, and then below.

#ifdef BONZOMATIC_ENABLE_NDI
NDIlib_video_frame_t pNDIFrame;
NDIlib_send_instance_t pNDI_send;
unsigned int * pBuffer[2] = { NULL, NULL };
unsigned int nBufferIndex = 0;
if (bNDIEnabled)
{
if (!NDIlib_initialize())
{
printf("Cannot run NDI.");
return 0;
}

NDIlib_send_create_t pNDICreateDesc;
sNDIIdentifier = "BONZOMATIC" + (sNDIIdentifier.length() ? (" - " + sNDIIdentifier) : "");
pNDICreateDesc.p_ndi_name = sNDIIdentifier.c_str();
pNDICreateDesc.p_groups = NULL;
pNDICreateDesc.clock_video = TRUE;
pNDICreateDesc.clock_audio = FALSE;

pNDI_send = NDIlib_send_create(&pNDICreateDesc);
if (!pNDI_send)
{
printf("Cannot create NDI source");
return 0;
}

NDIlib_metadata_frame_t pNDIConnType;
pNDIConnType.length = sNDIConnectionString.length();
pNDIConnType.timecode = NDIlib_send_timecode_synthesize;
pNDIConnType.p_data = (CHAR*)sNDIConnectionString.c_str();

NDIlib_send_add_connection_metadata(pNDI_send, &pNDIConnType);

pNDIFrame.xres = settings.nWidth;
pNDIFrame.yres = settings.nHeight;
pNDIFrame.FourCC = NDIlib_FourCC_type_BGRA;
pNDIFrame.frame_rate_N = fNDIFrameRate * 100;
pNDIFrame.frame_rate_D = 100;
pNDIFrame.picture_aspect_ratio = settings.nWidth / (float)settings.nHeight;
pNDIFrame.frame_format_type = bNDIProgressive ? NDIlib_frame_format_type_progressive : NDIlib_frame_format_type_interleaved;
pNDIFrame.timecode = NDIlib_send_timecode_synthesize;
pBuffer[0] = new unsigned int[settings.nWidth * settings.nHeight * 4];
pBuffer[1] = new unsigned int[settings.nWidth * settings.nHeight * 4];
pNDIFrame.p_data = NULL;
pNDIFrame.line_stride_in_bytes = settings.nWidth * 4;
}
#endif // BONZOMATIC_ENABLE_NDI

bool bShowGui = true;
Timer::Start();
float fNextTick = 0.1;
Expand Down Expand Up @@ -534,33 +462,9 @@ int main()

Renderer::EndFrame();

#ifdef BONZOMATIC_ENABLE_NDI
if (pBuffer[0] && pBuffer[1])
{
pNDIFrame.p_data = (BYTE*)pBuffer[ nBufferIndex ];
nBufferIndex = (nBufferIndex + 1) & 1;
if (Renderer::GrabFrame( pNDIFrame.p_data ))
{
unsigned int * p = (unsigned int *)pNDIFrame.p_data;
for(int i=0; i < settings.nWidth * settings.nHeight; i++)
p[i] = (p[i] & 0x00FF00) | ((p[i] >> 16) & 0xFF) | ((p[i] & 0xFF) << 16) | 0xFF000000;
NDIlib_send_send_video_async(pNDI_send, &pNDIFrame);
}
}
#endif // BONZOMATIC_ENABLE_NDI
Capture::CaptureFrame();
}

#ifdef BONZOMATIC_ENABLE_NDI
if (pBuffer[0] && pBuffer[1])
{
NDIlib_send_send_video_async(pNDI_send, NULL); // stop async thread

delete[] pBuffer[0];
delete[] pBuffer[1];
NDIlib_send_destroy(pNDI_send);
NDIlib_destroy();
}
#endif // BONZOMATIC_ENABLE_NDI

delete surface;

Expand Down

0 comments on commit 48cea07

Please sign in to comment.