/* * Copyright (C) 2005-2018 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later * See LICENSES/README.md for more information. */ #pragma once /* * Parts with a comment named "internal" are only used inside header and not * used or accessed direct during add-on development! */ #include "../AddonBase.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 //Increment this level always if you add features which can lead to compile failures in the addon #define INPUTSTREAM_VERSION_LEVEL 2 #define INPUTSTREAM_MAX_STREAM_COUNT 256 #define INPUTSTREAM_MAX_STRING_NAME_SIZE 256 #define INPUTSTREAM_MAX_STRING_CODEC_SIZE 32 #define INPUTSTREAM_MAX_STRING_LANGUAGE_SIZE 64 #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 { /// supports interface IDemux SUPPORTS_IDEMUX = (1 << 0), /// supports interface IPosTime SUPPORTS_IPOSTIME = (1 << 1), /// supports interface IDisplayTime SUPPORTS_IDISPLAYTIME = (1 << 2), /// supports seek SUPPORTS_SEEK = (1 << 3), /// supports pause SUPPORTS_PAUSE = (1 << 4), /// supports interface ITime SUPPORTS_ITIME = (1 << 5), /// supports interface IChapter SUPPORTS_ICHAPTER = (1 << 6), }; /// set of supported capabilities uint32_t m_mask; }; /*! * @brief structure of key/value pairs passed to addon on Open() */ struct INPUTSTREAM { const char* m_strURL; const char* m_mimeType; unsigned int m_nCountInfoValues; struct LISTITEMPROPERTY { const char* m_strKey; const char* m_strValue; } m_ListItemProperties[STREAM_MAX_PROPERTY_COUNT]; const char* m_libFolder; const char* m_profileFolder; }; /*! * @brief Array of stream IDs */ struct INPUTSTREAM_IDS { unsigned int m_streamCount; unsigned int m_streamIds[INPUTSTREAM_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 */ struct INPUTSTREAM_INFO { enum STREAM_TYPE { TYPE_NONE = 0, TYPE_VIDEO, TYPE_AUDIO, TYPE_SUBTITLE, TYPE_TELETEXT, TYPE_RDS, } m_streamType; enum Codec_FEATURES : uint32_t { FEATURE_DECODE = 1 }; uint32_t m_features; enum STREAM_FLAGS : uint32_t { FLAG_NONE = 0x0000, FLAG_DEFAULT = 0x0001, FLAG_DUB = 0x0002, FLAG_ORIGINAL = 0x0004, FLAG_COMMENT = 0x0008, FLAG_LYRICS = 0x0010, FLAG_KARAOKE = 0x0020, FLAG_FORCED = 0x0040, FLAG_HEARING_IMPAIRED = 0x0080, FLAG_VISUAL_IMPAIRED = 0x0100, }; // 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 }; // Keep in sync with AVColorRange enum COLORRANGE { COLORRANGE_UNKNOWN = 0, COLORRANGE_LIMITED, 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; //! @brief (optional) name of the stream, \0 for default handling char m_name[INPUTSTREAM_MAX_STRING_NAME_SIZE]; //! @brief (required) name of codec according to ffmpeg char m_codecName[INPUTSTREAM_MAX_STRING_CODEC_SIZE]; //! @brief (optional) internal name of codec (selectionstream info) char m_codecInternalName[INPUTSTREAM_MAX_STRING_CODEC_SIZE]; //! @brief (optional) the profile of the codec STREAMCODEC_PROFILE m_codecProfile; //! @brief (required) physical index unsigned int m_pID; const uint8_t* m_ExtraData; unsigned int m_ExtraSize; //! @brief RFC 5646 language code (empty string if undefined) char m_language[INPUTSTREAM_MAX_STRING_LANGUAGE_SIZE]; //! Video stream related data //@{ //! @brief Scale of 1000 and a rate of 29970 will result in 29.97 fps unsigned int m_FpsScale; unsigned int m_FpsRate; //! @brief height of the stream reported by the demuxer unsigned int m_Height; //! @brief width of the stream reported by the demuxer unsigned int m_Width; //! @brief display aspect of stream float m_Aspect; //@} //! Audio stream related data //@{ //! @brief (required) amount of channels unsigned int m_Channels; //! @brief (required) sample rate unsigned int m_SampleRate; //! @brief (required) bit rate unsigned int m_BitRate; //! @brief (required) bits per sample unsigned int m_BitsPerSample; unsigned int m_BlockAlign; //@} CRYPTO_INFO m_cryptoInfo; // new in API version 2.0.8 //@{ //! @brief Codec If available, the fourcc code codec unsigned int m_codecFourCC; //! @brief definition of colorspace COLORSPACE m_colorSpace; //! @brief color range if available COLORRANGE m_colorRange; //@} //new in API 2.0.9 / INPUTSTREAM_VERSION_LEVEL 1 //@{ COLORPRIMARIES m_colorPrimaries; COLORTRC m_colorTransferCharacteristic; //@} //! @brief mastering static Metadata INPUTSTREAM_MASTERING_METADATA* m_masteringMetadata; //! @brief content light static Metadata INPUTSTREAM_CONTENTLIGHT_METADATA* m_contentLightMetadata; }; struct INPUTSTREAM_TIMES { time_t startTime; double ptsStart; double ptsBegin; double ptsEnd; }; /*! * @brief "C" ABI Structures to transfer the methods from this to Kodi */ // this are properties given to the addon on create // at this time we have no parameters for the addon typedef struct AddonProps_InputStream /* internal */ { int dummy; } AddonProps_InputStream; typedef struct AddonToKodiFuncTable_InputStream /* internal */ { 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); void (*free_demux_packet)(void* kodiInstance, DemuxPacket* packet); } AddonToKodiFuncTable_InputStream; struct AddonInstance_InputStream; typedef struct KodiToAddonFuncTable_InputStream /* internal */ { 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); // 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); 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); // IDisplayTime 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); // IPosTime 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 */ { AddonProps_InputStream* props; AddonToKodiFuncTable_InputStream* toKodi; KodiToAddonFuncTable_InputStream* toAddon; } AddonInstance_InputStream; #ifdef __cplusplus } /* extern "C" */ namespace kodi { namespace addon { 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)) { 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, m_kodiVersion); } ~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; /*! * Close an open stream. * @remarks */ virtual void Close() = 0; /*! * Get Capabilities of this addon. * @param capabilities The add-on's capabilities. * @remarks */ virtual void GetCapabilities(INPUTSTREAM_CAPABILITIES& capabilities) = 0; /*! * Get IDs of available streams * @remarks */ 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; /*! * 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; /*! * Opens a stream for playback. * @param streamid unique id of stream * @remarks */ virtual bool OpenStream(int streamid) = 0; /*! * Reset the demultiplexer in the add-on. * @remarks Required if bHandlesDemuxing is set to true. */ virtual void DemuxReset() {} /*! * Abort the demultiplexer thread in the add-on. * @remarks Required if bHandlesDemuxing is set to true. */ 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() {} /*! * 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 * packet created by calling AllocateDemuxPacket(0) on the callback. * If the stream changed and Kodi's player needs to be reinitialised, * 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 occurred. * @remarks Return NULL if this add-on won't provide this function. */ 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 * @param backwards True to seek to keyframe BEFORE time, else AFTER * @param startpts can be updated to point to where display should start * @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; } /*! * 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) {} /*! * Sets desired width / height * @param width / hight */ virtual void SetVideoResolution(int width, int height) {} /*! * Totel time in ms * @remarks */ virtual int GetTotalTime() { return -1; } /*! * Playing time in ms * @remarks */ virtual int GetTime() { return -1; } /*! * Get current timing values in PTS scale * @remarks */ virtual bool GetTimes(INPUTSTREAM_TIMES& times) { return false; } /*! * Positions inputstream to playing time given in ms * @remarks */ virtual bool PosTime(int ms) { return false; } /*! * Return currently selected chapter * @remarks */ virtual int GetChapter() { return -1; }; /*! * Return number of available chapters * @remarks */ virtual int GetChapterCount() { return 0; }; /*! * 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; } /*! * 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; } /*! * @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; } /*! * @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; } /*! * @return Obtain the chunk size to use when reading streams. * @remarks Return 0 if this add-on won't provide this function. */ virtual int GetBlockSize() { return 0; } /*! * Check for real-time streaming * @return true if current stream is real-time */ 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); } /*! * @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); } /*! * @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); } 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; } 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; // Added on 2.0.10 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; // Added on 2.0.12 m_instanceData->toAddon->block_size_stream = ADDON_GetBlockSize; /* // Way to include part on new API version int minPartVersion[3] = { 3, 0, 0 }; if (compareVersion(api, minPartVersion) >= 0) { } */ } 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(); } inline static void ADDON_GetCapabilities(const AddonInstance_InputStream* instance, INPUTSTREAM_CAPABILITIES* capabilities) { static_cast(instance->toAddon->addonInstance) ->GetCapabilities(*capabilities); } // IDemux inline static struct INPUTSTREAM_IDS ADDON_GetStreamIds(const AddonInstance_InputStream* instance) { return static_cast(instance->toAddon->addonInstance)->GetStreamIds(); } 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_EnableStream(const AddonInstance_InputStream* instance, int streamid, bool enable) { static_cast(instance->toAddon->addonInstance) ->EnableStream(streamid, enable); } inline static bool ADDON_OpenStream(const AddonInstance_InputStream* instance, int streamid) { return static_cast(instance->toAddon->addonInstance) ->OpenStream(streamid); } inline static void ADDON_DemuxReset(const AddonInstance_InputStream* instance) { static_cast(instance->toAddon->addonInstance)->DemuxReset(); } inline static void ADDON_DemuxAbort(const AddonInstance_InputStream* instance) { static_cast(instance->toAddon->addonInstance)->DemuxAbort(); } inline static void ADDON_DemuxFlush(const AddonInstance_InputStream* instance) { static_cast(instance->toAddon->addonInstance)->DemuxFlush(); } inline static DemuxPacket* ADDON_DemuxRead(const AddonInstance_InputStream* instance) { return static_cast(instance->toAddon->addonInstance)->DemuxRead(); } 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); } inline static void ADDON_SetVideoResolution(const AddonInstance_InputStream* instance, int width, int height) { static_cast(instance->toAddon->addonInstance) ->SetVideoResolution(width, height); } // IDisplayTime inline static int ADDON_GetTotalTime(const AddonInstance_InputStream* instance) { return static_cast(instance->toAddon->addonInstance)->GetTotalTime(); } inline static int ADDON_GetTime(const AddonInstance_InputStream* instance) { return static_cast(instance->toAddon->addonInstance)->GetTime(); } // ITime inline static bool ADDON_GetTimes(const AddonInstance_InputStream* instance, INPUTSTREAM_TIMES* times) { return static_cast(instance->toAddon->addonInstance)->GetTimes(*times); } // 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_GetChapterCount(const AddonInstance_InputStream* instance) { return static_cast(instance->toAddon->addonInstance)->GetChapterCount(); } 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_GetChapterPos(const AddonInstance_InputStream* instance, int ch) { return static_cast(instance->toAddon->addonInstance)->GetChapterPos(ch); } inline static bool ADDON_SeekChapter(const AddonInstance_InputStream* instance, int ch) { return static_cast(instance->toAddon->addonInstance)->SeekChapter(ch); } 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 int64_t ADDON_SeekStream(const AddonInstance_InputStream* instance, int64_t position, int whence) { return static_cast(instance->toAddon->addonInstance) ->SeekStream(position, whence); } 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 */