/* -LICENSE-START-
** Copyright (c) 2018 Blackmagic Design
**
** Permission is hereby granted, free of charge, to any person or organization
** obtaining a copy of the software and accompanying documentation covered by
** this license (the "Software") to use, reproduce, display, distribute,
** execute, and transmit the Software, and to prepare derivative works of the
** Software, and to permit third-parties to whom the Software is furnished to
** do so, all subject to the following:
** 
** The copyright notices in the Software and this entire statement, including
** the above license grant, this restriction and the following disclaimer,
** must be included in all copies of the Software, in whole or in part, and
** all derivative works of the Software, unless such copies or derivative
** works are solely in the form of machine-executable object code generated by
** a source language processor.
** 
** 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
** DEALINGS IN THE SOFTWARE.
** -LICENSE-END-
*/


#ifndef BMD_CONST
    #if defined(_MSC_VER)
        #define BMD_CONST __declspec(selectany) static const
    #else
        #define BMD_CONST static const
    #endif
#endif

// Type Declarations


// Enumeration Mapping

cpp_quote("#if 0")
cpp_quote("#endif")

/* Enum BMDStreamingDeviceMode - Device modes */

typedef [v1_enum] enum	_BMDStreamingDeviceMode {
    bmdStreamingDeviceIdle                                       = /* 'idle' */ 0x69646C65,
    bmdStreamingDeviceEncoding                                   = /* 'enco' */ 0x656E636F,
    bmdStreamingDeviceStopping                                   = /* 'stop' */ 0x73746F70,
    bmdStreamingDeviceUnknown                                    = /* 'munk' */ 0x6D756E6B
} BMDStreamingDeviceMode;

/* Enum BMDStreamingEncodingFrameRate - Encoded frame rates */

typedef [v1_enum] enum	_BMDStreamingEncodingFrameRate {

    /* Interlaced rates */

    bmdStreamingEncodedFrameRate50i                              = /* 'e50i' */ 0x65353069,
    bmdStreamingEncodedFrameRate5994i                            = /* 'e59i' */ 0x65353969,
    bmdStreamingEncodedFrameRate60i                              = /* 'e60i' */ 0x65363069,

    /* Progressive rates */

    bmdStreamingEncodedFrameRate2398p                            = /* 'e23p' */ 0x65323370,
    bmdStreamingEncodedFrameRate24p                              = /* 'e24p' */ 0x65323470,
    bmdStreamingEncodedFrameRate25p                              = /* 'e25p' */ 0x65323570,
    bmdStreamingEncodedFrameRate2997p                            = /* 'e29p' */ 0x65323970,
    bmdStreamingEncodedFrameRate30p                              = /* 'e30p' */ 0x65333070,
    bmdStreamingEncodedFrameRate50p                              = /* 'e50p' */ 0x65353070,
    bmdStreamingEncodedFrameRate5994p                            = /* 'e59p' */ 0x65353970,
    bmdStreamingEncodedFrameRate60p                              = /* 'e60p' */ 0x65363070
} BMDStreamingEncodingFrameRate;

/* Enum BMDStreamingEncodingSupport - Output encoding mode supported flag */

typedef [v1_enum] enum	_BMDStreamingEncodingSupport {
    bmdStreamingEncodingModeNotSupported                         = 0,
    bmdStreamingEncodingModeSupported,                          
    bmdStreamingEncodingModeSupportedWithChanges                
} BMDStreamingEncodingSupport;

/* Enum BMDStreamingVideoCodec - Video codecs */

typedef [v1_enum] enum	_BMDStreamingVideoCodec {
    bmdStreamingVideoCodecH264                                   = /* 'H264' */ 0x48323634
} BMDStreamingVideoCodec;

/* Enum BMDStreamingH264Profile - H264 encoding profile */

typedef [v1_enum] enum	_BMDStreamingH264Profile {
    bmdStreamingH264ProfileHigh                                  = /* 'high' */ 0x68696768,
    bmdStreamingH264ProfileMain                                  = /* 'main' */ 0x6D61696E,
    bmdStreamingH264ProfileBaseline                              = /* 'base' */ 0x62617365
} BMDStreamingH264Profile;

/* Enum BMDStreamingH264Level - H264 encoding level */

typedef [v1_enum] enum	_BMDStreamingH264Level {
    bmdStreamingH264Level12                                      = /* 'lv12' */ 0x6C763132,
    bmdStreamingH264Level13                                      = /* 'lv13' */ 0x6C763133,
    bmdStreamingH264Level2                                       = /* 'lv2 ' */ 0x6C763220,
    bmdStreamingH264Level21                                      = /* 'lv21' */ 0x6C763231,
    bmdStreamingH264Level22                                      = /* 'lv22' */ 0x6C763232,
    bmdStreamingH264Level3                                       = /* 'lv3 ' */ 0x6C763320,
    bmdStreamingH264Level31                                      = /* 'lv31' */ 0x6C763331,
    bmdStreamingH264Level32                                      = /* 'lv32' */ 0x6C763332,
    bmdStreamingH264Level4                                       = /* 'lv4 ' */ 0x6C763420,
    bmdStreamingH264Level41                                      = /* 'lv41' */ 0x6C763431,
    bmdStreamingH264Level42                                      = /* 'lv42' */ 0x6C763432
} BMDStreamingH264Level;

/* Enum BMDStreamingH264EntropyCoding - H264 entropy coding */

typedef [v1_enum] enum	_BMDStreamingH264EntropyCoding {
    bmdStreamingH264EntropyCodingCAVLC                           = /* 'EVLC' */ 0x45564C43,
    bmdStreamingH264EntropyCodingCABAC                           = /* 'EBAC' */ 0x45424143
} BMDStreamingH264EntropyCoding;

/* Enum BMDStreamingAudioCodec - Audio codecs */

typedef [v1_enum] enum	_BMDStreamingAudioCodec {
    bmdStreamingAudioCodecAAC                                    = /* 'AAC ' */ 0x41414320
} BMDStreamingAudioCodec;

/* Enum BMDStreamingEncodingModePropertyID - Encoding mode properties */

typedef [v1_enum] enum	_BMDStreamingEncodingModePropertyID {

    /* Integers, Video Properties */

    bmdStreamingEncodingPropertyVideoFrameRate                   = /* 'vfrt' */ 0x76667274,	// Uses values of type BMDStreamingEncodingFrameRate
    bmdStreamingEncodingPropertyVideoBitRateKbps                 = /* 'vbrt' */ 0x76627274,

    /* Integers, H264 Properties */

    bmdStreamingEncodingPropertyH264Profile                      = /* 'hprf' */ 0x68707266,
    bmdStreamingEncodingPropertyH264Level                        = /* 'hlvl' */ 0x686C766C,
    bmdStreamingEncodingPropertyH264EntropyCoding                = /* 'hent' */ 0x68656E74,

    /* Flags, H264 Properties */

    bmdStreamingEncodingPropertyH264HasBFrames                   = /* 'hBfr' */ 0x68426672,

    /* Integers, Audio Properties */

    bmdStreamingEncodingPropertyAudioCodec                       = /* 'acdc' */ 0x61636463,
    bmdStreamingEncodingPropertyAudioSampleRate                  = /* 'asrt' */ 0x61737274,
    bmdStreamingEncodingPropertyAudioChannelCount                = /* 'achc' */ 0x61636863,
    bmdStreamingEncodingPropertyAudioBitRateKbps                 = /* 'abrt' */ 0x61627274
} BMDStreamingEncodingModePropertyID;

// Forward Declarations

interface IBMDStreamingDeviceNotificationCallback;
interface IBMDStreamingH264InputCallback;
interface IBMDStreamingDiscovery;
interface IBMDStreamingVideoEncodingMode;
interface IBMDStreamingMutableVideoEncodingMode;
interface IBMDStreamingVideoEncodingModePresetIterator;
interface IBMDStreamingDeviceInput;
interface IBMDStreamingH264NALPacket;
interface IBMDStreamingAudioPacket;
interface IBMDStreamingMPEG2TSPacket;
interface IBMDStreamingH264NALParser;

/* Interface IBMDStreamingDeviceNotificationCallback - Device notification callbacks. */

[
    object,
    uuid(F9531D64-3305-4B29-A387-7F74BB0D0E84),
    helpstring("Device notification callbacks.")
] interface IBMDStreamingDeviceNotificationCallback : IUnknown
{
    HRESULT StreamingDeviceArrived([in] IDeckLink* device);
    HRESULT StreamingDeviceRemoved([in] IDeckLink* device);
    HRESULT StreamingDeviceModeChanged([in] IDeckLink* device, [in] BMDStreamingDeviceMode mode);
};

/* Interface IBMDStreamingH264InputCallback - H264 input callbacks. */

[
    object,
    uuid(823C475F-55AE-46F9-890C-537CC5CEDCCA),
    helpstring("H264 input callbacks.")
] interface IBMDStreamingH264InputCallback : IUnknown
{
    HRESULT H264NALPacketArrived([in] IBMDStreamingH264NALPacket* nalPacket);
    HRESULT H264AudioPacketArrived([in] IBMDStreamingAudioPacket* audioPacket);
    HRESULT MPEG2TSPacketArrived([in] IBMDStreamingMPEG2TSPacket* tsPacket);
    HRESULT H264VideoInputConnectorScanningChanged(void);
    HRESULT H264VideoInputConnectorChanged(void);
    HRESULT H264VideoInputModeChanged(void);
};

/* Interface IBMDStreamingDiscovery - Installs device notifications */

[
    object,
    uuid(2C837444-F989-4D87-901A-47C8A36D096D),
    helpstring("Installs device notifications")
] interface IBMDStreamingDiscovery : IUnknown
{
    HRESULT InstallDeviceNotifications([in] IBMDStreamingDeviceNotificationCallback* theCallback);
    HRESULT UninstallDeviceNotifications(void);
};

/* Interface IBMDStreamingVideoEncodingMode - Represents an encoded video mode. */

[
    object,
    uuid(1AB8035B-CD13-458D-B6DF-5E8F7C2141D9),
    helpstring("Represents an encoded video mode.")
] interface IBMDStreamingVideoEncodingMode : IUnknown
{
    HRESULT GetName([out] BSTR *name);
    unsigned int GetPresetID(void);
    unsigned int GetSourcePositionX(void);
    unsigned int GetSourcePositionY(void);
    unsigned int GetSourceWidth(void);
    unsigned int GetSourceHeight(void);
    unsigned int GetDestWidth(void);
    unsigned int GetDestHeight(void);
    HRESULT GetFlag([in] BMDStreamingEncodingModePropertyID cfgID, [out] BOOL* value);
    HRESULT GetInt([in] BMDStreamingEncodingModePropertyID cfgID, [out] LONGLONG* value);
    HRESULT GetFloat([in] BMDStreamingEncodingModePropertyID cfgID, [out] double* value);
    HRESULT GetString([in] BMDStreamingEncodingModePropertyID cfgID, [out] BSTR *value);
    HRESULT CreateMutableVideoEncodingMode([out] IBMDStreamingMutableVideoEncodingMode** newEncodingMode); // Creates a mutable copy of the encoding mode
};

/* Interface IBMDStreamingMutableVideoEncodingMode - Represents a mutable encoded video mode. */

[
    object,
    uuid(19BF7D90-1E0A-400D-B2C6-FFC4E78AD49D),
    helpstring("Represents a mutable encoded video mode.")
] interface IBMDStreamingMutableVideoEncodingMode : IBMDStreamingVideoEncodingMode
{
    HRESULT SetSourceRect([in] unsigned int posX, [in] unsigned int posY, [in] unsigned int width, [in] unsigned int height);
    HRESULT SetDestSize([in] unsigned int width, [in] unsigned int height);
    HRESULT SetFlag([in] BMDStreamingEncodingModePropertyID cfgID, [in] BOOL value);
    HRESULT SetInt([in] BMDStreamingEncodingModePropertyID cfgID, [in] LONGLONG value);
    HRESULT SetFloat([in] BMDStreamingEncodingModePropertyID cfgID, [in] double value);
    HRESULT SetString([in] BMDStreamingEncodingModePropertyID cfgID, [in] BSTR value);
};

/* Interface IBMDStreamingVideoEncodingModePresetIterator - Enumerates encoding mode presets */

[
    object,
    uuid(7AC731A3-C950-4AD0-804A-8377AA51C6C4),
    helpstring("Enumerates encoding mode presets")
] interface IBMDStreamingVideoEncodingModePresetIterator : IUnknown
{
    HRESULT Next([out] IBMDStreamingVideoEncodingMode** videoEncodingMode);
};

/* Interface IBMDStreamingDeviceInput - Created by QueryInterface from IDeckLink */

[
    object,
    uuid(24B6B6EC-1727-44BB-9818-34FF086ACF98),
    helpstring("Created by QueryInterface from IDeckLink")
] interface IBMDStreamingDeviceInput : IUnknown
{

    /* Input modes */

    HRESULT DoesSupportVideoInputMode([in] BMDDisplayMode inputMode, [out] BOOL* result);
    HRESULT GetVideoInputModeIterator([out] IDeckLinkDisplayModeIterator** iterator);
    HRESULT SetVideoInputMode([in] BMDDisplayMode inputMode);
    HRESULT GetCurrentDetectedVideoInputMode([out] BMDDisplayMode* detectedMode);

    /* Capture modes */

    HRESULT GetVideoEncodingMode([out] IBMDStreamingVideoEncodingMode** encodingMode);
    HRESULT GetVideoEncodingModePresetIterator([in] BMDDisplayMode inputMode, [out] IBMDStreamingVideoEncodingModePresetIterator** iterator);
    HRESULT DoesSupportVideoEncodingMode([in] BMDDisplayMode inputMode, [in] IBMDStreamingVideoEncodingMode* encodingMode, [out] BMDStreamingEncodingSupport* result, [out] IBMDStreamingVideoEncodingMode** changedEncodingMode);
    HRESULT SetVideoEncodingMode([in] IBMDStreamingVideoEncodingMode* encodingMode);

    /* Input control */

    HRESULT StartCapture(void);
    HRESULT StopCapture(void);
    HRESULT SetCallback([in] IUnknown* theCallback);
};

/* Interface IBMDStreamingH264NALPacket - Represent an H.264 NAL packet */

[
    object,
    uuid(E260E955-14BE-4395-9775-9F02CC0A9D89),
    helpstring("Represent an H.264 NAL packet")
] interface IBMDStreamingH264NALPacket : IUnknown
{
    long GetPayloadSize(void);
    HRESULT GetBytes([out] void** buffer);
    HRESULT GetBytesWithSizePrefix([out] void** buffer); // Contains a 32-bit unsigned big endian size prefix
    HRESULT GetDisplayTime([in] ULONGLONG requestedTimeScale, [out] ULONGLONG* displayTime);
    HRESULT GetPacketIndex([out] unsigned int* packetIndex); // Deprecated
};

/* Interface IBMDStreamingAudioPacket - Represents a chunk of audio data */

[
    object,
    uuid(D9EB5902-1AD2-43F4-9E2C-3CFA50B5EE19),
    helpstring("Represents a chunk of audio data")
] interface IBMDStreamingAudioPacket : IUnknown
{
    BMDStreamingAudioCodec GetCodec(void);
    long GetPayloadSize(void);
    HRESULT GetBytes([out] void** buffer);
    HRESULT GetPlayTime([in] ULONGLONG requestedTimeScale, [out] ULONGLONG* playTime);
    HRESULT GetPacketIndex([out] unsigned int* packetIndex); // Deprecated
};

/* Interface IBMDStreamingMPEG2TSPacket - Represent an MPEG2 Transport Stream packet */

[
    object,
    uuid(91810D1C-4FB3-4AAA-AE56-FA301D3DFA4C),
    helpstring("Represent an MPEG2 Transport Stream packet")
] interface IBMDStreamingMPEG2TSPacket : IUnknown
{
    long GetPayloadSize(void);
    HRESULT GetBytes([out] void** buffer);
};

/* Interface IBMDStreamingH264NALParser - For basic NAL parsing */

[
    object,
    uuid(5867F18C-5BFA-4CCC-B2A7-9DFD140417D2),
    helpstring("For basic NAL parsing")
] interface IBMDStreamingH264NALParser : IUnknown
{
    HRESULT IsNALSequenceParameterSet([in] IBMDStreamingH264NALPacket* nal);
    HRESULT IsNALPictureParameterSet([in] IBMDStreamingH264NALPacket* nal);
    HRESULT GetProfileAndLevelFromSPS([in] IBMDStreamingH264NALPacket* nal, [out] unsigned int* profileIdc, [out] unsigned int* profileCompatability, [out] unsigned int* levelIdc);
};

/* Coclasses */

importlib("stdole2.tlb");

[
    uuid(23A4EDF5-A0E5-432C-94EF-3BABB5F81C82),
    helpstring("CBMDStreamingDiscovery Class")
] coclass CBMDStreamingDiscovery
{
    [default] interface IBMDStreamingDiscovery;
};

[
    uuid(7753EFBD-951C-407C-97A5-23C737B73B52),
    helpstring("CBMDStreamingH264NALParser Class")
] coclass CBMDStreamingH264NALParser
{
    [default] interface IBMDStreamingH264NALParser;
};