add 3rd party folders back

This commit is contained in:
2025-10-12 21:09:32 +03:00
parent 9cca8147d2
commit aaa0f93a0f
77 changed files with 13519 additions and 0 deletions

63
3rd/libomt/.gitattributes vendored Normal file
View File

@@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

363
3rd/libomt/.gitignore vendored Normal file
View File

@@ -0,0 +1,363 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd

21
3rd/libomt/LICENSE.txt Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Open Media Transport Contribitors
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.

38
3rd/libomt/README.md Normal file
View File

@@ -0,0 +1,38 @@
# libomt
libomt is a C wrapper for the libomnet library.
libomt uses the .NET Native AOT Deployment to build a native shared library with C exports
## Getting Started
Prebuilt binaries of libomt for both Windows and MacOS is available in the Releases page for libomtnet here:
https://github.com/openmediatransport/libomtnet/releases
## Requirements
libvmx shared library (included in the prebuilt binaries)
.NET 8.0 for Windows, Linux or MacOS (.NET not required unless compiling from source)
## Compiling
1. Setup a folder structure with both libomtnet and libomt as follows:
[root]
/libomtnet
/libomt
2. The build process will reference and build the .NET Standard library in the ../libomtnet folder
3. Run the build script for the desired platform from the build directory.
4. A shared library and a .lib file should be generated in the platform native directory.
On Windows this is usually bin\Release\net8.0\win-x64\native
## Using the library in your project
1. Include the libomt.h file in your C/C++ application
2. Add the libomt.lib library
Note: libomtnet.dll is not needed as it is automatically built into the libomt shared library.

View File

@@ -0,0 +1 @@
dotnet publish ../libomt.sln -r linux-arm64 -c Release

View File

@@ -0,0 +1 @@
dotnet publish ../libomt.sln -r linux-x64 -c Release

View File

@@ -0,0 +1,9 @@
dotnet publish ../libomt.sln -r osx-arm64 -c Release
dotnet publish ../libomt.sln -r osx-x64 -c Release
install_name_tool -id @rpath/libomt.dylib ../bin/Release/net8.0/osx-arm64/publish/libomt.dylib
install_name_tool -id @rpath/libomt.dylib ../bin/Release/net8.0/osx-arm64/native/libomt.dylib
install_name_tool -id @rpath/libomt.dylib ../bin/Release/net8.0/osx-x64/publish/libomt.dylib
install_name_tool -id @rpath/libomt.dylib ../bin/Release/net8.0/osx-x64/native/libomt.dylib
lipo -create -output libomt.dylib ../bin/Release/net8.0/osx-x64/native/libomt.dylib ../bin/Release/net8.0/osx-arm64/native/libomt.dylib
install_name_tool -id @rpath/libomt.dylib libomt.dylib
install_name_tool -add_rpath @loader_path libomt.dylib

View File

@@ -0,0 +1 @@
dotnet publish ../libomt.sln -r win-arm64 -c Release

View File

@@ -0,0 +1 @@
dotnet publish ../libomt.sln -r win-x64 -c Release

28
3rd/libomt/libomt.csproj Normal file
View File

@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishAot>true</PublishAot>
<Version>1.0.0.13</Version>
<Configurations>Debug;Release</Configurations>
</PropertyGroup>
<ItemGroup>
<Reference Include="libomtnet">
<HintPath>..\libomtnet\bin\Release\netstandard2.0\libomtnet.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<LinkerArg Condition="$(RuntimeIdentifier.StartsWith('osx'))" Include="-mmacosx-version-min=10.15" />
</ItemGroup>
<ItemGroup>
<None Update="libomt.h">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

598
3rd/libomt/libomt.h Normal file
View File

@@ -0,0 +1,598 @@
/*
* MIT License
*
* Copyright (c) 2025 Open Media Transport Contributors
*
* 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.
*
*/
#pragma once
#ifdef _MSC_VER
#pragma comment(lib, "libomt.lib")
#endif
#define OMT_MAX_STRING_LENGTH 1024
#ifdef __cplusplus
#include <cstdint>
#else
#include <stdint.h>
#endif
typedef enum OMTFrameType
{
OMTFrameType_None = 0,
OMTFrameType_Metadata = 1,
OMTFrameType_Video = 2,
OMTFrameType_Audio = 4,
OMTFrameType_INT32 = 0x7fffffff //Ensure int type in C
} OMTFrameType;
/**
* Supported Codecs:
*
* VMX1 = Fast video codec
*
* UYVY = 16bpp YUV format
*
* YUY2 = 16bpp YUV format YUYV pixel order
*
* UYVA = 16pp YUV format immediately followed by an alpha plane
*
* NV12 = Planar 4:2:0 YUV format. Y plane followed by interleaved half height U/V plane.
*
* YV12 = Planar 4:2:0 YUV format. Y plane followed by half height U and V planes.
*
* BGRA = 32bpp RGBA format (Same as ARGB32 on Win32)
*
* P216 = Planar 4:2:2 YUV format. 16bit Y plane followed by interlaved 16bit UV plane.
*
* PA16 = Same as P216 folowed by an additional 16bit alpha plane.
*
* FPA1 = Floating-point Planar Audio 32bit
*/
typedef enum OMTCodec
{
OMTCodec_VMX1 = 0x31584D56,
OMTCodec_FPA1 = 0x31415046, //Planar audio
OMTCodec_UYVY = 0x59565955,
OMTCodec_YUY2 = 0x32595559,
OMTCodec_BGRA = 0x41524742,
OMTCodec_NV12 = 0x3231564E,
OMTCodec_YV12 = 0x32315659,
OMTCodec_UYVA = 0x41565955,
OMTCodec_P216 = 0x36313250,
OMTCodec_PA16 = 0x36314150
} OMTCodec;
/**
* Specify the video encoding quality.
*
* If set to Default, the Sender is configured to allow suggestions from all Receivers.
*
* The highest suggest amongst all receivers is then selected.
*
* If a Receiver is set to Default, then it will defer the quality to whatever is set amongst other Receivers.
*/
typedef enum OMTQuality
{
OMTQuality_Default = 0,
OMTQuality_Low = 1,
OMTQuality_Medium = 50,
OMTQuality_High = 100,
OMTQuality_INT32 = 0x7fffffff //Ensure int type in C
} OMTQuality;
/**
* Specify the color space of the uncompressed Frame. This is used to determine the color space for YUV<>RGB conversions internally.
*
* If undefined, the codec will assume BT601 for heights < 720, BT709 for everything else.
*
*/
typedef enum OMTColorSpace
{
OMTColorSpace_Undefined = 0,
OMTColorSpace_BT601 = 601,
OMTColorSpace_BT709 = 709,
OMTColorSpace_INT32 = 0x7fffffff //Ensure int type in C
} OMTColorSpace;
/**
* Flags set on video frames:
*
* Interlaced: Frames are interlaced
*
* Alpha: Frames contain an alpha channel. If this is not set, BGRA will be encoded as BGRX and UYVA will be encoded as UYVY.
*
* PreMultiplied: When combined with Alpha, alpha channel is premultiplied, otherwise straight
*
* Preview: Frame is a special 1/8th preview frame
*
* HighBitDepth: Sender automatically adds this flag for frames encoded using P216 or PA16 pixel formats.
*
* Set this manually for VMX1 compressed data where the the frame was originally encoded using P216 or PA16.
* This determines which pixel format is selected on the decode side.
*
*/
typedef enum OMTVideoFlags
{
OMTVideoFlags_None = 0,
OMTVideoFlags_Interlaced = 1,
OMTVideoFlags_Alpha = 2,
OMTVideoFlags_PreMultiplied = 4,
OMTVideoFlags_Preview = 8,
OMTVideoFlags_HighBitDepth = 16,
OMTVideoFlags_INT32 = 0x7fffffff //Ensure int type in C
} OMTVideoFlags;
/**
* Specify the preferred uncompressed video format of decoded frames.
*
* UYVY is always the fastest, if no alpha channel is required.
*
* UYVYorBGRA will provide BGRA only when alpha channel is present.
*
* BGRA will always convert back to BGRA
*
* UYVYorUYVA will provide UYVA only when alpha channel is present.
*
* UYVYorUYVAorP216orPA16 will provide P216 if sender encoded with high bit depth, or PA16 if sender encoded with high bit depth and alpha. Otherwise same as UYVYorUYVA.
*
*/
typedef enum OMTPreferredVideoFormat
{
OMTPreferredVideoFormat_UYVY = 0,
OMTPreferredVideoFormat_UYVYorBGRA = 1,
OMTPreferredVideoFormat_BGRA = 2,
OMTPreferredVideoFormat_UYVYorUYVA = 3,
OMTPreferredVideoFormat_UYVYorUYVAorP216orPA16 = 4,
OMTPreferredVideoFormat_P216 = 5,
OMTPreferredVideoFormat_INT32 = 0x7fffffff //Ensure int type in C
} OMTPreferredVideoFormat;
/**
* Flags to enable certain features on a Receiver:
*
* Preview: Receive only a 1/8th preview of the video.
*
* IncludeCompressed: Include a copy of the compressed VMX1 video frames for further processing or recording.
*
* CompressedOnly: Include only the compressed VMX1 video frame without decoding. In this instance DataLength will always be 0.
*/
typedef enum OMTReceiveFlags
{
OMTReceiveFlags_None = 0,
OMTReceiveFlags_Preview = 1,
OMTReceiveFlags_IncludeCompressed = 2,
OMTReceiveFlags_CompressedOnly = 4,
OMTReceiveFlags_INT32 = 0x7fffffff //Ensure int type in C
} OMTReceiveFlags;
/// <summary>
/// Tally where 0 = off, 1 = on.
/// </summary>
typedef struct OMTTally
{
int preview;
int program;
} OMTTally;
typedef struct OMTSenderInfo
{
char ProductName[OMT_MAX_STRING_LENGTH];
char Manufacturer[OMT_MAX_STRING_LENGTH];
char Version[OMT_MAX_STRING_LENGTH];
char Reserved1[OMT_MAX_STRING_LENGTH];
char Reserved2[OMT_MAX_STRING_LENGTH];
char Reserved3[OMT_MAX_STRING_LENGTH];
} OMTSenderInfo;
typedef struct OMTStatistics
{
int64_t BytesSent;
int64_t BytesReceived;
int64_t BytesSentSinceLast;
int64_t BytesReceivedSinceLast;
int64_t Frames;
int64_t FramesSinceLast;
int64_t FramesDropped;
//Time in milliseconds spent encoding so far this instance. Can be divided by Frames to work out per frame times.
int64_t CodecTime;
//Time in milliseconds of the last frame encoded.
int64_t CodecTimeSinceLast;
int64_t Reserved1;
int64_t Reserved2;
int64_t Reserved3;
int64_t Reserved4;
int64_t Reserved5;
int64_t Reserved6;
int64_t Reserved7;
} OMTStatistics;
/**
* Media Frame struct for sending receiving.
*
* IMPORTANT: Zero this struct before use. OMTMediaFrame frame = {}; is sufficient.
*/
typedef struct OMTMediaFrame
{
//Specify the type of frame. This determines which values of this struct are valid/used.
enum OMTFrameType Type;
/**
* This is a timestamp where 1 second = 10,000,000
*
* This should not be left 0 unless this is the very first frame.
*
* This should represent the accurate time the frame or audio sample was generated at the original source and be used on the receiving end to synchronize
* and record to file as a presentation timestamp (pts).
*
* A special value of -1 can be specified to tell the Sender to generate timestamps and throttle as required to maintain
* the specified FrameRate or SampleRate of the frame.
*/
int64_t Timestamp;
/**
* Sending:
*
* Video: 'UYVY', 'YUY2', 'NV12', 'YV12, 'BGRA', 'UYVA', 'VMX1' are supported (BGRA will be treated as BGRX and UYVA as UYVY where alpha flags are not set)
*
* Audio: Only 'FPA1' is supported (32bit floating point planar audio)
*
* Receiving:
*
* Video: Only 'UYVY', 'UYVA', 'BGRA' and 'BGRX' are supported
*
* Audio: Only 'FPA1' is supported (32bit floating point planar audio)
*
*/
enum OMTCodec Codec;
//Video Properties
int Width;
int Height;
//Stride in bytes of each row of pixels. Typically width*2 for UYVY, width*4 for BGRA and just width for planar formats.
int Stride;
enum OMTVideoFlags Flags;
// Frame Rate Numerator/Denominator in Frames Per Second, for example Numerator 60 and Denominator 1 is 60 frames per second.
int FrameRateN;
int FrameRateD;
// Display aspect ratio expressed as a ratio of width/height. For example 1.777777777777778 for 16/9
float AspectRatio;
enum OMTColorSpace ColorSpace;
//Audio Properties
// Sample rate, i.e 48000, 44100 etc
int SampleRate;
// Audio Channels. A maximum of 32 channels are supported.
int Channels;
// Number of 32bit floating point samples per channel/plane. Each plane should contain SamplesPerChannel*4 bytes.
int SamplesPerChannel;
//Data Properties
/**
* Video: Uncompressed pixel data (or compressed VMX1 data when sending and Codec set to VMX1)
*
* Audio: Planar 32bit floating point audio
*
* Metadata: UTF-8 encoded XML string with terminating null character
*/
void* Data;
/**
* Video: Number of bytes total including stride
*
* Audio: Number of bytes (SamplesPerChannel * Channels * 4)
*
* Metadata: Number of bytes in UTF-8 encoded string + 1 for terminating null character.
*/
int DataLength;
/**
* Receive only. Use standard Data/DataLength if sending VMX1 frames with a Sender
*
* If IncludeCompressed or CompressedOnly OMTReceiveFlags is set, this will include the original compressed video frame in VMX1 format.
*
* This could then be muxed into an AVI or MOV file using FFmpeg or similar APIs
*/
void* CompressedData;
int CompressedLength;
//Frame MetaData Properties
// Per frame metadata as UTF-8 encoded string + 1 for null character. Up to 65536 bytes supported.
void* FrameMetadata;
// Length in bytes of per frame metadata including null character
int FrameMetadataLength;
} OMTMediaFrame;
typedef long long omt_receive_t;
typedef long long omt_send_t;
#ifdef __cplusplus
extern "C" {
#endif
/**
* =================================================
* Discovery
* =================================================
*/
/**
* Returns a list of sources currently available on the network.
*
* Return value is an array of UTF-8 char pointers.
*
* This array is valid until the next call to getaddresses.
*
* @param[in] count Number of entries in the returned array.
*/
char** omt_discovery_getaddresses(int * count);
/**
* =================================================
* Receive
* =================================================
*/
/**
* Create a new Receiver and begin connecting to the Sender specified by address.
* @param[in] address Address to connect to, either the full name provided by OMTDiscovery or a URL in the format omt://hostname:port</param>
* @param[in] frameTypes Specify the types of frames to receive, for example to setup audio only or metadata only feeds
* @param[in] format Specify the preferred uncompressed video format to receive. UYVYorBGRA will only receive BGRA frames when an alpha channel is present.
* @param[in] flags Specify optional flags such as requesting a Preview feed only, or including the compressed (VMX) data with each frame for further processing (or recording).
*/
omt_receive_t* omt_receive_create(const char* address, OMTFrameType frameTypes, OMTPreferredVideoFormat format, OMTReceiveFlags flags);
/**
* Destroy instance created with omt_receive_create.
*
* Make sure any threads currently accessing the omt_receive_ functions with this instance are closed before calling.
*/
void omt_receive_destroy(omt_receive_t* instance);
/**
* Receive any available frames in the buffer, or wait for frames if empty
*
* Returns a valid OMTMediaFrame if a frame was found, null if timed out.
*
* The data in this struct is valid for until the next call to omt_receive for this instance and frameType.
*
* Pointers do not need to be freed by the caller.
*
* @param[in] frameTypes The frame types to receive. Set multiple types to receive them all in a single thread. Set individually if using separate threads for audio/video/metadata
* @param[in] timeoutMilliseconds The maximum time to wait for a new frame if empty
*/
OMTMediaFrame* omt_receive(omt_receive_t* instance, OMTFrameType frameTypes, int timeoutMilliseconds);
/**
* Send a metadata frame to the sender. Does not support other frame types.
*/
int omt_receive_send(omt_receive_t* instance, OMTMediaFrame* frame);
void omt_receive_settally(omt_receive_t* instance, OMTTally* tally);
/**
* Receives the current tally state across all connections to a Sender, not just this Receiver.
*
* If this function times out, the last known tally state will be received.
*
* Returns 0 if timed out or tally didn't change. 1 otherwise.
*
*/
int omt_receive_gettally(omt_send_t* instance, int timeoutMilliseconds, OMTTally* tally);
/**
* Change the flags on the current receive instance. Will apply from the next frame received.
* This allows dynamic switching between preview mode.
*/
void omt_receive_setflags(omt_receive_t* instance, OMTReceiveFlags flags);
/**
* Inform the sender of the quality preference for this receiver. See OMTQuality documentation for more information.
*/
void omt_receive_setsuggestedquality(omt_receive_t* instance, OMTQuality quality);
/**
* Retrieve optional information describing the sender. Valid only when connected. Returns null if disconnected or no sender information was provided by sender.
*/
void omt_receive_getsenderinformation(omt_receive_t* instance, OMTSenderInfo* info);
/**
* Retrieve statistics for video and audio.
*
*/
void omt_receive_getvideostatistics(omt_receive_t* instance, OMTStatistics* stats);
void omt_receive_getaudiostatistics(omt_receive_t* instance, OMTStatistics* stats);
/**
* =================================================
* Send
* =================================================
*/
/**
* Create a new instance of the OMT Sender
*
* @param[in] name Specify the name of the source not including hostname
* @param[in] quality Specify the quality to use for video encoding. If Default, this can be automatically adjusted based on Receiver requirements.
*/
omt_send_t* omt_send_create(const char* name, OMTQuality quality);
/**
* Optionally set information describing the sender.
*/
void omt_send_setsenderinformation(omt_send_t* instance, OMTSenderInfo* info);
/**
* Add to the list of metadata that is sent immediately upon a new connection by a receiver.
*
* This metadata will also be immediately sent to any currently connected receivers.
*
* @param[in] metadata XML metadata in UTF-8 encoding followed by a null terminator.
*
*/
void omt_send_addconnectionmetadata(omt_send_t* instance, const char* metadata);
/**
* Clears the list of metadata that is sent immediately upon a new connection by a receiver.
*/
void omt_send_clearconnectionmetadata(omt_send_t* instance);
/**
* Use this to inform receivers to connect to a different address.
*
* This is used to create a "virtual source" that can be dynamically switched as needed.
*
* This is useful for scenarios where receiver needs to be changed remotely.
*
* @param[in] newAddress The new address. Set to null or empty to disable redirect.
*/
void omt_send_setredirect(omt_send_t* instance, const char* newAddress);
/**
* Retrieve the Discovery address in the format HOSTNAME (NAME)
*
* Returns the length in bytes of the UTF-8 encoded value including null terminator.
*
* maxLength specifies the maximum amount of bytes allocated to value by the caller.
*/
int omt_send_getaddress(omt_send_t* instance, char* address, int maxLength);
/**
* Destroy instance created with omt_send_create.
*
* Make sure any threads currently accessing the omt_send_ functions with this instance are closed before calling.
*/
void omt_send_destroy(omt_send_t* instance);
/**
* Send a frame to any receivers currently connected.
*
* Video: 'UYVY', 'YUY2', 'NV12', 'YV12, 'BGRA', 'UYVA', 'VMX1' are supported (BGRA will be treated as BGRX and UYVA as UYVY where alpha flags are not set)
*
* Audio: Supports planar 32bit floating point audio
*
* Metadata: Supports UTF8 encoded XML
*/
int omt_send(omt_send_t* instance, OMTMediaFrame* frame);
/**
* Total number of connections to this sender. Receivers establish one connection for video/metadata and a second for audio.
*/
int omt_send_connections(omt_send_t* instance);
/**
* Receive any available metadata in the buffer, or wait for metadata if empty
*
* Returns a valid OMTMediaFrame if found, null of timed out
*/
OMTMediaFrame* omt_send_receive(omt_send_t* instance, int timeoutMilliseconds);
/**
* Receives the current tally state across all connections to a Sender.
*
* If this function times out, the last known tally state will be received.
*
* Returns 0 if timed out or tally didn't change. 1 otherwise.
*
*/
int omt_send_gettally(omt_send_t* instance, int timeoutMilliseconds, OMTTally* tally);
/**
* Retrieve statistics for video and audio.
*
*/
void omt_send_getvideostatistics(omt_send_t* instance, OMTStatistics* stats);
void omt_send_getaudiostatistics(omt_send_t* instance, OMTStatistics* stats);
/**
* =================================================
* Logging
* =================================================
*/
/**
* Specify a log file filename, including the full path, or null to disable.
*
* If this function is not called, a log file is created in the ~/.OMT/logs folder for this process on Mac and Linux, C:\ProgramData\OMT\logs on Windows.
*
* To override the default folder used for for logs, set the OMT_STORAGE_PATH environment variable prior to calling any OMT functions.
*/
void omt_setloggingfilename(const char* filename);
/**
* =================================================
* Settings
*
* These functions override the default settings which are stored in ~/.OMT/settings.xml on Mac and Linux and C:\ProgramData\OMT\settings.xml on Windows by default.
*
* To override the default folder used for for settings, set the OMT_STORAGE_PATH environment variable prior to calling any OMT functions.
*
* The following settings are currently supported:
*
* DiscoveryServer [string] specify a URL in the format omt://hostname:port to connect to for discovery. If left blank, default DNS-SD discovery behavior is enabled.
*
* NetworkPortStart [integer] specify the first port to create Send instances on. Defaults to 6400
*
* NetworkPortEnd [integer] specify the last port to create Send instances on. Defaults to 6600
*
* Settings changed here will persist only for the currently running process.
* =================================================
*/
/**
* Retrieve the current value of a string setting.
* Returns the length in bytes of the UTF-8 encoded value including null terminator.
* maxLength specifies the maximum amount of bytes allocated to value by the caller.
*/
int omt_settings_get_string(const char* name, char* value, int maxLength);
/**
* Set a string setting that will be used for the duration of this process.
* Value should be a null terminated UTF-8 encoded string.
*/
void omt_settings_set_string(const char* name, const char* value);
/**
* Retrieve the current value of the integer setting.
*/
int omt_settings_get_integer(const char* name);
/**
* Set the specified setting to an integer value.
*/
void omt_settings_set_integer(const char* name, int value);
#ifdef __cplusplus
}
#endif

25
3rd/libomt/libomt.sln Normal file
View File

@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.11.35431.28
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "libomt", "libomt.csproj", "{6D82AB51-3240-46DA-BAEF-F2DD8BB70037}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6D82AB51-3240-46DA-BAEF-F2DD8BB70037}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6D82AB51-3240-46DA-BAEF-F2DD8BB70037}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6D82AB51-3240-46DA-BAEF-F2DD8BB70037}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6D82AB51-3240-46DA-BAEF-F2DD8BB70037}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AB7BCB17-6DF5-48E2-B1EE-BA18FCC50869}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,84 @@
/*
* MIT License
*
* Copyright (c) 2025 Open Media Transport Contributors
*
* 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.
*
*/
using libomtnet;
using System.Runtime.InteropServices;
namespace libomt
{
internal class BaseInstance : OMTBase
{
protected OMTSendReceiveBase? instance;
protected IntPtr lastMetadata = IntPtr.Zero;
public bool GetTally(int millisecondsTimeout, IntPtr pTally)
{
bool result = false;
if (instance != null)
{
OMTTally tally = new OMTTally();
result = instance.GetTally(millisecondsTimeout, ref tally);
if (pTally != IntPtr.Zero)
{
Marshal.WriteInt32(pTally, tally.Preview);
Marshal.WriteInt32(pTally, 4, tally.Program);
}
}
return result;
}
public void GetAudioStatistics(IntPtr pStatistics)
{
if (instance != null)
{
OMTStatistics stats = instance.GetAudioStatistics();
stats.ToIntPtr(pStatistics);
}
}
public void GetVideoStatistics(IntPtr pStatistics)
{
if (instance != null)
{
OMTStatistics stats = instance.GetVideoStatistics();
stats.ToIntPtr(pStatistics);
}
}
protected override void DisposeInternal()
{
if (lastMetadata != IntPtr.Zero)
{
OMTMediaFrame.FreeIntPtr(lastMetadata);
lastMetadata = IntPtr.Zero;
}
if (instance != null)
{
instance.Dispose();
instance = null;
}
base.DisposeInternal();
}
}
}

View File

@@ -0,0 +1,73 @@
/*
* MIT License
*
* Copyright (c) 2025 Open Media Transport Contributors
*
* 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.
*
*/
using libomtnet;
using System.Runtime.InteropServices;
namespace libomt
{
internal class DiscoveryInstance : OMTBase
{
private OMTDiscovery instance;
private static IntPtr lastAddresses = IntPtr.Zero;
private static int lastAddressesLength = 0;
public DiscoveryInstance()
{
instance = OMTDiscovery.GetInstance();
}
public OMTDiscovery Instance { get { return instance; } }
public IntPtr GetAddresses(IntPtr addressCount)
{
if (addressCount == IntPtr.Zero) return IntPtr.Zero;
string[] addresses = instance.GetAddresses();
if (addresses.Length > 0)
{
if (lastAddresses != IntPtr.Zero)
{
InstanceHelper.FreeStringArray(lastAddresses, lastAddressesLength);
lastAddressesLength = 0;
lastAddresses = IntPtr.Zero;
}
Marshal.WriteInt32(addressCount, addresses.Length);
lastAddressesLength = addresses.Length;
lastAddresses = InstanceHelper.AllocStringArray(addresses);
return lastAddresses;
}
return IntPtr.Zero;
}
protected override void DisposeInternal()
{
if (lastAddresses != IntPtr.Zero)
{
InstanceHelper.FreeStringArray(lastAddresses, lastAddressesLength);
lastAddressesLength = 0;
lastAddresses = IntPtr.Zero;
}
base.DisposeInternal();
}
}
}

View File

@@ -0,0 +1,86 @@
/*
* MIT License
*
* Copyright (c) 2025 Open Media Transport Contributors
*
* 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.
*
*/
using System.Runtime.InteropServices;
using System.Text;
namespace libomt
{
internal class InstanceHelper
{
public static Object? FromIntPtr(IntPtr handle)
{
if (handle != IntPtr.Zero)
{
GCHandle gh = GCHandle.FromIntPtr(handle);
return gh.Target;
}
return null;
}
public static IntPtr ToIntPtr(Object? obj)
{
if (obj == null) return IntPtr.Zero;
return GCHandle.ToIntPtr(GCHandle.Alloc(obj));
}
public static int WriteString(string value, IntPtr dst, int maxLength)
{
byte[] b = UTF8Encoding.UTF8.GetBytes(value);
if (b != null)
{
int len = b.Length + 1;
if (dst == IntPtr.Zero) return len;
if (maxLength > len)
{
Marshal.Copy(b, 0, dst, b.Length);
Marshal.WriteByte(dst, b.Length, 0);
return len;
}
}
return 0;
}
public static IntPtr AllocStringArray(string[] values)
{
IntPtr m = Marshal.AllocCoTaskMem(values.Length * IntPtr.Size);
for (int i = 0; i < values.Length; i++)
{
Marshal.WriteIntPtr(m, i * IntPtr.Size, Marshal.StringToCoTaskMemUTF8(values[i]));
}
return m;
}
public static void FreeStringArray(IntPtr ptr, int length)
{
if (ptr != IntPtr.Zero)
{
for (int i = 0; i < length; i++)
{
Marshal.ZeroFreeCoTaskMemUTF8(Marshal.ReadIntPtr(ptr, i * IntPtr.Size));
}
Marshal.FreeCoTaskMem(ptr);
}
}
}
}

View File

@@ -0,0 +1,153 @@
/*
* MIT License
*
* Copyright (c) 2025 Open Media Transport Contributors
*
* 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.
*
*/
using libomtnet;
using System.Runtime.InteropServices;
namespace libomt
{
internal class ReceiveInstance : BaseInstance
{
private OMTReceive? receive;
private IntPtr lastVideo = IntPtr.Zero;
private IntPtr lastAudio = IntPtr.Zero;
public ReceiveInstance(string name, OMTFrameType frameTypes, OMTPreferredVideoFormat format, OMTReceiveFlags flags) {
receive = new OMTReceive(name, frameTypes, format, flags);
instance = receive;
}
public void SetFlags(int flags)
{
if (receive != null)
{
receive.SetFlags((OMTReceiveFlags)flags);
}
}
public void SetSuggestedQuality(int quality)
{
if (receive != null)
{
receive.SetSuggestedQuality((OMTQuality)quality);
}
}
public void SetTally(IntPtr pTally)
{
if (receive != null)
{
if (pTally != IntPtr.Zero)
{
int preview = Marshal.ReadInt32(pTally);
int program = Marshal.ReadInt32(pTally, 4);
OMTTally t = new OMTTally(preview, program);
receive.SetTally(t);
}
}
}
public int Send(OMTMediaFrame frame)
{
if (receive != null)
{
return receive.Send(frame);
}
return 0;
}
public void GetSenderInformation(IntPtr pInfo)
{
if (receive != null)
{
OMTSenderInfo info = receive.GetSenderInformation();
if (info != null)
{
if (pInfo != IntPtr.Zero)
{
OMTUtils.WriteStringToPtrUTF8(info.ProductName, pInfo, UnmanagedExports.MAX_STRING_LENGTH);
OMTUtils.WriteStringToPtrUTF8(info.Manufacturer, pInfo + UnmanagedExports.MAX_STRING_LENGTH, UnmanagedExports.MAX_STRING_LENGTH);
OMTUtils.WriteStringToPtrUTF8(info.Version, pInfo + UnmanagedExports.MAX_STRING_LENGTH + UnmanagedExports.MAX_STRING_LENGTH, UnmanagedExports.MAX_STRING_LENGTH);
}
}
}
}
public IntPtr Receive(OMTFrameType frameTypes, int millisecondsTimeout)
{
if (receive != null)
{
OMTMediaFrame mediaFrame = new OMTMediaFrame();
if (receive.Receive(frameTypes, millisecondsTimeout, ref mediaFrame))
{
if (mediaFrame.Type == OMTFrameType.Video)
{
if (lastVideo != IntPtr.Zero)
{
OMTMediaFrame.FreeIntPtr(lastVideo);
lastVideo = IntPtr.Zero;
}
lastVideo = OMTMediaFrame.ToIntPtr(mediaFrame);
return lastVideo;
} else if (mediaFrame.Type == OMTFrameType.Audio)
{
if (lastAudio != IntPtr.Zero)
{
OMTMediaFrame.FreeIntPtr(lastAudio);
lastAudio = IntPtr.Zero;
}
lastAudio = OMTMediaFrame.ToIntPtr(mediaFrame);
return lastAudio;
} else if (mediaFrame.Type == OMTFrameType.Metadata)
{
if (lastMetadata != IntPtr.Zero)
{
OMTMediaFrame.FreeIntPtr(lastMetadata);
lastMetadata = IntPtr.Zero;
}
lastMetadata = OMTMediaFrame.ToIntPtr(mediaFrame);
return lastMetadata;
}
}
}
return IntPtr.Zero;
}
protected override void DisposeInternal()
{
if (lastVideo != IntPtr.Zero)
{
OMTMediaFrame.FreeIntPtr(lastVideo);
lastVideo = IntPtr.Zero;
}
if (lastAudio != IntPtr.Zero) {
OMTMediaFrame.FreeIntPtr(lastAudio);
lastAudio = IntPtr.Zero;
}
receive = null;
base.DisposeInternal();
}
}
}

View File

@@ -0,0 +1,143 @@
/*
* MIT License
*
* Copyright (c) 2025 Open Media Transport Contributors
*
* 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.
*
*/
using libomtnet;
using System.Net.NetworkInformation;
namespace libomt
{
internal class SendInstance : BaseInstance
{
private OMTSend? send;
public SendInstance( string name, int quality)
{
send = new OMTSend(name, (OMTQuality)quality);
instance = send;
}
public int Send(OMTMediaFrame frame)
{
if (send != null)
{
return send.Send(frame);
}
return 0;
}
public int GetAddress(IntPtr value, int maxLength)
{
if (send != null)
{
return InstanceHelper.WriteString(send.Address, value, maxLength);
}
return 0;
}
public void SetRedirect(IntPtr newAddress)
{
if (send != null)
{
if (newAddress != IntPtr.Zero)
{
send.SetRedirect(OMTUtils.PtrToStringUTF8(newAddress));
}
}
}
public IntPtr Receive(int millisecondsTimeout)
{
if (send != null)
{
OMTMediaFrame mediaFrame = new OMTMediaFrame();
if (send.Receive(millisecondsTimeout, ref mediaFrame))
{
if (mediaFrame.Type == OMTFrameType.Metadata)
{
if (lastMetadata != IntPtr.Zero)
{
OMTMediaFrame.FreeIntPtr(lastMetadata);
lastMetadata = IntPtr.Zero;
}
lastMetadata = OMTMediaFrame.ToIntPtr(mediaFrame);
return lastMetadata;
}
}
}
return IntPtr.Zero;
}
public int Connections { get
{
if (send != null)
{
return send.Connections;
}
else {
return 0;
}
}
}
public void AddConnectionMetadata(IntPtr pMetadata)
{
if (send != null)
{
if (pMetadata != IntPtr.Zero)
{
string metadata = OMTUtils.PtrToStringUTF8(pMetadata);
send.AddConnectionMetadata(metadata);
}
}
}
public void ClearConnectionMetadata()
{
if (send != null)
{
send.ClearConnectionMetadata();
}
}
public void SetSenderInformation(IntPtr pInfo)
{
if (send != null)
{
if (pInfo != IntPtr.Zero)
{
OMTSenderInfo info = new OMTSenderInfo();
info.ProductName = OMTUtils.PtrToStringUTF8(pInfo, UnmanagedExports.MAX_STRING_LENGTH);
info.Manufacturer = OMTUtils.PtrToStringUTF8(pInfo + UnmanagedExports.MAX_STRING_LENGTH, UnmanagedExports.MAX_STRING_LENGTH);
info.Version = OMTUtils.PtrToStringUTF8(pInfo + UnmanagedExports.MAX_STRING_LENGTH + UnmanagedExports.MAX_STRING_LENGTH, UnmanagedExports.MAX_STRING_LENGTH);
send.SetSenderInformation(info);
}
}
}
protected override void DisposeInternal()
{
send = null;
base.DisposeInternal();
}
}
}

636
3rd/libomt/src/libomt.cs Normal file
View File

@@ -0,0 +1,636 @@
/*
* MIT License
*
* Copyright (c) 2025 Open Media Transport Contributors
*
* 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.
*
*/
using System.Runtime.InteropServices;
using System.Text;
using libomtnet;
namespace libomt
{
public class UnmanagedExports
{
private static object lockSync = new object();
private static DiscoveryInstance? discoveryInstance = null;
internal const int MAX_STRING_LENGTH = 1024;
static UnmanagedExports()
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
OMTLogging.Write(e.ExceptionObject.ToString(), "UnhandledException");
}
[UnmanagedCallersOnly(EntryPoint = "omt_settings_set_string")]
public static void OMTSettingsSetString(IntPtr name, IntPtr value)
{
try
{
if (name != IntPtr.Zero && value != IntPtr.Zero)
{
string? szName = Marshal.PtrToStringUTF8(name);
string? szValue = Marshal.PtrToStringUTF8(value);
if (szName != null && szValue != null)
{
OMTSettings.GetInstance().SetString(szName, szValue);
}
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_settings_set_string");
}
}
[UnmanagedCallersOnly(EntryPoint = "omt_settings_get_string")]
public static int OMTSettingsGetString(IntPtr name, IntPtr value, int maxLength)
{
try
{
if (name != IntPtr.Zero)
{
string? szName = Marshal.PtrToStringUTF8(name);
if (szName != null)
{
string szValue = OMTSettings.GetInstance().GetString(szName, null);
if (szValue != null)
{
return InstanceHelper.WriteString(szValue, value, maxLength);
}
}
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_settings_get_string");
}
return 0;
}
[UnmanagedCallersOnly(EntryPoint = "omt_settings_set_integer")]
public static void OMTSettingsSetInteger(IntPtr name, int value)
{
try
{
if (name != IntPtr.Zero)
{
string? szName = Marshal.PtrToStringUTF8(name);
if (szName != null)
{
OMTSettings.GetInstance().SetInteger(szName, value);
}
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_settings_set_integer");
}
}
[UnmanagedCallersOnly(EntryPoint = "omt_settings_get_integer")]
public static int OMTSettingsGetInteger(IntPtr name)
{
try
{
if (name != IntPtr.Zero)
{
string? szName = Marshal.PtrToStringUTF8(name);
if (szName != null)
{
return OMTSettings.GetInstance().GetInteger(szName, 0);
}
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_settings_get_integer");
}
return 0;
}
[UnmanagedCallersOnly(EntryPoint = "omt_send_create")]
public static IntPtr OMTSendCreate(IntPtr name, int profile)
{
try
{
if (name != IntPtr.Zero)
{
string? szName = Marshal.PtrToStringUTF8(name);
if (szName != null)
{
return InstanceHelper.ToIntPtr(new SendInstance(szName, profile));
}
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_send_create");
}
return IntPtr.Zero;
}
[UnmanagedCallersOnly(EntryPoint = "omt_receive_create")]
public static IntPtr OMTReceiveCreate(IntPtr name, OMTFrameType frameTypes, OMTPreferredVideoFormat format, OMTReceiveFlags receiveFlags)
{
try
{
if (name != IntPtr.Zero)
{
string? szName = Marshal.PtrToStringUTF8(name);
if (szName != null)
{
return InstanceHelper.ToIntPtr(new ReceiveInstance(szName, frameTypes, format, receiveFlags));
}
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_receive_create");
}
return IntPtr.Zero;
}
[UnmanagedCallersOnly(EntryPoint = "omt_send_destroy")]
public static void OMTSendDestroy(IntPtr instance)
{
try
{
if (instance != IntPtr.Zero)
{
SendInstance? sendInstance = (SendInstance?)InstanceHelper.FromIntPtr(instance);
if (sendInstance != null)
{
sendInstance.Dispose();
}
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_send_destroy");
}
}
[UnmanagedCallersOnly(EntryPoint = "omt_send_getaddress")]
public static int OMTSendGetAddress(IntPtr instance, IntPtr address, int maxLength)
{
try
{
if (instance != IntPtr.Zero)
{
SendInstance? sendInstance = (SendInstance?)InstanceHelper.FromIntPtr(instance);
if (sendInstance != null)
{
return sendInstance.GetAddress(address, maxLength);
}
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_send_getaddress");
}
return 0;
}
[UnmanagedCallersOnly(EntryPoint = "omt_receive_destroy")]
public static void OMTReceiveDestroy(IntPtr instance)
{
try
{
if (instance != IntPtr.Zero)
{
ReceiveInstance? receiveInstance = (ReceiveInstance?)InstanceHelper.FromIntPtr(instance);
if (receiveInstance != null)
{
receiveInstance.Dispose();
}
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_receive_destroy");
}
}
[UnmanagedCallersOnly(EntryPoint = "omt_send")]
public static int OMTSend(IntPtr instance, IntPtr frame)
{
try
{
SendInstance? sendInstance = (SendInstance?)InstanceHelper.FromIntPtr(instance);
if (sendInstance != null)
{
if (frame != IntPtr.Zero)
{
OMTMediaFrame v = OMTMediaFrame.FromIntPtr(frame);
return sendInstance.Send(v);
}
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_send");
}
return 0;
}
[UnmanagedCallersOnly(EntryPoint = "omt_send_connections")]
public static int OMTSendConnections(IntPtr instance)
{
try
{
SendInstance? sendInstance = (SendInstance?)InstanceHelper.FromIntPtr(instance);
if (sendInstance != null)
{
return sendInstance.Connections;
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_send_connections");
}
return 0;
}
[UnmanagedCallersOnly(EntryPoint = "omt_receive_send")]
public static int OMTReceiveSend(IntPtr instance, IntPtr frame)
{
try
{
ReceiveInstance? receiveInstance = (ReceiveInstance?)InstanceHelper.FromIntPtr(instance);
if (receiveInstance != null)
{
if (frame != IntPtr.Zero)
{
OMTMediaFrame v = OMTMediaFrame.FromIntPtr(frame);
return receiveInstance.Send(v);
}
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_receive_sendmetadata");
}
return 0;
}
[UnmanagedCallersOnly(EntryPoint = "omt_send_receive")]
public static IntPtr OMTSendReceive(IntPtr instance, int millisecondsTimeout)
{
try
{
SendInstance? sendInstance = (SendInstance?)InstanceHelper.FromIntPtr(instance);
if (sendInstance != null)
{
return sendInstance.Receive(millisecondsTimeout);
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_send_receive");
}
return IntPtr.Zero;
}
[UnmanagedCallersOnly(EntryPoint = "omt_receive")]
public static IntPtr OMTReceive(IntPtr instance, int frameTypes, int millisecondsTimeout)
{
try
{
ReceiveInstance? receiveInstance = (ReceiveInstance?)InstanceHelper.FromIntPtr(instance);
if (receiveInstance != null)
{
return receiveInstance.Receive((OMTFrameType)frameTypes, millisecondsTimeout);
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_receive");
}
return IntPtr.Zero;
}
[UnmanagedCallersOnly(EntryPoint = "omt_receive_settally")]
public static void OMTReceiveSetTally(IntPtr instance, IntPtr tally)
{
try
{
ReceiveInstance? receiveInstance = (ReceiveInstance?)InstanceHelper.FromIntPtr(instance);
if (receiveInstance != null)
{
receiveInstance.SetTally(tally);
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_receive_settally");
}
}
[UnmanagedCallersOnly(EntryPoint = "omt_receive_setsuggestedquality")]
public static void OMTReceiveSetSuggestedQuality(IntPtr instance, int quality)
{
try
{
ReceiveInstance? receiveInstance = (ReceiveInstance?)InstanceHelper.FromIntPtr(instance);
if (receiveInstance != null)
{
receiveInstance.SetSuggestedQuality(quality);
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_receive_setsuggestedquality");
}
}
[UnmanagedCallersOnly(EntryPoint = "omt_receive_setflags")]
public static void OMTReceiveSetFlags(IntPtr instance, int flags)
{
try
{
ReceiveInstance? receiveInstance = (ReceiveInstance?)InstanceHelper.FromIntPtr(instance);
if (receiveInstance != null)
{
receiveInstance.SetFlags(flags);
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_receive_setflags");
}
}
[UnmanagedCallersOnly(EntryPoint = "omt_send_getvideostatistics")]
public static void OMTSendGetVideoStatistics(IntPtr instance, IntPtr statistics)
{
try
{
SendInstance? sendInstance = (SendInstance?)InstanceHelper.FromIntPtr(instance);
if (sendInstance != null)
{
sendInstance.GetVideoStatistics(statistics);
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_send_getvideostatistics");
}
}
[UnmanagedCallersOnly(EntryPoint = "omt_send_getaudiostatistics")]
public static void OMTSendGetAudioStatistics(IntPtr instance, IntPtr statistics)
{
try
{
SendInstance? sendInstance = (SendInstance?)InstanceHelper.FromIntPtr(instance);
if (sendInstance != null)
{
sendInstance.GetAudioStatistics(statistics);
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_send_getaudiostatistics");
}
}
[UnmanagedCallersOnly(EntryPoint = "omt_receive_getvideostatistics")]
public static void OMTReceiveGetVideoStatistics(IntPtr instance, IntPtr statistics)
{
try
{
ReceiveInstance? receiveInstance = (ReceiveInstance?)InstanceHelper.FromIntPtr(instance);
if (receiveInstance != null)
{
receiveInstance.GetVideoStatistics(statistics);
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_receive_getvideostatistics");
}
}
[UnmanagedCallersOnly(EntryPoint = "omt_receive_getaudiostatistics")]
public static void OMTReceiveGetAudioStatistics(IntPtr instance, IntPtr statistics)
{
try
{
ReceiveInstance? receiveInstance = (ReceiveInstance?)InstanceHelper.FromIntPtr(instance);
if (receiveInstance != null)
{
receiveInstance.GetAudioStatistics(statistics);
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_receive_getaudiostatistics");
}
}
[UnmanagedCallersOnly(EntryPoint = "omt_send_setredirect")]
public static void OMTSendSetRedirect(IntPtr instance, IntPtr newAddress)
{
try
{
SendInstance? sendInstance = (SendInstance?)InstanceHelper.FromIntPtr(instance);
if (sendInstance != null)
{
sendInstance.SetRedirect(newAddress);
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_send_setredirect");
}
}
[UnmanagedCallersOnly(EntryPoint = "omt_send_setsenderinformation")]
public static void OMTSendSetSenderInformation(IntPtr instance, IntPtr info)
{
try
{
SendInstance? sendInstance = (SendInstance?)InstanceHelper.FromIntPtr(instance);
if (sendInstance != null)
{
sendInstance.SetSenderInformation(info);
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_send_setsenderinformation");
}
}
[UnmanagedCallersOnly(EntryPoint = "omt_send_addconnectionmetadata")]
public static void OMTSendAddConnectionMetadata(IntPtr instance, IntPtr metadata)
{
try
{
SendInstance? sendInstance = (SendInstance?)InstanceHelper.FromIntPtr(instance);
if (sendInstance != null)
{
sendInstance.AddConnectionMetadata(metadata);
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_send_addconnectionmetadata");
}
}
[UnmanagedCallersOnly(EntryPoint = "omt_send_clearconnectionmetadata")]
public static void OMTSendClearConnectionMetadata(IntPtr instance)
{
try
{
SendInstance? sendInstance = (SendInstance?)InstanceHelper.FromIntPtr(instance);
if (sendInstance != null)
{
sendInstance.ClearConnectionMetadata();
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_send_clearconnectionmetadata");
}
}
[UnmanagedCallersOnly(EntryPoint = "omt_receive_getsenderinformation")]
public static void OMTReceiveGetSenderInformation(IntPtr instance, IntPtr info)
{
try
{
ReceiveInstance? receiveInstance = (ReceiveInstance?)InstanceHelper.FromIntPtr(instance);
if (receiveInstance != null)
{
receiveInstance.GetSenderInformation(info);
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_receive_getsenderinformation");
}
}
[UnmanagedCallersOnly(EntryPoint = "omt_receive_gettally")]
public static bool OMTReceiveGetTally(IntPtr instance, int millisecondsTimeout, IntPtr tally)
{
try
{
if (tally != IntPtr.Zero)
{
ReceiveInstance? receiveInstance = (ReceiveInstance?)InstanceHelper.FromIntPtr(instance);
if (receiveInstance != null)
{
return receiveInstance.GetTally(millisecondsTimeout, tally);
}
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_receive_gettally");
}
return false;
}
[UnmanagedCallersOnly(EntryPoint = "omt_send_gettally")]
public static bool OMTSendGetTally(IntPtr instance, int millisecondsTimeout, IntPtr tally)
{
try
{
SendInstance? sendInstance = (SendInstance?)InstanceHelper.FromIntPtr(instance);
if (sendInstance != null)
{
return sendInstance.GetTally(millisecondsTimeout, tally);
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_send_gettally");
}
return false;
}
[UnmanagedCallersOnly(EntryPoint = "omt_setloggingfilename")]
public static void OMTSetLoggingFilename(IntPtr filename)
{
if (filename != IntPtr.Zero)
{
string? fn = Marshal.PtrToStringUTF8(filename);
if (fn != null)
{
OMTLogging.SetFilename(fn);
}
}
}
[UnmanagedCallersOnly(EntryPoint = "omt_discovery_getaddresses")]
private static IntPtr OMTDiscoveryGetAddresses(IntPtr addressCount)
{
try
{
DiscoveryInstance? instance = CreateDiscovery();
if (instance != null)
{
return instance.GetAddresses(addressCount);
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_discovery_getaddresses");
}
return IntPtr.Zero;
}
private static DiscoveryInstance? CreateDiscovery()
{
try
{
lock (lockSync)
{
if (discoveryInstance == null)
{
discoveryInstance = new DiscoveryInstance();
}
return discoveryInstance;
}
}
catch (Exception ex)
{
OMTLogging.Write(ex.ToString(), "omt_creatediscovery");
}
return null;
}
}
}