From 5f8335c1e49ce108ef3481863833c98efa00411b Mon Sep 17 00:00:00 2001 From: manuel Date: Thu, 2 Jul 2020 23:09:26 +0200 Subject: sync with upstream --- .../include/kodi/addon-instance/Inputstream.h | 843 +++++++++++++-------- 1 file changed, 520 insertions(+), 323 deletions(-) (limited to 'xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h') diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h index 252edbf..354806e 100644 --- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h @@ -14,25 +14,31 @@ */ #include "../AddonBase.h" -#include "../StreamCrypto.h" #include "../StreamCodec.h" +#include "../StreamCrypto.h" #ifdef BUILD_KODI_ADDON #include "../DemuxPacket.h" +#include "../InputStreamConstants.h" #else #include "cores/VideoPlayer/Interface/Addon/DemuxPacket.h" +#include "cores/VideoPlayer/Interface/Addon/InputStreamConstants.h" #endif -namespace kodi { namespace addon { class CInstanceInputStream; }} +//Increment this level always if you add features which can lead to compile failures in the addon +#define INPUTSTREAM_VERSION_LEVEL 2 -extern "C" { +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ /*! * @brief InputStream add-on capabilities. All capabilities are set to "false" as default. */ struct INPUTSTREAM_CAPABILITIES { - enum MASKTYPE: uint32_t + enum MASKTYPE : uint32_t { /// supports interface IDemux SUPPORTS_IDEMUX = (1 << 0), @@ -50,7 +56,10 @@ extern "C" { SUPPORTS_PAUSE = (1 << 4), /// supports interface ITime - SUPPORTS_ITIME = (1 << 5) + SUPPORTS_ITIME = (1 << 5), + + /// supports interface IChapter + SUPPORTS_ICHAPTER = (1 << 6), }; /// set of supported capabilities @@ -62,19 +71,18 @@ extern "C" { */ struct INPUTSTREAM { - static const unsigned int MAX_INFO_COUNT = 8; - - const char *m_strURL; + const char* m_strURL; + const char* m_mimeType; unsigned int m_nCountInfoValues; struct LISTITEMPROPERTY { - const char *m_strKey; - const char *m_strValue; - } m_ListItemProperties[MAX_INFO_COUNT]; + const char* m_strKey; + const char* m_strValue; + } m_ListItemProperties[STREAM_MAX_PROPERTY_COUNT]; - const char *m_libFolder; - const char *m_profileFolder; + const char* m_libFolder; + const char* m_profileFolder; }; /*! @@ -82,11 +90,37 @@ extern "C" { */ struct INPUTSTREAM_IDS { - static const unsigned int MAX_STREAM_COUNT = 32; + static const unsigned int MAX_STREAM_COUNT = 256; unsigned int m_streamCount; unsigned int m_streamIds[MAX_STREAM_COUNT]; }; + /*! + * @brief MASTERING Metadata + */ + struct INPUTSTREAM_MASTERING_METADATA + { + double primary_r_chromaticity_x; + double primary_r_chromaticity_y; + double primary_g_chromaticity_x; + double primary_g_chromaticity_y; + double primary_b_chromaticity_x; + double primary_b_chromaticity_y; + double white_point_chromaticity_x; + double white_point_chromaticity_y; + double luminance_max; + double luminance_min; + }; + + /*! + * @brief CONTENTLIGHT Metadata + */ + struct INPUTSTREAM_CONTENTLIGHT_METADATA + { + uint64_t max_cll; + uint64_t max_fall; + }; + /*! * @brief stream properties */ @@ -94,11 +128,12 @@ extern "C" { { enum STREAM_TYPE { - TYPE_NONE, + TYPE_NONE = 0, TYPE_VIDEO, TYPE_AUDIO, TYPE_SUBTITLE, - TYPE_TELETEXT + TYPE_TELETEXT, + TYPE_RDS, } m_streamType; enum Codec_FEATURES : uint32_t @@ -118,65 +153,130 @@ extern "C" { FLAG_KARAOKE = 0x0020, FLAG_FORCED = 0x0040, FLAG_HEARING_IMPAIRED = 0x0080, - FLAG_VISUAL_IMPAIRED = 0x0100 + FLAG_VISUAL_IMPAIRED = 0x0100, }; - enum INPUTSTREAM_COLORSPACE - { - COLORSPACE_UNKNOWN, - COLORSPACE_BT709, - COLORSPACE_BT470M, - COLORSPACE_BT470BG, - COLORSPACE_SMPTE170M, - COLORSPACE_SMPTE240M, - COLORSPACE_FILM, - COLORSPACE_BT2020, - COLORSPACE_SMPTE428, - COLORSPACE_SMPTEST428_1, - COLORSPACE_SMPTE431, - COLORSPACE_SMPTE432, - COLORSPACE_JEDEC_P22 + // Keep in sync with AVColorSpace + enum COLORSPACE + { + COLORSPACE_RGB = 0, + COLORSPACE_BT709 = 1, + COLORSPACE_UNSPECIFIED = 2, + COLORSPACE_UNKNOWN = COLORSPACE_UNSPECIFIED, // compatibility + COLORSPACE_RESERVED = 3, + COLORSPACE_FCC = 4, + COLORSPACE_BT470BG = 5, + COLORSPACE_SMPTE170M = 6, + COLORSPACE_SMPTE240M = 7, + COLORSPACE_YCGCO = 8, + COLORSPACE_YCOCG = COLORSPACE_YCGCO, + COLORSPACE_BT2020_NCL = 9, + COLORSPACE_BT2020_CL = 10, + COLORSPACE_SMPTE2085 = 11, + COLORSPACE_CHROMA_DERIVED_NCL = 12, + COLORSPACE_CHROMA_DERIVED_CL = 13, + COLORSPACE_ICTCP = 14, + COLORSPACE_MAX + }; + + // Keep in sync with AVColorPrimaries + enum COLORPRIMARIES : int32_t + { + COLORPRIMARY_RESERVED0 = 0, + COLORPRIMARY_BT709 = 1, + COLORPRIMARY_UNSPECIFIED = 2, + COLORPRIMARY_RESERVED = 3, + COLORPRIMARY_BT470M = 4, + COLORPRIMARY_BT470BG = 5, + COLORPRIMARY_SMPTE170M = 6, + COLORPRIMARY_SMPTE240M = 7, + COLORPRIMARY_FILM = 8, + COLORPRIMARY_BT2020 = 9, + COLORPRIMARY_SMPTE428 = 10, + COLORPRIMARY_SMPTEST428_1 = COLORPRIMARY_SMPTE428, + COLORPRIMARY_SMPTE431 = 11, + COLORPRIMARY_SMPTE432 = 12, + COLORPRIMARY_JEDEC_P22 = 22, + COLORPRIMARY_MAX }; - enum INPUTSTREAM_COLORRANGE + // Keep in sync with AVColorRange + enum COLORRANGE { - COLORRANGE_UNKNOWN, + COLORRANGE_UNKNOWN = 0, COLORRANGE_LIMITED, - COLORRANGE_FULLRANGE + COLORRANGE_FULLRANGE, + COLORRANGE_MAX + }; + + // keep in sync with AVColorTransferCharacteristic + enum COLORTRC : int32_t + { + COLORTRC_RESERVED0 = 0, + COLORTRC_BT709 = 1, + COLORTRC_UNSPECIFIED = 2, + COLORTRC_RESERVED = 3, + COLORTRC_GAMMA22 = 4, + COLORTRC_GAMMA28 = 5, + COLORTRC_SMPTE170M = 6, + COLORTRC_SMPTE240M = 7, + COLORTRC_LINEAR = 8, + COLORTRC_LOG = 9, + COLORTRC_LOG_SQRT = 10, + COLORTRC_IEC61966_2_4 = 11, + COLORTRC_BT1361_ECG = 12, + COLORTRC_IEC61966_2_1 = 13, + COLORTRC_BT2020_10 = 14, + COLORTRC_BT2020_12 = 15, + COLORTRC_SMPTE2084 = 16, + COLORTRC_SMPTEST2084 = COLORTRC_SMPTE2084, + COLORTRC_SMPTE428 = 17, + COLORTRC_SMPTEST428_1 = COLORTRC_SMPTE428, + COLORTRC_ARIB_STD_B67 = 18, + COLORTRC_MAX }; uint32_t m_flags; - char m_name[256]; /*!< @brief (optinal) name of the stream, \0 for default handling */ - char m_codecName[32]; /*!< @brief (required) name of codec according to ffmpeg */ - char m_codecInternalName[32]; /*!< @brief (optional) internal name of codec (selectionstream info) */ - STREAMCODEC_PROFILE m_codecProfile; /*!< @brief (optional) the profile of the codec */ - unsigned int m_pID; /*!< @brief (required) physical index */ + char m_name[256]; /*!< @brief (optinal) name of the stream, \0 for default handling */ + char m_codecName[32]; /*!< @brief (required) name of codec according to ffmpeg */ + char m_codecInternalName + [32]; /*!< @brief (optional) internal name of codec (selectionstream info) */ + STREAMCODEC_PROFILE m_codecProfile; /*!< @brief (optional) the profile of the codec */ + unsigned int m_pID; /*!< @brief (required) physical index */ - const uint8_t *m_ExtraData; + const uint8_t* m_ExtraData; unsigned int m_ExtraSize; - char m_language[64]; /*!< @brief RFC 5646 language code (empty string if undefined) */ + char m_language[64]; /*!< @brief RFC 5646 language code (empty string if undefined) */ - unsigned int m_FpsScale; /*!< @brief Scale of 1000 and a rate of 29970 will result in 29.97 fps */ + unsigned int + m_FpsScale; /*!< @brief Scale of 1000 and a rate of 29970 will result in 29.97 fps */ unsigned int m_FpsRate; - unsigned int m_Height; /*!< @brief height of the stream reported by the demuxer */ - unsigned int m_Width; /*!< @brief width of the stream reported by the demuxer */ - float m_Aspect; /*!< @brief display aspect of stream */ + unsigned int m_Height; /*!< @brief height of the stream reported by the demuxer */ + unsigned int m_Width; /*!< @brief width of the stream reported by the demuxer */ + float m_Aspect; /*!< @brief display aspect of stream */ - unsigned int m_Channels; /*!< @brief (required) amount of channels */ - unsigned int m_SampleRate; /*!< @brief (required) sample rate */ - unsigned int m_BitRate; /*!< @brief (required) bit rate */ - unsigned int m_BitsPerSample; /*!< @brief (required) bits per sample */ + unsigned int m_Channels; /*!< @brief (required) amount of channels */ + unsigned int m_SampleRate; /*!< @brief (required) sample rate */ + unsigned int m_BitRate; /*!< @brief (required) bit rate */ + unsigned int m_BitsPerSample; /*!< @brief (required) bits per sample */ unsigned int m_BlockAlign; CRYPTO_INFO m_cryptoInfo; // new in API version 2.0.8 - unsigned int m_codecFourCC; /*!< @brief Codec If available, the fourcc code codec */ - INPUTSTREAM_COLORSPACE m_colorSpace; /*!< @brief definition of colorspace */ - INPUTSTREAM_COLORRANGE m_colorRange; /*!< @brief color range if available */ + unsigned int m_codecFourCC; /*!< @brief Codec If available, the fourcc code codec */ + COLORSPACE m_colorSpace; /*!< @brief definition of colorspace */ + COLORRANGE m_colorRange; /*!< @brief color range if available */ + + //new in API 2.0.9 / INPUTSTREAM_VERSION_LEVEL 1 + COLORPRIMARIES m_colorPrimaries; + COLORTRC m_colorTransferCharacteristic; + INPUTSTREAM_MASTERING_METADATA* m_masteringMetadata; /*!< @brief mastering static Metadata */ + INPUTSTREAM_CONTENTLIGHT_METADATA* + m_contentLightMetadata; /*!< @brief content light static Metadata */ }; struct INPUTSTREAM_TIMES @@ -188,7 +288,7 @@ extern "C" { }; /*! - * @brief Structure to transfer the methods from xbmc_inputstream_dll.h to XBMC + * @brief "C" ABI Structures to transfer the methods from this to Kodi */ // this are properties given to the addon on create @@ -202,53 +302,72 @@ extern "C" { { KODI_HANDLE kodiInstance; DemuxPacket* (*allocate_demux_packet)(void* kodiInstance, int data_size); - DemuxPacket* (*allocate_encrypted_demux_packet)(void* kodiInstance, unsigned int data_size, unsigned int encrypted_subsample_count); + DemuxPacket* (*allocate_encrypted_demux_packet)(void* kodiInstance, + unsigned int data_size, + unsigned int encrypted_subsample_count); void (*free_demux_packet)(void* kodiInstance, DemuxPacket* packet); } AddonToKodiFuncTable_InputStream; struct AddonInstance_InputStream; typedef struct KodiToAddonFuncTable_InputStream /* internal */ { - kodi::addon::CInstanceInputStream* addonInstance; + KODI_HANDLE addonInstance; - bool (__cdecl* open)(const AddonInstance_InputStream* instance, INPUTSTREAM* props); - void (__cdecl* close)(const AddonInstance_InputStream* instance); - const char* (__cdecl* get_path_list)(const AddonInstance_InputStream* instance); - void (__cdecl* get_capabilities)(const AddonInstance_InputStream* instance, INPUTSTREAM_CAPABILITIES* capabilities); + bool(__cdecl* open)(const AddonInstance_InputStream* instance, INPUTSTREAM* props); + void(__cdecl* close)(const AddonInstance_InputStream* instance); + const char*(__cdecl* get_path_list)(const AddonInstance_InputStream* instance); + void(__cdecl* get_capabilities)(const AddonInstance_InputStream* instance, + INPUTSTREAM_CAPABILITIES* capabilities); // IDemux - struct INPUTSTREAM_IDS (__cdecl* get_stream_ids)(const AddonInstance_InputStream* instance); - struct INPUTSTREAM_INFO (__cdecl* get_stream)(const AddonInstance_InputStream* instance, int streamid); - void (__cdecl* enable_stream)(const AddonInstance_InputStream* instance, int streamid, bool enable); + struct INPUTSTREAM_IDS(__cdecl* get_stream_ids)(const AddonInstance_InputStream* instance); + struct INPUTSTREAM_INFO(__cdecl* get_stream)(const AddonInstance_InputStream* instance, + int streamid); + void(__cdecl* enable_stream)(const AddonInstance_InputStream* instance, + int streamid, + bool enable); bool(__cdecl* open_stream)(const AddonInstance_InputStream* instance, int streamid); - void (__cdecl* demux_reset)(const AddonInstance_InputStream* instance); - void (__cdecl* demux_abort)(const AddonInstance_InputStream* instance); - void (__cdecl* demux_flush)(const AddonInstance_InputStream* instance); - DemuxPacket* (__cdecl* demux_read)(const AddonInstance_InputStream* instance); - bool (__cdecl* demux_seek_time)(const AddonInstance_InputStream* instance, double time, bool backwards, double* startpts); - void (__cdecl* demux_set_speed)(const AddonInstance_InputStream* instance, int speed); - void (__cdecl* set_video_resolution)(const AddonInstance_InputStream* instance, int width, int height); + void(__cdecl* demux_reset)(const AddonInstance_InputStream* instance); + void(__cdecl* demux_abort)(const AddonInstance_InputStream* instance); + void(__cdecl* demux_flush)(const AddonInstance_InputStream* instance); + DemuxPacket*(__cdecl* demux_read)(const AddonInstance_InputStream* instance); + bool(__cdecl* demux_seek_time)(const AddonInstance_InputStream* instance, + double time, + bool backwards, + double* startpts); + void(__cdecl* demux_set_speed)(const AddonInstance_InputStream* instance, int speed); + void(__cdecl* set_video_resolution)(const AddonInstance_InputStream* instance, + int width, + int height); // IDisplayTime - int (__cdecl* get_total_time)(const AddonInstance_InputStream* instance); - int (__cdecl* get_time)(const AddonInstance_InputStream* instance); + int(__cdecl* get_total_time)(const AddonInstance_InputStream* instance); + int(__cdecl* get_time)(const AddonInstance_InputStream* instance); // ITime - bool(__cdecl* get_times)(const AddonInstance_InputStream* instance, INPUTSTREAM_TIMES *times); + bool(__cdecl* get_times)(const AddonInstance_InputStream* instance, INPUTSTREAM_TIMES* times); // IPosTime - bool (__cdecl* pos_time)(const AddonInstance_InputStream* instance, int ms); - - // Seekable (mandatory) - bool (__cdecl* can_pause_stream)(const AddonInstance_InputStream* instance); - bool (__cdecl* can_seek_stream)(const AddonInstance_InputStream* instance); - - int (__cdecl* read_stream)(const AddonInstance_InputStream* instance, uint8_t* buffer, unsigned int bufferSize); - int64_t(__cdecl* seek_stream)(const AddonInstance_InputStream* instance, int64_t position, int whence); - int64_t (__cdecl* position_stream)(const AddonInstance_InputStream* instance); - int64_t (__cdecl* length_stream)(const AddonInstance_InputStream* instance); - void (__cdecl* pause_stream)(const AddonInstance_InputStream* instance, double time); - bool (__cdecl* is_real_time_stream)(const AddonInstance_InputStream* instance); + bool(__cdecl* pos_time)(const AddonInstance_InputStream* instance, int ms); + + int(__cdecl* read_stream)(const AddonInstance_InputStream* instance, + uint8_t* buffer, + unsigned int bufferSize); + int64_t(__cdecl* seek_stream)(const AddonInstance_InputStream* instance, + int64_t position, + int whence); + int64_t(__cdecl* position_stream)(const AddonInstance_InputStream* instance); + int64_t(__cdecl* length_stream)(const AddonInstance_InputStream* instance); + bool(__cdecl* is_real_time_stream)(const AddonInstance_InputStream* instance); + + // IChapter + int(__cdecl* get_chapter)(const AddonInstance_InputStream* instance); + int(__cdecl* get_chapter_count)(const AddonInstance_InputStream* instance); + const char*(__cdecl* get_chapter_name)(const AddonInstance_InputStream* instance, int ch); + int64_t(__cdecl* get_chapter_pos)(const AddonInstance_InputStream* instance, int ch); + bool(__cdecl* seek_chapter)(const AddonInstance_InputStream* instance, int ch); + + int(__cdecl* block_size_stream)(const AddonInstance_InputStream* instance); } KodiToAddonFuncTable_InputStream; typedef struct AddonInstance_InputStream /* internal */ @@ -258,6 +377,7 @@ extern "C" { KodiToAddonFuncTable_InputStream toAddon; } AddonInstance_InputStream; +#ifdef __cplusplus } /* extern "C" */ namespace kodi @@ -265,90 +385,93 @@ namespace kodi namespace addon { - class CInstanceInputStream : public IAddonInstance +class ATTRIBUTE_HIDDEN CInstanceInputStream : public IAddonInstance +{ +public: + explicit CInstanceInputStream(KODI_HANDLE instance, const std::string& kodiVersion = "") + : IAddonInstance(ADDON_INSTANCE_INPUTSTREAM, + !kodiVersion.empty() ? kodiVersion + : GetKodiTypeVersion(ADDON_INSTANCE_INPUTSTREAM)) { - public: - explicit CInstanceInputStream(KODI_HANDLE instance) - : IAddonInstance(ADDON_INSTANCE_INPUTSTREAM) - { - if (CAddonBase::m_interface->globalSingleInstance != nullptr) - throw std::logic_error("kodi::addon::CInstanceInputStream: Creation of multiple together with single instance way is not allowed!"); + if (CAddonBase::m_interface->globalSingleInstance != nullptr) + throw std::logic_error("kodi::addon::CInstanceInputStream: Creation of multiple together " + "with single instance way is not allowed!"); - SetAddonStruct(instance); - } + SetAddonStruct(instance, m_kodiVersion); + } - ~CInstanceInputStream() override = default; + ~CInstanceInputStream() override = default; - /*! + /*! * Open a stream. * @param props * @return True if the stream has been opened successfully, false otherwise. * @remarks */ - virtual bool Open(INPUTSTREAM& props) = 0; + virtual bool Open(INPUTSTREAM& props) = 0; - /*! + /*! * Close an open stream. * @remarks */ - virtual void Close() = 0; + virtual void Close() = 0; - /*! + /*! * Get Capabilities of this addon. * @param capabilities The add-on's capabilities. * @remarks */ - virtual void GetCapabilities(INPUTSTREAM_CAPABILITIES& capabilities) = 0; + virtual void GetCapabilities(INPUTSTREAM_CAPABILITIES& capabilities) = 0; - /*! + /*! * Get IDs of available streams * @remarks */ - virtual INPUTSTREAM_IDS GetStreamIds() = 0; + virtual INPUTSTREAM_IDS GetStreamIds() = 0; - /*! + /*! * Get stream properties of a stream. * @param streamid unique id of stream * @return struc of stream properties * @remarks */ - virtual INPUTSTREAM_INFO GetStream(int streamid) = 0; + virtual INPUTSTREAM_INFO GetStream(int streamid) = 0; - /*! + /*! * Enable or disable a stream. * A disabled stream does not send demux packets * @param streamid unique id of stream * @param enable true for enable, false for disable * @remarks */ - virtual void EnableStream(int streamid, bool enable) = 0; + virtual void EnableStream(int streamid, bool enable) = 0; - /*! + /*! * Opens a stream for playback. * @param streamid unique id of stream * @remarks */ - virtual bool OpenStream(int streamid) = 0; + virtual bool OpenStream(int streamid) = 0; - /*! + /*! * Reset the demultiplexer in the add-on. * @remarks Required if bHandlesDemuxing is set to true. */ - virtual void DemuxReset() { } + virtual void DemuxReset() {} - /*! + /*! * Abort the demultiplexer thread in the add-on. * @remarks Required if bHandlesDemuxing is set to true. */ - virtual void DemuxAbort() { } + virtual void DemuxAbort() {} - /*! + /*! * Flush all data that's currently in the demultiplexer buffer in the add-on. * @remarks Required if bHandlesDemuxing is set to true. */ - virtual void DemuxFlush() { } + virtual void DemuxFlush() {} - /*! + /*! * Read the next packet from the demultiplexer, if there is one. * @return The next packet. * If there is no next packet, then the add-on should return the @@ -357,12 +480,12 @@ namespace addon * then, the add-on should call AllocateDemuxPacket(0) on the * callback, and set the streamid to DMX_SPECIALID_STREAMCHANGE and * return the value. - * The add-on should return NULL if an error occured. + * The add-on should return NULL if an error occurred. * @remarks Return NULL if this add-on won't provide this function. */ - virtual DemuxPacket* DemuxRead() { return nullptr; } + virtual DemuxPacket* DemuxRead() { return nullptr; } - /*! + /*! * Notify the InputStream addon/demuxer that Kodi wishes to seek the stream by time * Demuxer is required to set stream to an IDR frame * @param time The absolute time since stream start @@ -371,314 +494,388 @@ namespace addon * @return True if the seek operation was possible * @remarks Optional, and only used if addon has its own demuxer. */ - virtual bool DemuxSeekTime(double time, bool backwards, double &startpts) { return false; } + virtual bool DemuxSeekTime(double time, bool backwards, double& startpts) { return false; } - /*! + /*! * Notify the InputStream addon/demuxer that Kodi wishes to change playback speed * @param speed The requested playback speed * @remarks Optional, and only used if addon has its own demuxer. */ - virtual void DemuxSetSpeed(int speed) { } + virtual void DemuxSetSpeed(int speed) {} - /*! + /*! * Sets desired width / height * @param width / hight */ - virtual void SetVideoResolution(int width, int height) { } + virtual void SetVideoResolution(int width, int height) {} - /*! + /*! * Totel time in ms * @remarks */ - virtual int GetTotalTime() { return -1; } + virtual int GetTotalTime() { return -1; } - /*! + /*! * Playing time in ms * @remarks */ - virtual int GetTime() { return -1; } + virtual int GetTime() { return -1; } - /*! + /*! * Get current timing values in PTS scale * @remarks */ - virtual bool GetTimes(INPUTSTREAM_TIMES ×) { return false; } + virtual bool GetTimes(INPUTSTREAM_TIMES& times) { return false; } - /*! + /*! * Positions inputstream to playing time given in ms * @remarks */ - virtual bool PosTime(int ms) { return false; } + virtual bool PosTime(int ms) { return false; } + /*! + * Return currently selected chapter + * @remarks + */ + virtual int GetChapter() { return -1; }; - /*! - * Check if the backend support pausing the currently playing stream - * This will enable/disable the pause button in Kodi based on the return value - * @return false if the InputStream addon/backend does not support pausing, true if possible - */ - virtual bool CanPauseStream() { return false; } + /*! + * Return number of available chapters + * @remarks + */ + virtual int GetChapterCount() { return 0; }; - /*! - * Check if the backend supports seeking for the currently playing stream - * This will enable/disable the rewind/forward buttons in Kodi based on the return value - * @return false if the InputStream addon/backend does not support seeking, true if possible - */ - virtual bool CanSeekStream() { return false; } + /*! + * Return name of chapter # ch + * @remarks + */ + virtual const char* GetChapterName(int ch) { return nullptr; }; + + /*! + * Return position if chapter # ch in milliseconds + * @remarks + */ + virtual int64_t GetChapterPos(int ch) { return 0; }; + + /*! + * Seek to the beginning of chapter # ch + * @remarks + */ + virtual bool SeekChapter(int ch) { return false; }; - /*! + /*! * Read from an open stream. * @param buffer The buffer to store the data in. * @param bufferSize The amount of bytes to read. * @return The amount of bytes that were actually read from the stream. * @remarks Return -1 if this add-on won't provide this function. */ - virtual int ReadStream(uint8_t* buffer, unsigned int bufferSize) { return -1; } + virtual int ReadStream(uint8_t* buffer, unsigned int bufferSize) { return -1; } - /*! + /*! * Seek in a stream. * @param position The position to seek to. * @param whence ? * @return The new position. * @remarks Return -1 if this add-on won't provide this function. */ - virtual int64_t SeekStream(int64_t position, int whence = SEEK_SET) { return -1; } + virtual int64_t SeekStream(int64_t position, int whence = SEEK_SET) { return -1; } - /*! + /*! * @return The position in the stream that's currently being read. * @remarks Return -1 if this add-on won't provide this function. */ - virtual int64_t PositionStream() { return -1; } + virtual int64_t PositionStream() { return -1; } - /*! + /*! * @return The total length of the stream that's currently being read. * @remarks Return -1 if this add-on won't provide this function. */ - virtual int64_t LengthStream() { return -1; } - + virtual int64_t LengthStream() { return -1; } - /*! - * @brief Notify the InputStream addon that Kodi (un)paused the currently playing stream + /*! + * @return Obtain the chunk size to use when reading streams. + * @remarks Return 0 if this add-on won't provide this function. */ - virtual void PauseStream(double time) { } - + virtual int GetBlockSize() { return 0; } - /*! + /*! * Check for real-time streaming * @return true if current stream is real-time */ - virtual bool IsRealTimeStream() { return true; } + virtual bool IsRealTimeStream() { return true; } - /*! + /*! * @brief Allocate a demux packet. Free with FreeDemuxPacket * @param dataSize The size of the data that will go into the packet * @return The allocated packet */ - DemuxPacket* AllocateDemuxPacket(int dataSize) - { - return m_instanceData->toKodi.allocate_demux_packet(m_instanceData->toKodi.kodiInstance, dataSize); - } + DemuxPacket* AllocateDemuxPacket(int dataSize) + { + return m_instanceData->toKodi.allocate_demux_packet(m_instanceData->toKodi.kodiInstance, + dataSize); + } - /*! + /*! * @brief Allocate a demux packet. Free with FreeDemuxPacket * @param dataSize The size of the data that will go into the packet * @return The allocated packet */ - DemuxPacket* AllocateEncryptedDemuxPacket(int dataSize, unsigned int encryptedSubsampleCount) - { - return m_instanceData->toKodi.allocate_encrypted_demux_packet(m_instanceData->toKodi.kodiInstance, dataSize, encryptedSubsampleCount); - } + DemuxPacket* AllocateEncryptedDemuxPacket(int dataSize, unsigned int encryptedSubsampleCount) + { + return m_instanceData->toKodi.allocate_encrypted_demux_packet( + m_instanceData->toKodi.kodiInstance, dataSize, encryptedSubsampleCount); + } - /*! + /*! * @brief Free a packet that was allocated with AllocateDemuxPacket * @param packet The packet to free */ - void FreeDemuxPacket(DemuxPacket* packet) - { - return m_instanceData->toKodi.free_demux_packet(m_instanceData->toKodi.kodiInstance, packet); - } + void FreeDemuxPacket(DemuxPacket* packet) + { + return m_instanceData->toKodi.free_demux_packet(m_instanceData->toKodi.kodiInstance, packet); + } - private: - void SetAddonStruct(KODI_HANDLE instance) - { - if (instance == nullptr) - throw std::logic_error("kodi::addon::CInstanceInputStream: Creation with empty addon structure not allowed, table must be given from Kodi!"); - - m_instanceData = static_cast(instance); - m_instanceData->toAddon.addonInstance = this; - m_instanceData->toAddon.open = ADDON_Open; - m_instanceData->toAddon.close = ADDON_Close; - m_instanceData->toAddon.get_capabilities = ADDON_GetCapabilities; - - m_instanceData->toAddon.get_stream_ids = ADDON_GetStreamIds; - m_instanceData->toAddon.get_stream = ADDON_GetStream; - m_instanceData->toAddon.enable_stream = ADDON_EnableStream; - m_instanceData->toAddon.open_stream = ADDON_OpenStream; - m_instanceData->toAddon.demux_reset = ADDON_DemuxReset; - m_instanceData->toAddon.demux_abort = ADDON_DemuxAbort; - m_instanceData->toAddon.demux_flush = ADDON_DemuxFlush; - m_instanceData->toAddon.demux_read = ADDON_DemuxRead; - m_instanceData->toAddon.demux_seek_time = ADDON_DemuxSeekTime; - m_instanceData->toAddon.demux_set_speed = ADDON_DemuxSetSpeed; - m_instanceData->toAddon.set_video_resolution = ADDON_SetVideoResolution; - - m_instanceData->toAddon.get_total_time = ADDON_GetTotalTime; - m_instanceData->toAddon.get_time = ADDON_GetTime; - - m_instanceData->toAddon.get_times = ADDON_GetTimes; - - m_instanceData->toAddon.pos_time = ADDON_PosTime; - - m_instanceData->toAddon.can_pause_stream = ADDON_CanPauseStream; - m_instanceData->toAddon.can_seek_stream = ADDON_CanSeekStream; - - m_instanceData->toAddon.read_stream = ADDON_ReadStream; - m_instanceData->toAddon.seek_stream = ADDON_SeekStream; - m_instanceData->toAddon.position_stream = ADDON_PositionStream; - m_instanceData->toAddon.length_stream = ADDON_LengthStream; - m_instanceData->toAddon.pause_stream = ADDON_PauseStream; - m_instanceData->toAddon.is_real_time_stream = ADDON_IsRealTimeStream; - } +private: + static int compareVersion(const int v1[3], const int v2[3]) + { + for (unsigned i(0); i < 3; ++i) + if (v1[i] != v2[i]) + return v1[i] - v2[i]; + return 0; + } - inline static bool ADDON_Open(const AddonInstance_InputStream* instance, INPUTSTREAM* props) - { - return instance->toAddon.addonInstance->Open(*props); + void SetAddonStruct(KODI_HANDLE instance, const std::string& kodiVersion) + { + if (instance == nullptr) + throw std::logic_error("kodi::addon::CInstanceInputStream: Creation with empty addon " + "structure not allowed, table must be given from Kodi!"); + int api[3] = { 0, 0, 0 }; + sscanf(kodiVersion.c_str(), "%d.%d.%d", &api[0], &api[1], &api[2]); + + m_instanceData = static_cast(instance); + m_instanceData->toAddon.addonInstance = this; + m_instanceData->toAddon.open = ADDON_Open; + m_instanceData->toAddon.close = ADDON_Close; + m_instanceData->toAddon.get_capabilities = ADDON_GetCapabilities; + + m_instanceData->toAddon.get_stream_ids = ADDON_GetStreamIds; + m_instanceData->toAddon.get_stream = ADDON_GetStream; + m_instanceData->toAddon.enable_stream = ADDON_EnableStream; + m_instanceData->toAddon.open_stream = ADDON_OpenStream; + m_instanceData->toAddon.demux_reset = ADDON_DemuxReset; + m_instanceData->toAddon.demux_abort = ADDON_DemuxAbort; + m_instanceData->toAddon.demux_flush = ADDON_DemuxFlush; + m_instanceData->toAddon.demux_read = ADDON_DemuxRead; + m_instanceData->toAddon.demux_seek_time = ADDON_DemuxSeekTime; + m_instanceData->toAddon.demux_set_speed = ADDON_DemuxSetSpeed; + m_instanceData->toAddon.set_video_resolution = ADDON_SetVideoResolution; + + m_instanceData->toAddon.get_total_time = ADDON_GetTotalTime; + m_instanceData->toAddon.get_time = ADDON_GetTime; + + m_instanceData->toAddon.get_times = ADDON_GetTimes; + m_instanceData->toAddon.pos_time = ADDON_PosTime; + + m_instanceData->toAddon.read_stream = ADDON_ReadStream; + m_instanceData->toAddon.seek_stream = ADDON_SeekStream; + m_instanceData->toAddon.position_stream = ADDON_PositionStream; + m_instanceData->toAddon.length_stream = ADDON_LengthStream; + m_instanceData->toAddon.is_real_time_stream = ADDON_IsRealTimeStream; + + int minChapterVersion[3] = { 2, 0, 10 }; + if (compareVersion(api, minChapterVersion) >= 0) + { + m_instanceData->toAddon.get_chapter = ADDON_GetChapter; + m_instanceData->toAddon.get_chapter_count = ADDON_GetChapterCount; + m_instanceData->toAddon.get_chapter_name = ADDON_GetChapterName; + m_instanceData->toAddon.get_chapter_pos = ADDON_GetChapterPos; + m_instanceData->toAddon.seek_chapter = ADDON_SeekChapter; } - inline static void ADDON_Close(const AddonInstance_InputStream* instance) + int minBlockSizeVersion[3] = {2, 0, 12}; + if (compareVersion(api, minBlockSizeVersion) >= 0) { - instance->toAddon.addonInstance->Close(); + m_instanceData->toAddon.block_size_stream = ADDON_GetBlockSize; } + } - inline static void ADDON_GetCapabilities(const AddonInstance_InputStream* instance, INPUTSTREAM_CAPABILITIES* capabilities) - { - instance->toAddon.addonInstance->GetCapabilities(*capabilities); - } + inline static bool ADDON_Open(const AddonInstance_InputStream* instance, INPUTSTREAM* props) + { + return static_cast(instance->toAddon.addonInstance)->Open(*props); + } + inline static void ADDON_Close(const AddonInstance_InputStream* instance) + { + static_cast(instance->toAddon.addonInstance)->Close(); + } - // IDemux - inline static struct INPUTSTREAM_IDS ADDON_GetStreamIds(const AddonInstance_InputStream* instance) - { - return instance->toAddon.addonInstance->GetStreamIds(); - } + inline static void ADDON_GetCapabilities(const AddonInstance_InputStream* instance, + INPUTSTREAM_CAPABILITIES* capabilities) + { + static_cast(instance->toAddon.addonInstance) + ->GetCapabilities(*capabilities); + } - inline static struct INPUTSTREAM_INFO ADDON_GetStream(const AddonInstance_InputStream* instance, int streamid) - { - return instance->toAddon.addonInstance->GetStream(streamid); - } - inline static void ADDON_EnableStream(const AddonInstance_InputStream* instance, int streamid, bool enable) - { - instance->toAddon.addonInstance->EnableStream(streamid, enable); - } + // IDemux + inline static struct INPUTSTREAM_IDS ADDON_GetStreamIds(const AddonInstance_InputStream* instance) + { + return static_cast(instance->toAddon.addonInstance)->GetStreamIds(); + } - inline static bool ADDON_OpenStream(const AddonInstance_InputStream* instance, int streamid) - { - return instance->toAddon.addonInstance->OpenStream(streamid); - } + inline static struct INPUTSTREAM_INFO ADDON_GetStream(const AddonInstance_InputStream* instance, + int streamid) + { + return static_cast(instance->toAddon.addonInstance)->GetStream(streamid); + } - inline static void ADDON_DemuxReset(const AddonInstance_InputStream* instance) - { - instance->toAddon.addonInstance->DemuxReset(); - } + inline static void ADDON_EnableStream(const AddonInstance_InputStream* instance, + int streamid, + bool enable) + { + static_cast(instance->toAddon.addonInstance) + ->EnableStream(streamid, enable); + } - inline static void ADDON_DemuxAbort(const AddonInstance_InputStream* instance) - { - instance->toAddon.addonInstance->DemuxAbort(); - } + inline static bool ADDON_OpenStream(const AddonInstance_InputStream* instance, int streamid) + { + return static_cast(instance->toAddon.addonInstance) + ->OpenStream(streamid); + } - inline static void ADDON_DemuxFlush(const AddonInstance_InputStream* instance) - { - instance->toAddon.addonInstance->DemuxFlush(); - } + inline static void ADDON_DemuxReset(const AddonInstance_InputStream* instance) + { + static_cast(instance->toAddon.addonInstance)->DemuxReset(); + } - inline static DemuxPacket* ADDON_DemuxRead(const AddonInstance_InputStream* instance) - { - return instance->toAddon.addonInstance->DemuxRead(); - } + inline static void ADDON_DemuxAbort(const AddonInstance_InputStream* instance) + { + static_cast(instance->toAddon.addonInstance)->DemuxAbort(); + } - inline static bool ADDON_DemuxSeekTime(const AddonInstance_InputStream* instance, double time, bool backwards, double *startpts) - { - return instance->toAddon.addonInstance->DemuxSeekTime(time, backwards, *startpts); - } + inline static void ADDON_DemuxFlush(const AddonInstance_InputStream* instance) + { + static_cast(instance->toAddon.addonInstance)->DemuxFlush(); + } - inline static void ADDON_DemuxSetSpeed(const AddonInstance_InputStream* instance, int speed) - { - instance->toAddon.addonInstance->DemuxSetSpeed(speed); - } + inline static DemuxPacket* ADDON_DemuxRead(const AddonInstance_InputStream* instance) + { + return static_cast(instance->toAddon.addonInstance)->DemuxRead(); + } - inline static void ADDON_SetVideoResolution(const AddonInstance_InputStream* instance, int width, int height) - { - instance->toAddon.addonInstance->SetVideoResolution(width, height); - } + inline static bool ADDON_DemuxSeekTime(const AddonInstance_InputStream* instance, + double time, + bool backwards, + double* startpts) + { + return static_cast(instance->toAddon.addonInstance) + ->DemuxSeekTime(time, backwards, *startpts); + } + inline static void ADDON_DemuxSetSpeed(const AddonInstance_InputStream* instance, int speed) + { + static_cast(instance->toAddon.addonInstance)->DemuxSetSpeed(speed); + } - // IDisplayTime - inline static int ADDON_GetTotalTime(const AddonInstance_InputStream* instance) - { - return instance->toAddon.addonInstance->GetTotalTime(); - } + inline static void ADDON_SetVideoResolution(const AddonInstance_InputStream* instance, + int width, + int height) + { + static_cast(instance->toAddon.addonInstance) + ->SetVideoResolution(width, height); + } - inline static int ADDON_GetTime(const AddonInstance_InputStream* instance) - { - return instance->toAddon.addonInstance->GetTime(); - } - // ITime - inline static bool ADDON_GetTimes(const AddonInstance_InputStream* instance, INPUTSTREAM_TIMES *times) - { - return instance->toAddon.addonInstance->GetTimes(*times); - } + // IDisplayTime + inline static int ADDON_GetTotalTime(const AddonInstance_InputStream* instance) + { + return static_cast(instance->toAddon.addonInstance)->GetTotalTime(); + } - // IPosTime - inline static bool ADDON_PosTime(const AddonInstance_InputStream* instance, int ms) - { - return instance->toAddon.addonInstance->PosTime(ms); - } + inline static int ADDON_GetTime(const AddonInstance_InputStream* instance) + { + return static_cast(instance->toAddon.addonInstance)->GetTime(); + } - // Seekable (mandatory) - inline static bool ADDON_CanPauseStream(const AddonInstance_InputStream* instance) - { - return instance->toAddon.addonInstance->CanPauseStream(); - } + // ITime + inline static bool ADDON_GetTimes(const AddonInstance_InputStream* instance, + INPUTSTREAM_TIMES* times) + { + return static_cast(instance->toAddon.addonInstance)->GetTimes(*times); + } - inline static bool ADDON_CanSeekStream(const AddonInstance_InputStream* instance) - { - return instance->toAddon.addonInstance->CanSeekStream(); - } + // IPosTime + inline static bool ADDON_PosTime(const AddonInstance_InputStream* instance, int ms) + { + return static_cast(instance->toAddon.addonInstance)->PosTime(ms); + } + inline static int ADDON_GetChapter(const AddonInstance_InputStream* instance) + { + return static_cast(instance->toAddon.addonInstance)->GetChapter(); + } - inline static int ADDON_ReadStream(const AddonInstance_InputStream* instance, uint8_t* buffer, unsigned int bufferSize) - { - return instance->toAddon.addonInstance->ReadStream(buffer, bufferSize); - } + inline static int ADDON_GetChapterCount(const AddonInstance_InputStream* instance) + { + return static_cast(instance->toAddon.addonInstance)->GetChapterCount(); + } - inline static int64_t ADDON_SeekStream(const AddonInstance_InputStream* instance, int64_t position, int whence) - { - return instance->toAddon.addonInstance->SeekStream(position, whence); - } + inline static const char* ADDON_GetChapterName(const AddonInstance_InputStream* instance, int ch) + { + return static_cast(instance->toAddon.addonInstance)->GetChapterName(ch); + } - inline static int64_t ADDON_PositionStream(const AddonInstance_InputStream* instance) - { - return instance->toAddon.addonInstance->PositionStream(); - } + inline static int64_t ADDON_GetChapterPos(const AddonInstance_InputStream* instance, int ch) + { + return static_cast(instance->toAddon.addonInstance)->GetChapterPos(ch); + } - inline static int64_t ADDON_LengthStream(const AddonInstance_InputStream* instance) - { - return instance->toAddon.addonInstance->LengthStream(); - } + inline static bool ADDON_SeekChapter(const AddonInstance_InputStream* instance, int ch) + { + return static_cast(instance->toAddon.addonInstance)->SeekChapter(ch); + } - inline static void ADDON_PauseStream(const AddonInstance_InputStream* instance, double time) - { - instance->toAddon.addonInstance->PauseStream(time); - } + inline static int ADDON_ReadStream(const AddonInstance_InputStream* instance, + uint8_t* buffer, + unsigned int bufferSize) + { + return static_cast(instance->toAddon.addonInstance) + ->ReadStream(buffer, bufferSize); + } - inline static bool ADDON_IsRealTimeStream(const AddonInstance_InputStream* instance) - { - return instance->toAddon.addonInstance->IsRealTimeStream(); - } + inline static int64_t ADDON_SeekStream(const AddonInstance_InputStream* instance, + int64_t position, + int whence) + { + return static_cast(instance->toAddon.addonInstance) + ->SeekStream(position, whence); + } - AddonInstance_InputStream* m_instanceData; - }; + inline static int64_t ADDON_PositionStream(const AddonInstance_InputStream* instance) + { + return static_cast(instance->toAddon.addonInstance)->PositionStream(); + } + + inline static int64_t ADDON_LengthStream(const AddonInstance_InputStream* instance) + { + return static_cast(instance->toAddon.addonInstance)->LengthStream(); + } + + inline static int ADDON_GetBlockSize(const AddonInstance_InputStream* instance) + { + return static_cast(instance->toAddon.addonInstance)->GetBlockSize(); + } + + inline static bool ADDON_IsRealTimeStream(const AddonInstance_InputStream* instance) + { + return static_cast(instance->toAddon.addonInstance)->IsRealTimeStream(); + } + + AddonInstance_InputStream* m_instanceData; +}; } /* namespace addon */ } /* namespace kodi */ + +#endif /* __cplusplus */ -- cgit v1.2.3