Commit d503fc6b authored by Nicolas Bouillot's avatar Nicolas Bouillot

Merge branch 'develop'

parents ec999e3a 0508ea03
build/
\ No newline at end of file
Nicolas Bouillot
\ No newline at end of file
# CMake Config
cmake_minimum_required(VERSION 3.5.1)
#
# CONFIGURATION
#
# Project Variables
set(NDI2SHMDATA_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(NDI2SHMDATA_VERSION_MAJOR 0)
set(NDI2SHMDATA_VERSION_MINOR 1)
set(NDI2SHMDATA_VERSION_PATCH 0)
set(NDI2SHMDATA_VERSION_STRING ${NDI2SHMDATA_VERSION_MAJOR}.${NDI2SHMDATA_VERSION_MINOR}.${NDI2SHMDATA_VERSION_PATCH})
set(SHMDATA_REQUIRED_VERSION 1.3)
# Package (pkg-config) Information
set(PACKAGE_NAME ndi2shmdata)
set(PACKAGE_DESCRIPTION "Ndi2shmdata provides tools for sharing video between shmdata and NewTek's NDI")
set(PACKAGE_URL "https://gitlab.com/sat-metalab/ndi2shmdata")
set(PACKAGE_VERSION ${NDI2SHMDATA_VERSION_STRING})
# Compilation
set(CMAKE_CXX_STANDARD 17)
set(DATADIR ${CMAKE_INSTALL_PREFIX}/share/ndi2shmdata/)
# CPack - General
set(CPACK_PACKAGE_NAME ${PACKAGE_NAME})
set(CPACK_PACKAGE_VENDOR "Metalab - Société des arts technologiques")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PACKAGE_DESCRIPTION}")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_PACKAGE_VERSION_MAJOR "${NDI2SHMDATA_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${NDI2SHMDATA_VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${NDI2SHMDATA_VERSION_PATCH}")
set(CPACK_GENERATOR TGZ)
set(CPACK_SOURCE_GENERATOR TGZ)
set(CPACK_COMPONENTS_ALL applications)
# CPack - Applications
set(CPACK_COMPONENT_APPLICATIONS_DISPLAY_NAME "ndi2shmdata & shmdata2ndi")
set(CPACK_COMPONENT_APPLICATIONS_DESCRIPTION "Application for converting ndi to shmdata")
set(CPACK_COMPONENT_APPLICATIONS_DEPENDS libraries)
# CPack - Source
set(CPACK_SOURCE_IGNORE_FILES "/\.hooks/;/\.idea/;/build/;/html/;/scripts/;${CPACK_SOURCE_IGNORE_FILES}")
# Add local cmake directory to ckame module path in case we need it
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake")
#
# INCLUDES
#
include(FeatureSummary)
include(CPack)
include(PackageSourceTest)
include(CMakeDependentOption)
#
# PROJECT
#
project(Ndi2shmdata)
enable_testing()
option(ACCEPT_NDI_LICENSE "Accept NDI License Agreement" OFF)
if (NOT ACCEPT_NDI_LICENSE)
message(FATAL_ERROR "ndi2shmdata compilation requires acceptation of the NDI License. The license is available in the ndi-sdk folder. License can be accepted using the following cmake option: -DACCEPT_NDI_LICENSE=ON\nExample 'cmake -DACCEPT_NDI_LICENSE=ON ..' ")
endif()
# Prerequisites
find_package(PkgConfig REQUIRED)
# This is required in the case where macport screwed with the paths on mac os x
set(ENV{PKG_CONFIG_PATH} "/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH")
pkg_check_modules(SHMDATA REQUIRED shmdata-${SHMDATA_REQUIRED_VERSION})
# Global stuff
link_directories(
${SHMDATA_LIBRARY_DIRS}
${NDI2SHMDATA_DIR}/ndi-sdk/lib/x86_64-linux-gnu
)
link_libraries(
${SHMDATA_LIBRARIES}
dl
ndi
pthread
)
include_directories(
${SHMDATA_INCLUDE_DIRS}
${NDI2SHMDATA_DIR}/ndi-sdk/include
)
add_compile_options(${SHMDATA_CFLAGS})
# BUILD TYPE
if(CMAKE_BUILD_TYPE EQUAL "Debug")
add_definitions(-DDEBUG)
endif()
# WARNINGS
add_definitions(-Wall)
add_definitions(-Wextra)
add_definitions(-Werror)
add_definitions(-Wno-error=unused-parameter)
# OSX (not tested !)
if(APPLE AND ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(OSX TRUE)
add_definitions(-DOSX)
add_compile_options(-ObjC++) # Allows objective-c building
endif ()
#
# MODULES
#
add_subdirectory(src)
#
# OTHER TARGETS
#
# Uninstall
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/CMakeUninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/CMakeUninstall.cmake"
IMMEDIATE @ONLY)
add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/CMakeUninstall.cmake)
#
# POST
#
# Report
feature_summary(WHAT ALL)
if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
endif (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
foreach (file ${files})
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
if (IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
exec_program(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
if (NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
endif (NOT "${rm_retval}" STREQUAL 0)
else (IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
endif (IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
endforeach (file)
\ No newline at end of file
CONTRIBUTING
======
Coding style
------------
We use Google C++ Style Guide, as decribed [here](https://google.github.io/styleguide/cppguide.html), with two excpetions:
* a function call’s arguments will either be all on the same line or will have one line each.
* a function declaration’s or function definition’s parameters will either all be on the same line or will have one line each.
Note that you may find configuration file for your editor [here](https://github.com/google/styleguide).
Contributing
------------
Please send your merge request at the [sat-metalab' gitlab account](https://gitlab.com/sat-metalab/ndi2shmdata). If you do not know how to make a merge request, gitlab provides some [help about creating a merge request](https://docs.gitlab.com/ee/gitlab-basics/add-merge-request.html).
Branching strategy with git
---------------------------
The [master](https://gitlab.com/sat-metalab/ndi2shmdata/tree/master) branch contains releases. Validated new developments are into the [develop](https://gitlab.com/sat-metalab/ndi2shmdata/tree/develop) branch.
Modifications are made into a dedicated branch that need to be merged into the develop branch through a gitlab merge request. When you modification is ready, you need to prepare your merge request as follow:
* Update your develop branch.
```
git fetch
git checkout develop
git pull origin develop
```
* Go back to your branch and rebase onto develop. Note that it would be appreciated that you only merge request from a single commit (i.e interactive rebase with squash and/or fixup before pushing).
```
git rebase -i develop
```
# How to make new releases
First make sure `develop` branch reflects the desired `master`:
* Increase the version (major, minor or patch) or in the CMakeLists.txt file located at the root of the project
* Create a new entry in the NEWS.md file (top of the file) with version number, date and description of changes
* Commit and push, open a code review
Release into the master branch:
* merge into master: `git checkout master && git pull origin master && git merge --no-ff develop`
* tag the version `git tag -a vX.X.X -m"Short message that explains the new version"`
* push to master: `git push origin master --tags`
You're done.
# NDI2shmdata Changelog
ndi2shmdata [0.1.0] - 2019-02-11
--------------------------------
New features:
* command line listing of available NDI streams
* ndi2shmdata subscribes to a NDI stream using its name, and write video frames to a shmdata
* shmdata2ndi subscribes to a shmdata and publishes it as a NDI stream
# NDI2shmdata
Tool that convert shmdata to NewTek's NDI. This allows for shmdata enabled software to enter the NDI world.
\ No newline at end of file
Tool that convert [shmdata](https://gitlab.com/sat-metalab/shmdata) to [NewTek's NDI](http://ndi.newtek.com), and _vice versa_.
Example
=======
List visible NDI streams:
```
ndi2shmdata -l
```
Get a stream and make it a shmdata located at `/tmp/shmomg`:
```
ndi2shmdata -d -o /tmp/shmomg -n "ndi-stream-name"
```
View the stream with gst-launch:
```
gst-launch -v shmdatasrc socket-path=/tmp/shmomg ! videoconvert ! xvimagesink sync=false
```
For more detailled information, get help from the commands using the `-h` flag:
```
ndi2shmdata -h
shmdata2ndi -h
```
Build from sources
==================
This has been tested with Ubuntu 18.04. git and shmdata must be installed on your system.
You need to accept NDI license for the code to compile. The License Agreement text is available [here](ndi-sdk/NDI\ License\ Agreement.pdf) and can be accepted with the cmake variable "ACCEPT_NDI_LICENSE" set to "ON".
```
git clone http://gitlab.com:sat-metalab/ndi2shmdata.git
cd ndi2shmdata && mkdir build && cd build
cmake -DACCEPT_NDI_LICENSE=ON ..
make
sudo make install
```
TODO
====
* audio support in ndi2shmdata and shmdata2ndi
* (maybe) support NDI timecode
configure_file("cmake/PackageSourceTest.sh.in" "PackageSourceTest.sh" @ONLY)
add_custom_target(package_source_test COMMAND ${CMAKE_CURRENT_BINARY_DIR}/PackageSourceTest.sh)
\ No newline at end of file
#!/usr/bin/env bash
set -e
# Clean before, in case of a previous failed test
rm -f @PACKAGE_NAME@-@PACKAGE_VERSION@-Source.tar.gz
rm -rf @PACKAGE_NAME@-@PACKAGE_VERSION@-Source
# Create the source package
make package_source
# Extract and rebuild + test
tar -zxvf @PACKAGE_NAME@-@PACKAGE_VERSION@-Source.tar.gz
cd @PACKAGE_NAME@-@PACKAGE_VERSION@-Source
mkdir build
cd build
cmake ..
make
make test
# Cleanup after
cd ../..
rm -f @PACKAGE_NAME@-@PACKAGE_VERSION@-Source.tar.gz
rm -rf @PACKAGE_NAME@-@PACKAGE_VERSION@-Source
\ No newline at end of file
This diff is collapsed.
#pragma once
// NOTE : The following MIT license applies to this file ONLY and not to the SDK as a whole. Please review the SDK documentation
// for the description of the full license terms, which are also provided in the file "NDI License Agreement.pdf" within the SDK or
// online at http://new.tk/ndisdk_license/. Your use of any part of this SDK is acknowledgment that you agree to the SDK license
// terms. The full NDI SDK may be downloaded at https://www.newtek.com/ndi/sdk/
//
//***********************************************************************************************************************************************
//
// Copyright(c) 2014-2018 NewTek, inc
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
// merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//***********************************************************************************************************************************************
//**************************************************************************************************************************
// Structures and type definitions required by NDI finding
// The reference to an instance of the finder
typedef void* NDIlib_find_instance_t;
// The creation structure that is used when you are creating a finder
typedef struct NDIlib_find_create_t
{ // Do we want to incluide the list of NDI sources that are running
// on the local machine ?
// If TRUE then local sources will be visible, if FALSE then they
// will not.
bool show_local_sources;
// Which groups do you want to search in for sources
const char* p_groups;
// The list of additional IP addresses that exist that we should query for
// sources on. For instance, if you want to find the sources on a remote machine
// that is not on your local sub-net then you can put a comma seperated list of
// those IP addresses here and those sources will be available locally even though
// they are not mDNS discoverable. An example might be "12.0.0.8,13.0.12.8".
// When none is specified the registry is used.
// Default = nullptr;
const char* p_extra_ips;
#if NDILIB_CPP_DEFAULT_CONSTRUCTORS
NDIlib_find_create_t(bool show_local_sources_ = true, const char* p_groups_ = nullptr, const char* p_extra_ips_ = nullptr);
#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS
} NDIlib_find_create_t;
//**************************************************************************************************************************
// Create a new finder instance. This will return nullptr if it fails.
// This function is deprecated, please use NDIlib_find_create_v2 if you can. This function
// ignores the p_extra_ips member and sets it to the default.
PROCESSINGNDILIB_API
NDIlib_find_instance_t NDIlib_find_create_v2(const NDIlib_find_create_t* p_create_settings NDILIB_CPP_DEFAULT_VALUE(nullptr));
// Create a new finder instance. This will return nullptr if it fails.
// This function is deprecated, please use NDIlib_find_create_v2 if you can. This function
// ignores the p_extra_ips member and sets it to the default.
PROCESSINGNDILIB_API
NDIlib_find_instance_t NDIlib_find_create_v3(const NDIlib_find_create_t* p_create_settings NDILIB_CPP_DEFAULT_VALUE(nullptr), const char* p_config_data NDILIB_CPP_DEFAULT_VALUE(nullptr));
// This will destroy an existing finder instance.
PROCESSINGNDILIB_API
void NDIlib_find_destroy(NDIlib_find_instance_t p_instance);
// This function will recover the current set of sources (i.e. the ones that exist right this second).
// The char* memory buffers returned in NDIlib_source_t are valid until the next call to NDIlib_find_get_current_sources or a call to NDIlib_find_destroy.
// For a given NDIlib_find_instance_t, do not call NDIlib_find_get_current_sources asynchronously.
PROCESSINGNDILIB_API
const NDIlib_source_t* NDIlib_find_get_current_sources(NDIlib_find_instance_t p_instance, uint32_t* p_no_sources);
// This will allow you to wait until the number of online sources have changed.
PROCESSINGNDILIB_API
bool NDIlib_find_wait_for_sources(NDIlib_find_instance_t p_instance, uint32_t timeout_in_ms);
#pragma once
//***********************************************************************************************************************************************
//
// Copyright(c) 2014-2018 NewTek, inc
//
//***********************************************************************************************************************************************
// It is important when using video to realize that often you are using differenc clocks
// for different parts of the signal chain. Within NDI, the sender can send at the clock rate
// that it wants and the receiver will receive it at that rate. The receiver however is very
// unlikely to share the exact same clock rate in many cases. For instance, bear in mind that
// computer clocks rely on crystals which while all rated for the same frequency are still not
// exact. If you sending computer has an audio clock that it "thinks" is 48000Hz, to the receiver
// computer that has a different audio clock this might be 48001Hz or 47998Hz. While these
// differences might appear small they accumulate over time and can cause audio to either
// slightly drift out of sync (it is receiving more audio sample sthan it needs to play back)
// or might cause audio glitches because it is not receiving enough audio samples. While we
// have described the situation for audio, the same exact problem occurs for video sources;
// it is commonly thought that this can be solved by simply having a "frame buffer" and that
// displaying the "most recently received video frame" will solve these timing discrepencies.
// Unfortunately this is not the case and when it is done because of the variance in clock
// timings, it is veyr common the the video will appear the "jitter" when the sending and
// receiving closks are almost in alignment. The solution to these problems is to implement
// a "time base corrector" for the video clock which is a device that uses hysterisis to know
// when the best time is to either drop or insert a video frame such that the video is most
// likely to play back smoothly, and audio should be dynamically audio sampled (with a high
// order resampling filter) to adaptively track any clocking differences. Implementing these
// components is very difficult to get entirely correct under all scenarios and this
// implementation is provided to facilitate this and help people who are building real time
// video applications to receive audio and video without needing to undertake the full
// complexity of implementing such clock devices.
//
// Another way to look at what this class does is that it transforms "push" sources (i.e.
// NDI sources in which the data is pushed from the sender to the receiver) into "pull"
// sources in which a host application is pulling the data down-stream. The frame-sync
// automatically tracks all clocks to acheive the best video performance doing this
// operation.
//
// In addition to time-base correction operations, these implementations also will automatically
// detect and correct timing jitter that might occur. This will internally correct for timing
// anomolies that might be caused by network, sender or receiver side timing errors caused
// by CPU limitatoins, network bandwidth fluctuations, etc...
//
// A very common use of a frame-synchronizer might be if you are displaying video on screen
// timed to the GPU v-sync, you should use sych a device to convert from the incoming time-base
// into the time-base of the GPU.
//
// The following are common times that you want to use a frame-synchronizer
// Video playback on screen : Yes, you want the clock to be synced with vertical refresh.
// Audio playback through sound card : Yes you want the clock to be synced with your sound card clock.
// Video mixing : Yes you want the input video clocks to all be synced to your output video clock.
// Audio mixing : Yes, you want all input audio clocks to be brough into sync with your output audio clock.
// Recording a single channel : No, you want to record the signal in it's raw form without any reclocking.
// Recording multiple channels : Maybe. If you want to sync some input channels to match a master clock so that
// they can be ISO edited, then you might want a frame-sync.
// The type instance for a frame-synchronizer
typedef void* NDIlib_framesync_instance_t;
// Create a frame synchronizer instance that can be used to get frames
// from a receiver. Once this receiver has been bound to a frame-sync
// then you should use it in order to receover video frames. You can
// continue to use the underlying receiver for other operations (tally,
// PTZ, etc...). Note that it remains your responsability to destroy the
// receiver even when a frame-sync is using it. You should always destroy
// the receiver after the framesync has been destroyed.
PROCESSINGNDILIB_API
NDIlib_framesync_instance_t NDIlib_framesync_create(NDIlib_recv_instance_t p_receiver);
// Destroy a frame-sync implemenration
PROCESSINGNDILIB_API
void NDIlib_framesync_destroy(NDIlib_framesync_instance_t p_instance);
// This function will pull audio samples from the frame-sync queue. This function
// will always return data immediately, inserting silence if no current audio
// data is present. You should call this at the rate that you want audio and it
// will automatically adapt the incoming audio signal to match the rate at which
// you are calling by using dynamic audio sampling. Note that you have no obligation
// that your requested sample rate, no channels and no samples match the incoming signal
// and all combinations of conversions are supported. If you specify a sample-rate=0
// or no_channels=0 then it will use the original sample rate of the buffer.
PROCESSINGNDILIB_API
void NDIlib_framesync_capture_audio(// The frame sync instance data
NDIlib_framesync_instance_t p_instance,
// The destination audio buffer that you wish to have filled in.
NDIlib_audio_frame_v2_t* p_audio_data,
// Your desired sample rate, number of channels and the number of desired samples.
int sample_rate, int no_channels, int no_samples);
// Free audio returned by NDIlib_framesync_capture_audio
PROCESSINGNDILIB_API
void NDIlib_framesync_free_audio(// The frame sync instance data
NDIlib_framesync_instance_t p_instance,
// The destination audio buffer that you wish to have filled in.
NDIlib_audio_frame_v2_t* p_audio_data);
// This function will pull video samples from the frame-sync queue. This function
// will always immediately return a video sample by using time-base correction. You can
// specify the desired field type which is then used to return the best possible frame.
// Note that field based frame-synronization means that the frame-synchronizer attempts
// to match the fielded input phase with the frame requests so that you have the most
// correct possible field ordering on output. Note that the same frame can be returned
// multiple times.
//
// If no video frame has evern been received, this will return NDIlib_video_frame_v2_t as
// an empty (all zero) structure. The reason for this is that it allows you to determine
// that there has not yet been any video and act accordingly. For instamce you might want
// to display a constant frame output at a particular video format, or black.
PROCESSINGNDILIB_API
void NDIlib_framesync_capture_video(// The frame sync instance data
NDIlib_framesync_instance_t p_instance,
// The destination audio buffer that you wish to have filled in.
NDIlib_video_frame_v2_t* p_video_data,
// The frame type that you would prefer, all effort is made to match these.
NDIlib_frame_format_type_e field_type NDILIB_CPP_DEFAULT_VALUE(NDIlib_frame_format_type_progressive));
// Free audio returned by NDIlib_framesync_capture_video
PROCESSINGNDILIB_API
void NDIlib_framesync_free_video(// The frame sync instance data
NDIlib_framesync_instance_t p_instance,
// The destination audio buffer that you wish to have filled in.
NDIlib_video_frame_v2_t* p_video_data);
#pragma once
// NOTE : The following MIT license applies to this file ONLY and not to the SDK as a whole. Please review the SDK documentation
// for the description of the full license terms, which are also provided in the file "NDI License Agreement.pdf" within the SDK or
// online at http://new.tk/ndisdk_license/. Your use of any part of this SDK is acknowledgment that you agree to the SDK license
// terms. The full NDI SDK may be downloaded at https://www.newtek.com/ndi/sdk/
//
//***********************************************************************************************************************************************
//
// Copyright(c) 2014-2018 NewTek, inc
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
// merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//***********************************************************************************************************************************************
// C++ implementations of default constructors are here to avoid them needing to be inline with
// all of the rest of the code.
// All the structs used and reasonable defaults are here
inline NDIlib_source_t::NDIlib_source_t(const char* p_ndi_name_, const char* p_url_address_)
: p_ndi_name(p_ndi_name_), p_url_address(p_url_address_) {}
inline NDIlib_video_frame_v2_t::NDIlib_video_frame_v2_t(int xres_, int yres_, NDIlib_FourCC_type_e FourCC_, int frame_rate_N_, int frame_rate_D_,
float picture_aspect_ratio_, NDIlib_frame_format_type_e frame_format_type_,
int64_t timecode_, uint8_t* p_data_, int line_stride_in_bytes_, const char* p_metadata_, int64_t timestamp_)
: xres(xres_), yres(yres_), FourCC(FourCC_), frame_rate_N(frame_rate_N_), frame_rate_D(frame_rate_D_),
picture_aspect_ratio(picture_aspect_ratio_), frame_format_type(frame_format_type_),
timecode(timecode_), p_data(p_data_), line_stride_in_bytes(line_stride_in_bytes_), p_metadata(p_metadata_), timestamp(timestamp_) {}
inline NDIlib_audio_frame_v2_t::NDIlib_audio_frame_v2_t(int sample_rate_, int no_channels_, int no_samples_, int64_t timecode_, float* p_data_,
int channel_stride_in_bytes_, const char* p_metadata_, int64_t timestamp_)
: sample_rate(sample_rate_), no_channels(no_channels_), no_samples(no_samples_), timecode(timecode_),
p_data(p_data_), channel_stride_in_bytes(channel_stride_in_bytes_), p_metadata(p_metadata_), timestamp(timestamp_) {}
inline NDIlib_video_frame_t::NDIlib_video_frame_t(int xres_, int yres_, NDIlib_FourCC_type_e FourCC_, int frame_rate_N_, int frame_rate_D_,
float picture_aspect_ratio_, NDIlib_frame_format_type_e frame_format_type_,
int64_t timecode_, uint8_t* p_data_, int line_stride_in_bytes_)
: xres(xres_), yres(yres_), FourCC(FourCC_), frame_rate_N(frame_rate_N_), frame_rate_D(frame_rate_D_),
picture_aspect_ratio(picture_aspect_ratio_), frame_format_type(frame_format_type_),
timecode(timecode_), p_data(p_data_), line_stride_in_bytes(line_stride_in_bytes_) {}
inline NDIlib_audio_frame_t::NDIlib_audio_frame_t(int sample_rate_, int no_channels_, int no_samples_, int64_t timecode_, float* p_data_,
int channel_stride_in_bytes_)
: sample_rate(sample_rate_), no_channels(no_channels_), no_samples(no_samples_), timecode(timecode_),
p_data(p_data_), channel_stride_in_bytes(channel_stride_in_bytes_) {}
inline NDIlib_metadata_frame_t::NDIlib_metadata_frame_t(int length_, int64_t timecode_, char* p_data_)
: length(length_), timecode(timecode_), p_data(p_data_) {}
inline NDIlib_tally_t::NDIlib_tally_t(bool on_program_, bool on_preview_)
: on_program(on_program_), on_preview(on_preview_) {}
inline NDIlib_routing_create_t::NDIlib_routing_create_t(const char* p_ndi_name_, const char* p_groups_)
: p_ndi_name(p_ndi_name_), p_groups(p_groups_) {}
inline NDIlib_recv_create_v3_t::NDIlib_recv_create_v3_t(const NDIlib_source_t source_to_connect_to_, NDIlib_recv_color_format_e color_format_,
NDIlib_recv_bandwidth_e bandwidth_, bool allow_video_fields_, const char* p_ndi_name_)
: source_to_connect_to(source_to_connect_to_), color_format(color_format_), bandwidth(bandwidth_), allow_video_fields(allow_video_fields_), p_ndi_recv_name(p_ndi_name_) {}
inline NDIlib_recv_create_t::NDIlib_recv_create_t(const NDIlib_source_t source_to_connect_to_, NDIlib_recv_color_format_e color_format_,
NDIlib_recv_bandwidth_e bandwidth_, bool allow_video_fields_)
: source_to_connect_to(source_to_connect_to_), color_format(color_format_), bandwidth(bandwidth_), allow_video_fields(allow_video_fields_) {}
inline NDIlib_recv_performance_t::NDIlib_recv_performance_t(void)
: video_frames(0), audio_frames(0), metadata_frames(0) {}
inline NDIlib_recv_queue_t::NDIlib_recv_queue_t(void)
: video_frames(0), audio_frames(0), metadata_frames(0) {}
inline NDIlib_recv_recording_time_t::NDIlib_recv_recording_time_t(void)
: no_frames(0), start_time(0), last_time(0) {}
inline NDIlib_send_create_t::NDIlib_send_create_t(const char* p_ndi_name_, const char* p_groups_, bool clock_video_, bool clock_audio_)
: p_ndi_name(p_ndi_name_), p_groups(p_groups_), clock_video(clock_video_), clock_audio(clock_audio_) {}
inline NDIlib_find_create_t::NDIlib_find_create_t(bool show_local_sources_, const char* p_groups_, const char* p_extra_ips_)
: show_local_sources(show_local_sources_), p_groups(p_groups_), p_extra_ips(p_extra_ips_) {}
inline NDIlib_audio_frame_interleaved_16s_t::NDIlib_audio_frame_interleaved_16s_t(int sample_rate_, int no_channels_, int no_samples_, int64_t timecode_, int reference_level_, int16_t* p_data_)
: sample_rate(sample_rate_), no_channels(no_channels_), no_samples(no_samples_), timecode(timecode_),
reference_level(reference_level_), p_data(p_data_) {}
inline NDIlib_audio_frame_interleaved_32s_t::NDIlib_audio_frame_interleaved_32s_t(int sample_rate_, int no_channels_, int no_samples_, int64_t timecode_, int reference_level_, int32_t* p_data_)
: sample_rate(sample_rate_), no_channels(no_channels_), no_samples(no_samples_), timecode(timecode_),
reference_level(reference_level_), p_data(p_data_) {}
inline NDIlib_audio_frame_interleaved_32f_t::NDIlib_audio_frame_interleaved_32f_t(int sample_rate_, int no_channels_, int no_samples_, int64_t timecode_, float* p_data_)
: sample_rate(sample_rate_), no_channels(no_channels_), no_samples(no_samples_), timecode(timecode_), p_data(p_data_) {}
#pragma once
// NOTE : The following MIT license applies to this file ONLY and not to the SDK as a whole. Please review the SDK documentation
// for the description of the full license terms, which are also provided in the file "NDI License Agreement.pdf" within the SDK or
// online at http://new.tk/ndisdk_license/. Your use of any part of this SDK is acknowledgment that you agree to the SDK license
// terms. The full NDI SDK may be downloaded at https://www.newtek.com/ndi/sdk/
//
//***********************************************************************************************************************************************
//
// Copyright(c) 2014-2018 NewTek, inc
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
// merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//***********************************************************************************************************************************************
// Is this library being compiled, or imported by another application.
#ifdef _WIN32
#define PROCESSINGNDILIB_DEPRECATED __declspec(deprecated)
#ifdef PROCESSINGNDILIB_EXPORTS
#ifdef __cplusplus
#define PROCESSINGNDILIB_API extern "C" __declspec(dllexport)
#else // __cplusplus
#define PROCESSINGNDILIB_API __declspec(dllexport)
#endif // __cplusplus
#else // PROCESSINGNDILIB_EXPORTS
#ifdef __cplusplus
#define PROCESSINGNDILIB_API extern "C" __declspec(dllimport)
#else // __cplusplus
#define PROCESSINGNDILIB_API __declspec(dllimport)
#endif // __cplusplus
#ifdef _WIN64
#define NDILIB_LIBRARY_NAME "Processing.NDI.Lib.x64.dll"
#define NDILIB_REDIST_FOLDER "NDI_RUNTIME_DIR_V3"
#define NDILIB_REDIST_URL "http://new.tk/NDIRedistV3"
#else // _WIN64
#define NDILIB_LIBRARY_NAME "Processing.NDI.Lib.x86.dll"
#define NDILIB_REDIST_FOLDER "NDI_RUNTIME_DIR_V3"
#define NDILIB_REDIST_URL "http://new.tk/NDIRedistV3"
#endif // _WIN64
#endif // PROCESSINGNDILIB_EXPORTS
#else // _WIN32
#ifdef __APPLE__
#define NDILIB_LIBRARY_NAME "libndi.3.dylib"
#define NDILIB_REDIST_FOLDER "NDI_RUNTIME_DIR_V3"
#define NDILIB_REDIST_URL "http://new.tk/NDIRedistV3Apple"
#else // __APPLE__
#define NDILIB_LIBRARY_NAME "libndi.so.3"
#define NDILIB_REDIST_FOLDER "NDI_RUNTIME_DIR_V3"
#define NDILIB_REDIST_URL ""
#endif // __APPLE__
#define PROCESSINGNDILIB_DEPRECATED
#ifdef __cplusplus
#define PROCESSINGNDILIB_API extern "C" __attribute((visibility("default")))
#else // __cplusplus
#define PROCESSINGNDILIB_API __attribute((visibility("default")))
#endif // __cplusplus
#endif // _WIN32
#ifndef NDILIB_CPP_DEFAULT_CONSTRUCTORS
#ifdef __cplusplus
#define NDILIB_CPP_DEFAULT_CONSTRUCTORS 1
#else // __cplusplus
#define NDILIB_CPP_DEFAULT_CONSTRUCTORS 0
#endif // __cplusplus
#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS
#ifndef NDILIB_CPP_DEFAULT_VALUE
#ifdef __cplusplus
#define NDILIB_CPP_DEFAULT_VALUE(a) =(a)
#else // __cplusplus
#define NDILIB_CPP_DEFAULT_VALUE(a)
#endif // __cplusplus
#endif // NDILIB_CPP_DEFAULT_VALUE
// Data structures shared by multiple SDKs
#include "Processing.NDI.compat.h"
#include "Processing.NDI.structs.h"
// This is not actually required, but will start and end the libraries which might get
// you slightly better performance in some cases. In general it is more "correct" to
// call these although it is not required. There is no way to call these that would have
// an adverse impact on anything (even calling destroy before you've deleted all your
// objects). This will return false if the CPU is not sufficiently capable to run NDILib
// currently NDILib requires SSE4.2 instructions (see documentation). You can verify
// a specific CPU against the library with a call to NDIlib_is_supported_CPU()
PROCESSINGNDILIB_API
bool NDIlib_initialize(void);
PROCESSINGNDILIB_API