How to get the SDK

  1. Contact support@siraview.com and request an account for access to our Nuget server.

  2. Add our NuGet server as a source to your nuget:

Stable Feed:

nuget.exe sources add -Name SiraStable -Source http://proget.siraview.com:81/nuget/InternalStable/ -UserName <username> -Password <password>

Nightly builds:

nuget.exe sources add -Name SiraDev -Source http://proget.siraview.com:81/nuget/InternalDev/ -UserName <username> -Password <password>

 

Which packages do I need?

For C++ development: SiraStreamsSDK-build, SiraStreamsSDK-run and DecoderSDK-full packages.

For C# development: SiraStreamsSDK-interop and SiraStreamsSDK-run.

What’s in the packages?

We’re using Nuget packages as a delivery and version control mechanism; they’re not fully-fledged "native" packages though. In particular they don’t contain the scripts or MSBuild props/targets to handle include paths, libary linking and binary content copying. Future packages may add this support.

The packages are all just "content" packages, which add folders to your Project Directory with Sira headers, libs and binaries in various subfolders.

SiraStreamsSDK-build: Contains the headers and libs you need to build against the SDK. Brings in DecoderBaseClasses-build as a dependency.

SiraStreamsSDK-run: Contains the binaries you need to run the SDK.

The -build and -run packages are separated to allow greater flexibility in use and deployment. For example you may want to use a pre-installed version of the SDK that’s already on the machine, so you can avoid downloading the -run package (which is ~100MB in size). Or you may be building a C# application

SiraStreamsSDK-interop: A proper C# assembly that implements a class model on top of the native Streams API.

Worked example: Step 1 Getting started

Now you have the headers and libs, you can write some code:

#include "Sira\SiraStreamsSDK\include\SiraViewDecoders\DllInterface\SiraViewDecoders.h"
#include "Sira\DecoderSDK\DecoderBaseClasses\SvStruct.h"

#include "Sira\DecoderSDK\DecoderBaseClasses\Support\StringConversion.h" (1)

using namespace Sira;

int main()
{
	auto initParams = InitSvInitParams(
		"<your developer key goes here>",	(2)
		"<your company name>",
		"<your product name>",
		"",
		"",
		GuidFromString("{79F1B30A-ECD9-433E-A1A4-2B0D0E95D215}"),  (3)
		TRUE,	// use plugins
		FALSE,	// Use external process for SDK - experimental
		0,
		NULL);

	SDKHandle sdkHandle;
	Result r = StreamsSDK_Init(initParams, sdkHandle);
	if (r != OK && r != InvalidLicence)		(4)
	{
		return -1;
	}

}
  1. Provides the GuidFromString helper function

  2. You need a developer key, see below.

  3. Generate your own GUID here, or use the one we give you.

  4. InvalidLicense is OK: it means the developer key checked out but there’s no runtime license. Everything will work, but you’ll get watermarks on images.

License Controls

The SDK uses two levels of licensing controls:

  1. A developer key

  2. A runtime license file

As the names suggest, you’ll need a developer key in order to build your software, and a runtime license file when you want to distribute your software (including our sdk) to your users.

 

Developer Keys

Without a valid developer key, the SDK doesn’t function. You’ll get an error code from the StreamsSDK_Init function, and all other SDK functions will fail.

We will generate this for you upon request, but we might require you to sign an NDA or enter some other form of formal agreement with us.

 

Runtime License Files

When you’re ready to ship your software you can purchase runtime licenses from us. Runtime licenses are usually hardware-locked. You’ll need to send us a hardware node code for the machine you intend to ultimately run on, and we will send back a license file to be installed on that machine.

To obtain a node code run

cctv.exe nodecode

Configuring Include paths

Unfortunately there’s an inter-dependency between the packages' use of header files. The XXX header file has an inclue line like

#include "DecoderSDK\DecoderBaseClasses\SvStruct.h"

In order for this to be resolved, you’ll need to add the following path to your project’s include directories:

$(ProjectDir)Sira

Copying binaries

The SDK runtime binaries must be available to be loaded when you launch your exe. The SDK does provide a mechanism to let you explicitly specify the binaries location, but for now just add a post-build event like:

xcopy /E /Y $(ProjectDir)Sira\SiraStreamsSDK\bin\*.* $(OutDir)

Worked Example: Step 2 Autodetect

Once the SDK is initialised you can use it to load a video file. There are different ways of doing this but the first to start with is autodetect. By default autodetect will try every decoder in the system until it finds one that works.

First, create a decoder collection object:

	DecoderCollectionHandle decoderCollectionHandle;
	r = StreamsSDK_CreateDecoderCollection(sdkHandle, "", "", decoderCollectionHandle);

The default decoder collection includes all the built-in decoders and any plugins that were detected at the time the decoder collection object is created.

Next, filter and sort the collection according the name of the file you’re going to attempt to load:

	DecoderCollectionHandle autoDC;
	r = DecoderCollection_GetAutodetectCollection(hDC, "abc.oba", 0, autoDC);

Now actually run the autodetect algorithm using your filtered collection:

	r = DecoderCollection_Autodetect(autoDC, strlen(path), path, DecoderAttempt_Handler, LoadProgress_Handler, LoadMessage_Handler,
		AbortOperation_Handler, decoderHandle, decoderInfo, queryResult, reservedResourcesCount);
	if (r != OK)
	{
		return -1;
	}

 

 

The whole file should look like this:

#include "stdafx.h"
#include "Sira\SiraStreamsSDK\include\SiraViewDecoders\DllInterface\SiraViewDecoders.h"
#include "Sira\DecoderSDK\DecoderBaseClasses\SvStruct.h"
#include "Sira\DecoderSDK\DecoderBaseClasses\Support\StringConversion.h"

using namespace Sira;

void __stdcall loggingCallback(const char * file, const int line, int level, char * s)
{
	//if (level <= LogLevel::VERBOSE_DEBUG)
	{
		SYSTEMTIME systemTime;
		GetSystemTime(&systemTime);

		int incomingLength = strlen(s);
		int bufferLength = incomingLength + /*25*/ 50;	// 50 instead of 25 is massive overkill to permit int-level to be printed
		char * tmpBuf = new char[bufferLength];
		sprintf_s(tmpBuf, bufferLength, "%04d\\%02d\\%02d %02d:%02d:%02d.%03d pid:%d level:%d %s",
			systemTime.wYear, systemTime.wMonth, systemTime.wDay,
			systemTime.wHour, systemTime.wMinute, systemTime.wSecond,
			systemTime.wMilliseconds, GetCurrentProcessId(), level, s);

		fprintf(stderr, tmpBuf);
		delete[]tmpBuf;
	}
}

void __stdcall DecoderAttempt_Handler(SvDecoderInfoEx decoderInfo, int index, int count)
{
	char m[4096];
	sprintf_s(m, "Attempting %d/%d: %s (%d.%d)\n", index, count, decoderInfo.decoderInfo.name.string, GetDecoderVersionMajor(decoderInfo.decoderInfo.version),
		GetDecoderVersionMinor(decoderInfo.decoderInfo.version));
	fprintf(stderr, m);
}

void __stdcall LoadProgress_Handler(double progress)
{

}

void __stdcall LoadMessage_Handler(char * message)
{
	fprintf(stderr, message);
}

BOOL __stdcall AbortOperation_Handler(void)
{
	return FALSE;
}


int main()
{
	auto sdkPath = "C:\\Code\\test\\ConsoleApplication1\\Debug\\sdk";
	SetCurrentDirectoryA(sdkPath);
	auto initParams = InitSvInitParams("9373C6141109E2AB44D32CBA7CA5E180",
		"Sira Defence & Security Ltd", "CCTV.exe",
		sdkPath,
		"",
		GuidFromString("{F95A2C58-9A81-4E0E-99E9-FD69790A31C1}"),
		TRUE,	// use plugins
		FALSE,	// Use external process for SDK - experimental
		0,
		&loggingCallback);

	SDKHandle hSDK;
	Result r = StreamsSDK_Init(initParams, hSDK);

	if (r != OK && r != InvalidLicence)
	{
		return -1;
	}

	DecoderCollectionHandle hDC;
	r = StreamsSDK_CreateDecoderCollection(hSDK, NULL, NULL, hDC);

	DecoderHandle decoderHandle;
	SvDecoderInfoEx decoderInfo;
	SvQueryResultInfo queryResult;
	int reservedResourcesCount;
	const char * path = "E:\\Video\\0004 PC Link\\A&I 127.oba";

	DecoderCollectionHandle autoDC;
	r = DecoderCollection_GetAutodetectCollection(hDC, "abc.oba", 0, autoDC);

	r = DecoderCollection_Autodetect(autoDC, strlen(path), path, DecoderAttempt_Handler, LoadProgress_Handler, LoadMessage_Handler,
		AbortOperation_Handler, decoderHandle, decoderInfo, queryResult, reservedResourcesCount);
	if (r != OK)
	{
		return -1;
	}
}

 

Worked Example: Step 3 Getting samples

Given a decoder instance that is in the "Loaded" state, for a file which has a single track containing a single stream:

SvGetSampleParams getSampleParams = SvGetSampleParams(AbortOperation_Handler);

int trackCount = 0;
auto result = Decoder_GetTrackCount(decoderHandle, &trackCount);

int trackHandle = 0;
result = Decoder_GetTrack(decoderHandle, 0, &trackHandle);

// Not strictly required if we don't care how many streams there are
SvTrackInfo trackInfo;
memset(&trackInfo, 0, sizeof(trackInfo));
result = Track_GetInfo(trackHandle, &trackInfo);

int streamHandle = 0;
result = Track_GetStream(trackHandle, 0, &streamHandle);

// No strictly required if we don't care what type of stream it is
SvStreamInfo streamInfo;
memset(&streamInfo, 0, sizeof(streamInfo));
result = Stream_GetInfo(streamHandle, &streamInfo);

int nameSize = 0;
result = Stream_GetName(streamHandle, &nameSize, 0);

char *name = new char[nameSize];
result = Stream_GetName(streamHandle, &nameSize, name);
//PRINT(4, "name: [%s] ", name);
delete[] name;

SvSample sample;
result = Stream_GetNextSample(streamHandle, &getSampleParams, &sample);
//PRINT("sample", sample);
result = Stream_ReleaseSample(streamHandle, &sample);