aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlwin Esch <alwin.esch@web.de>2017-06-22 17:41:11 +0200
committerGitHub <noreply@github.com>2017-06-22 17:41:11 +0200
commit506419b7c11350537fce2dc4179da1c5dff6fa16 (patch)
treee9be3cf3afcef88236c44e43d95c4915bed6bb49
parent1de7be400e9189d3c91c93ba1c84ff44f3e63a47 (diff)
parent428b378150d4104709279b48ed668acb09d92ad7 (diff)
Merge pull request #12325 from AlwinEsch/change-inputstream
[inputstream] change addon interface to new C++ style
-rw-r--r--xbmc/addons/AddonBuilder.cpp7
-rw-r--r--xbmc/addons/BinaryAddonCache.cpp1
-rw-r--r--xbmc/addons/CMakeLists.txt2
-rw-r--r--xbmc/addons/InputStream.cpp481
-rw-r--r--xbmc/addons/InputStream.h145
-rw-r--r--xbmc/addons/interfaces/AddonInterfaces.cpp20
-rw-r--r--xbmc/addons/interfaces/AddonInterfaces.h4
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h585
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_inputstream_dll.h256
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_inputstream_types.h187
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_inputstream.h89
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h8
-rw-r--r--xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp31
-rw-r--r--xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp365
-rw-r--r--xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.h87
15 files changed, 940 insertions, 1328 deletions
diff --git a/xbmc/addons/AddonBuilder.cpp b/xbmc/addons/AddonBuilder.cpp
index 7ce67db302..b39f0fc840 100644
--- a/xbmc/addons/AddonBuilder.cpp
+++ b/xbmc/addons/AddonBuilder.cpp
@@ -24,7 +24,6 @@
#include "addons/GameResource.h"
#include "addons/ImageDecoder.h"
#include "addons/ImageResource.h"
-#include "addons/InputStream.h"
#include "addons/LanguageResource.h"
#include "addons/PluginSource.h"
#include "addons/Repository.h"
@@ -125,6 +124,7 @@ std::shared_ptr<IAddon> CAddonBuilder::Build()
case ADDON_ADSPDLL:
case ADDON_AUDIOENCODER:
case ADDON_IMAGEDECODER:
+ case ADDON_INPUTSTREAM:
case ADDON_VIZ:
case ADDON_SCREENSAVER:
return std::make_shared<CAddonDll>(std::move(m_addonInfo));
@@ -132,8 +132,6 @@ std::shared_ptr<IAddon> CAddonBuilder::Build()
return std::make_shared<PVR::CPVRClient>(std::move(m_addonInfo));
case ADDON_AUDIODECODER:
return CAudioDecoder::FromExtension(std::move(m_addonInfo), m_extPoint);
- case ADDON_INPUTSTREAM:
- return CInputStream::FromExtension(std::move(m_addonInfo), m_extPoint);
case ADDON_PERIPHERALDLL:
return PERIPHERALS::CPeripheralAddon::FromExtension(std::move(m_addonInfo), m_extPoint);
case ADDON_GAMEDLL:
@@ -195,6 +193,7 @@ AddonPtr CAddonBuilder::FromProps(CAddonInfo addonInfo)
case ADDON_ADSPDLL:
case ADDON_AUDIOENCODER:
case ADDON_IMAGEDECODER:
+ case ADDON_INPUTSTREAM:
case ADDON_VIZ:
case ADDON_SCREENSAVER:
return AddonPtr(new CAddonDll(std::move(addonInfo)));
@@ -214,8 +213,6 @@ AddonPtr CAddonBuilder::FromProps(CAddonInfo addonInfo)
return AddonPtr(new CRepository(std::move(addonInfo)));
case ADDON_CONTEXT_ITEM:
return AddonPtr(new CContextMenuAddon(std::move(addonInfo)));
- case ADDON_INPUTSTREAM:
- return AddonPtr(new CInputStream(std::move(addonInfo)));
case ADDON_PERIPHERALDLL:
return AddonPtr(new PERIPHERALS::CPeripheralAddon(std::move(addonInfo), false, false)); //! @todo implement
case ADDON_GAME_CONTROLLER:
diff --git a/xbmc/addons/BinaryAddonCache.cpp b/xbmc/addons/BinaryAddonCache.cpp
index b46fe738a4..f8775c2916 100644
--- a/xbmc/addons/BinaryAddonCache.cpp
+++ b/xbmc/addons/BinaryAddonCache.cpp
@@ -34,7 +34,6 @@ void CBinaryAddonCache::Init()
{
m_addonsToCache = {
ADDON_AUDIODECODER,
- ADDON_INPUTSTREAM,
ADDON_PVRDLL,
ADDON_GAMEDLL,
ADDON_VFS,
diff --git a/xbmc/addons/CMakeLists.txt b/xbmc/addons/CMakeLists.txt
index 92436e558a..8145bce0de 100644
--- a/xbmc/addons/CMakeLists.txt
+++ b/xbmc/addons/CMakeLists.txt
@@ -19,7 +19,6 @@ set(SOURCES Addon.cpp
GUIWindowAddonBrowser.cpp
ImageDecoder.cpp
ImageResource.cpp
- InputStream.cpp
LanguageResource.cpp
PluginSource.cpp
PVRClient.cpp
@@ -58,7 +57,6 @@ set(HEADERS Addon.h
IAddon.h
ImageDecoder.h
ImageResource.h
- InputStream.h
LanguageResource.h
PluginSource.h
PVRClient.h
diff --git a/xbmc/addons/InputStream.cpp b/xbmc/addons/InputStream.cpp
deleted file mode 100644
index b013428f8f..0000000000
--- a/xbmc/addons/InputStream.cpp
+++ /dev/null
@@ -1,481 +0,0 @@
-/*
- * Copyright (C) 2016 Team Kodi
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-#include "InputStream.h"
-#include "URL.h"
-#include "filesystem/SpecialProtocol.h"
-#include "utils/StringUtils.h"
-#include "utils/log.h"
-#include "cores/VideoPlayer/DVDDemuxers/DVDDemux.h"
-#include "threads/SingleLock.h"
-#include "utils/RegExp.h"
-#include "utils/URIUtils.h"
-#include "utils/Variant.h"
-
-namespace ADDON
-{
-
-std::map<std::string, CInputStream::Config> CInputStream::m_configMap;
-CCriticalSection CInputStream::m_parentSection;
-
-std::unique_ptr<CInputStream> CInputStream::FromExtension(CAddonInfo addonInfo, const cp_extension_t* ext)
-{
- std::string listitemprops = CAddonMgr::GetInstance().GetExtValue(ext->configuration, "@listitemprops");
- std::string extensions = CAddonMgr::GetInstance().GetExtValue(ext->configuration, "@extension");
- std::string protocols = CAddonMgr::GetInstance().GetExtValue(ext->configuration, "@protocols");
- std::string name(ext->plugin->identifier);
- std::unique_ptr<CInputStream> istr(new CInputStream(addonInfo, name, listitemprops,
- extensions, protocols));
- if (!CAddonMgr::GetInstance().IsAddonDisabled(addonInfo.ID()))
- istr->CheckConfig();
- return istr;
-}
-
-CInputStream::CInputStream(const CAddonInfo& addonInfo,
- const std::string& name,
- const std::string& listitemprops,
- const std::string& extensions,
- const std::string& protocols)
-: CAddonDll(std::move(addonInfo))
-{
- m_fileItemProps = StringUtils::Tokenize(listitemprops, "|");
- for (auto &key : m_fileItemProps)
- {
- StringUtils::Trim(key);
- key = name + "." + key;
- }
-
- m_extensionsList = StringUtils::Tokenize(extensions, "|");
- for (auto &ext : m_extensionsList)
- {
- StringUtils::Trim(ext);
- }
-
- m_protocolsList = StringUtils::Tokenize(protocols, "|");
- for (auto &ext : m_protocolsList)
- {
- StringUtils::Trim(ext);
- }
-
- memset(&m_struct, 0, sizeof(m_struct));
- m_struct.toKodi.kodiInstance = this;
- m_struct.toKodi.AllocateDemuxPacket = cb_allocate_demux_packet;
- m_struct.toKodi.FreeDemuxPacket = cb_free_demux_packet;
-}
-
-bool CInputStream::Create()
-{
- return CAddonDll::Create(ADDON_INSTANCE_INPUTSTREAM, &m_struct, &m_struct.props) == ADDON_STATUS_OK;
-}
-
-void CInputStream::SaveSettings()
-{
- CAddon::SaveSettings();
- if (!m_bIsChild)
- UpdateConfig();
-}
-
-void CInputStream::CheckConfig()
-{
- bool hasConfig = false;
-
- {
- CSingleLock lock(m_parentSection);
- auto it = m_configMap.find(ID());
- hasConfig = it != m_configMap.end();
- }
-
- if (!m_bIsChild && !hasConfig)
- UpdateConfig();
-}
-
-void CInputStream::UpdateConfig()
-{
- std::string pathList;
- ADDON_STATUS status = CAddonDll::Create(ADDON_INSTANCE_INPUTSTREAM, &m_struct, &m_struct.props);
-
- if (status != ADDON_STATUS_PERMANENT_FAILURE)
- {
- pathList = m_struct.toAddon.GetPathList();
- Destroy();
- }
-
- Config config;
- config.m_pathList = StringUtils::Tokenize(pathList, "|");
- for (auto &path : config.m_pathList)
- {
- StringUtils::Trim(path);
- }
-
- CSingleLock lock(m_parentSection);
- auto it = m_configMap.find(ID());
- if (it == m_configMap.end())
- config.m_parentBusy = false;
- else
- config.m_parentBusy = it->second.m_parentBusy;
-
- config.m_ready = true;
- if (status == ADDON_STATUS_PERMANENT_FAILURE)
- config.m_ready = false;
-
- m_configMap[ID()] = config;
-}
-
-bool CInputStream::UseParent()
-{
- CSingleLock lock(m_parentSection);
-
- auto it = m_configMap.find(ID());
- if (it == m_configMap.end())
- return false;
- if (it->second.m_parentBusy)
- return false;
-
- it->second.m_parentBusy = true;
- return true;
-}
-
-bool CInputStream::Supports(const CFileItem &fileitem)
-{
- {
- CSingleLock lock(m_parentSection);
-
- auto it = m_configMap.find(ID());
- if (it == m_configMap.end())
- return false;
- if (!it->second.m_ready)
- return false;
- }
-
- // check if a specific inputstream addon is requested
- CVariant addon = fileitem.GetProperty("inputstreamaddon");
- if (!addon.isNull())
- {
- if (addon.asString() != ID())
- return false;
- else
- return true;
- }
-
- // check protocols
- std::string protocol = fileitem.GetURL().GetProtocol();
- if (!protocol.empty())
- {
- if (std::find(m_protocolsList.begin(),
- m_protocolsList.end(), protocol) != m_protocolsList.end())
- return true;
- }
-
- // check paths
- CSingleLock lock(m_parentSection);
- auto it = m_configMap.find(ID());
- if (it == m_configMap.end())
- return false;
-
- bool match = false;
- for (auto &path : it->second.m_pathList)
- {
- if (path.empty())
- continue;
-
- CRegExp r(true, CRegExp::asciiOnly, path.c_str());
- if (r.RegFind(fileitem.GetPath().c_str()) == 0 && r.GetFindLen() > 5)
- {
- match = true;
- break;
- }
- }
- return match;
-}
-
-bool CInputStream::Open(CFileItem &fileitem)
-{
- INPUTSTREAM props;
- std::map<std::string, std::string> propsMap;
- for (auto &key : m_fileItemProps)
- {
- if (fileitem.GetProperty(key).isNull())
- continue;
- propsMap[key] = fileitem.GetProperty(key).asString();
- }
-
- props.m_nCountInfoValues = 0;
- for (auto &pair : propsMap)
- {
- props.m_ListItemProperties[props.m_nCountInfoValues].m_strKey = pair.first.c_str();
- props.m_ListItemProperties[props.m_nCountInfoValues].m_strValue = pair.second.c_str();
- props.m_nCountInfoValues++;
- }
-
- props.m_strURL = fileitem.GetPath().c_str();
-
- std::string libFolder = URIUtils::GetDirectory(m_parentLib);
- std::string profileFolder = CSpecialProtocol::TranslatePath(Profile());
- props.m_libFolder = libFolder.c_str();
- props.m_profileFolder = profileFolder.c_str();
-
- bool ret = m_struct.toAddon.Open(props);
- if (ret)
- m_caps = m_struct.toAddon.GetCapabilities();
-
- UpdateStreams();
- return ret;
-}
-
-void CInputStream::Close()
-{
- m_struct.toAddon.Close();
-
- if (!m_bIsChild)
- {
- CSingleLock lock(m_parentSection);
- auto it = m_configMap.find(ID());
- if (it != m_configMap.end())
- it->second.m_parentBusy = false;
- }
-}
-
-// IDisplayTime
-int CInputStream::GetTotalTime()
-{
- return m_struct.toAddon.GetTotalTime();
-}
-
-int CInputStream::GetTime()
-{
- return m_struct.toAddon.GetTime();
-}
-
-// IPosTime
-bool CInputStream::PosTime(int ms)
-{
- return m_struct.toAddon.PosTime(ms);
-}
-
-// IDemux
-void CInputStream::UpdateStreams()
-{
- DisposeStreams();
-
- INPUTSTREAM_IDS streamIDs = m_struct.toAddon.GetStreamIds();
- if (streamIDs.m_streamCount > INPUTSTREAM_IDS::MAX_STREAM_COUNT)
- {
- DisposeStreams();
- return;
- }
-
- for (unsigned int i=0; i<streamIDs.m_streamCount; i++)
- {
- INPUTSTREAM_INFO stream = m_struct.toAddon.GetStream(streamIDs.m_streamIds[i]);
- if (stream.m_streamType == INPUTSTREAM_INFO::TYPE_NONE)
- continue;
-
- std::string codecName(stream.m_codecName);
- StringUtils::ToLower(codecName);
- AVCodec *codec = avcodec_find_decoder_by_name(codecName.c_str());
- if (!codec)
- continue;
-
- CDemuxStream *demuxStream;
-
- if (stream.m_streamType == INPUTSTREAM_INFO::TYPE_AUDIO)
- {
- CDemuxStreamAudio *audioStream = new CDemuxStreamAudio();
-
- audioStream->iChannels = stream.m_Channels;
- audioStream->iSampleRate = stream.m_SampleRate;
- audioStream->iBlockAlign = stream.m_BlockAlign;
- audioStream->iBitRate = stream.m_BitRate;
- audioStream->iBitsPerSample = stream.m_BitsPerSample;
- demuxStream = audioStream;
- }
- else if (stream.m_streamType == INPUTSTREAM_INFO::TYPE_VIDEO)
- {
- CDemuxStreamVideo *videoStream = new CDemuxStreamVideo();
-
- videoStream->iFpsScale = stream.m_FpsScale;
- videoStream->iFpsRate = stream.m_FpsRate;
- videoStream->iWidth = stream.m_Width;
- videoStream->iHeight = stream.m_Height;
- videoStream->fAspect = stream.m_Aspect;
- videoStream->stereo_mode = "mono";
- videoStream->iBitRate = stream.m_BitRate;
- demuxStream = videoStream;
- }
- else if (stream.m_streamType == INPUTSTREAM_INFO::TYPE_SUBTITLE)
- {
- //! @todo needs identifier in INPUTSTREAM_INFO
- continue;
- }
- else
- continue;
-
- demuxStream->codec = codec->id;
- demuxStream->codecName = stream.m_codecInternalName;
- demuxStream->uniqueId = streamIDs.m_streamIds[i];
- demuxStream->language[0] = stream.m_language[0];
- demuxStream->language[1] = stream.m_language[1];
- demuxStream->language[2] = stream.m_language[2];
- demuxStream->language[3] = stream.m_language[3];
-
- if (stream.m_ExtraData && stream.m_ExtraSize)
- {
- demuxStream->ExtraData = new uint8_t[stream.m_ExtraSize];
- demuxStream->ExtraSize = stream.m_ExtraSize;
- for (unsigned int j=0; j<stream.m_ExtraSize; j++)
- demuxStream->ExtraData[j] = stream.m_ExtraData[j];
- }
-
- m_streams[demuxStream->uniqueId] = demuxStream;
- }
-}
-
-void CInputStream::DisposeStreams()
-{
- for (auto &stream : m_streams)
- delete stream.second;
- m_streams.clear();
-}
-
-int CInputStream::GetNrOfStreams() const
-{
- return m_streams.size();
-}
-
-CDemuxStream* CInputStream::GetStream(int iStreamId)
-{
- std::map<int, CDemuxStream*>::iterator it = m_streams.find(iStreamId);
- if (it != m_streams.end())
- return it->second;
-
- return nullptr;
-}
-
-std::vector<CDemuxStream*> CInputStream::GetStreams() const
-{
- std::vector<CDemuxStream*> streams;
-
- for (auto &stream : m_streams)
- {
- streams.push_back(stream.second);
- }
-
- return streams;
-}
-
-void CInputStream::EnableStream(int iStreamId, bool enable)
-{
- std::map<int, CDemuxStream*>::iterator it = m_streams.find(iStreamId);
- if (it == m_streams.end())
- return;
-
- m_struct.toAddon.EnableStream(it->second->uniqueId, enable);
-}
-
-DemuxPacket* CInputStream::ReadDemux()
-{
- DemuxPacket* pPacket = m_struct.toAddon.DemuxRead();
-
- if (!pPacket)
- {
- return nullptr;
- }
- else if (pPacket->iStreamId == DMX_SPECIALID_STREAMINFO)
- {
- UpdateStreams();
- }
- else if (pPacket->iStreamId == DMX_SPECIALID_STREAMCHANGE)
- {
- UpdateStreams();
- }
-
- return pPacket;
-}
-
-bool CInputStream::SeekTime(double time, bool backward, double* startpts)
-{
- return m_struct.toAddon.DemuxSeekTime(time, backward, startpts);
-}
-
-void CInputStream::AbortDemux()
-{
- m_struct.toAddon.DemuxAbort();
-}
-
-void CInputStream::FlushDemux()
-{
- m_struct.toAddon.DemuxFlush();
-}
-
-void CInputStream::SetSpeed(int iSpeed)
-{
- m_struct.toAddon.DemuxSetSpeed(iSpeed);
-}
-
-int CInputStream::ReadStream(uint8_t* buf, unsigned int size)
-{
- return m_struct.toAddon.ReadStream(buf, size);
-}
-
-int64_t CInputStream::SeekStream(int64_t offset, int whence)
-{
- return m_struct.toAddon.SeekStream(offset, whence);
-}
-
-int64_t CInputStream::PositionStream()
-{
- return m_struct.toAddon.PositionStream();
-}
-
-int64_t CInputStream::LengthStream()
-{
- return m_struct.toAddon.LengthStream();
-}
-
-void CInputStream::PauseStream(double time)
-{
- m_struct.toAddon.PauseStream(time);
-}
-
-bool CInputStream::IsRealTimeStream()
-{
- return m_struct.toAddon.IsRealTimeStream();
-}
-
-void CInputStream::SetVideoResolution(int width, int height)
-{
- m_struct.toAddon.SetVideoResolution(width, height);
-}
-
-/*!
- * Callbacks from add-on to kodi
- */
-//@{
-DemuxPacket* CInputStream::cb_allocate_demux_packet(void* kodiInstance, int iDataSize)
-{
- return CDVDDemuxUtils::AllocateDemuxPacket(iDataSize);
-}
-
-void CInputStream::cb_free_demux_packet(void* kodiInstance, DemuxPacket* pPacket)
-{
- CDVDDemuxUtils::FreeDemuxPacket(pPacket);
-}
-//@}
-
-} /*namespace ADDON*/
-
diff --git a/xbmc/addons/InputStream.h b/xbmc/addons/InputStream.h
deleted file mode 100644
index 3b85860c45..0000000000
--- a/xbmc/addons/InputStream.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2016 Team Kodi
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-#pragma once
-
-#include "addons/binary-addons/AddonDll.h"
-#include "addons/kodi-addon-dev-kit/include/kodi/kodi_inputstream_types.h"
-#include "FileItem.h"
-#include "cores/VideoPlayer/DVDDemuxers/DVDDemuxUtils.h"
-#include "threads/CriticalSection.h"
-#include <vector>
-#include <map>
-
-class CDemuxStream;
-
-namespace ADDON
-{
-
- class CInputStream : public CAddonDll
- {
- public:
-
- static std::unique_ptr<CInputStream> FromExtension(CAddonInfo addonInfo, const cp_extension_t* ext);
-
- explicit CInputStream(CAddonInfo addonInfo)
- : CAddonDll(std::move(addonInfo))
- {};
- CInputStream(const CAddonInfo& addonInfo,
- const std::string& name,
- const std::string& listitemprops,
- const std::string& extensions,
- const std::string& protocols);
- virtual ~CInputStream() {}
-
- virtual void SaveSettings() override;
-
- bool Create();
-
- bool UseParent();
- bool Supports(const CFileItem &fileitem);
- bool Open(CFileItem &fileitem);
- void Close();
-
- bool HasDemux() { return m_caps.m_supportsIDemux; };
- bool HasPosTime() { return m_caps.m_supportsIPosTime; };
- bool HasDisplayTime() { return m_caps.m_supportsIDisplayTime; };
- bool CanPause() { return m_caps.m_supportsPause; };
- bool CanSeek() { return m_caps.m_supportsSeek; };
-
- // IDisplayTime
- int GetTotalTime();
- int GetTime();
-
- // IPosTime
- bool PosTime(int ms);
-
- // demux
- int GetNrOfStreams() const;
- CDemuxStream* GetStream(int iStreamId);
- std::vector<CDemuxStream*> GetStreams() const;
- DemuxPacket* ReadDemux();
- bool SeekTime(double time, bool backward, double* startpts);
- void AbortDemux();
- void FlushDemux();
- void SetSpeed(int iSpeed);
- void EnableStream(int iStreamId, bool enable);
- void SetVideoResolution(int width, int height);
-
- // stream
- int ReadStream(uint8_t* buf, unsigned int size);
- int64_t SeekStream(int64_t offset, int whence);
- int64_t PositionStream();
- int64_t LengthStream();
- void PauseStream(double time);
- bool IsRealTimeStream();
-
- /*!
- * @brief To get the interface table used between addon and kodi
- * @todo This function becomes removed after old callback library system
- * is removed.
- */
- AddonInstance_InputStream* GetInstanceInterface() { return &m_struct; }
-
- protected:
- void UpdateStreams();
- void DisposeStreams();
- void UpdateConfig();
- void CheckConfig();
-
- std::vector<std::string> m_fileItemProps;
- std::vector<std::string> m_extensionsList;
- std::vector<std::string> m_protocolsList;
- INPUTSTREAM_CAPABILITIES m_caps;
- std::map<int, CDemuxStream*> m_streams;
-
- static CCriticalSection m_parentSection;
-
- struct Config
- {
- std::vector<std::string> m_pathList;
- bool m_parentBusy;
- bool m_ready;
- };
- static std::map<std::string, Config> m_configMap;
-
- private:
- /*!
- * @brief Callback functions from addon to kodi
- */
- //@{
- /*!
- * @brief Allocate a demux packet. Free with FreeDemuxPacket
- * @param kodiInstance A pointer to the add-on.
- * @param iDataSize The size of the data that will go into the packet
- * @return The allocated packet.
- */
- static DemuxPacket* cb_allocate_demux_packet(void* kodiInstance, int iDataSize = 0);
-
- /*!
- * @brief Free a packet that was allocated with AllocateDemuxPacket
- * @param kodiInstance A pointer to the add-on.
- * @param pPacket The packet to free.
- */
- static void cb_free_demux_packet(void* kodiInstance, DemuxPacket* pPacket);
- //@}
-
- AddonInstance_InputStream m_struct;
- };
-
-} /*namespace ADDON*/
diff --git a/xbmc/addons/interfaces/AddonInterfaces.cpp b/xbmc/addons/interfaces/AddonInterfaces.cpp
index 5f664810da..1d52b2ecf2 100644
--- a/xbmc/addons/interfaces/AddonInterfaces.cpp
+++ b/xbmc/addons/interfaces/AddonInterfaces.cpp
@@ -22,7 +22,6 @@
#include "AddonInterfaces.h"
#include "addons/Addon.h"
-#include "addons/InputStream.h"
#include "addons/PVRClient.h"
#include "games/addons/GameClient.h"
@@ -56,8 +55,6 @@ CAddonInterfaces::CAddonInterfaces(CAddon* addon)
m_callbacks->GUILib_UnRegisterMe = CAddonInterfaces::GUILib_UnRegisterMe;
m_callbacks->PVRLib_RegisterMe = CAddonInterfaces::PVRLib_RegisterMe;
m_callbacks->PVRLib_UnRegisterMe = CAddonInterfaces::PVRLib_UnRegisterMe;
- m_callbacks->INPUTSTREAMLib_RegisterMe = CAddonInterfaces::INPUTSTREAMLib_RegisterMe;
- m_callbacks->INPUTSTREAMLib_UnRegisterMe = CAddonInterfaces::INPUTSTREAMLib_UnRegisterMe;
m_callbacks->PeripheralLib_RegisterMe = CAddonInterfaces::PeripheralLib_RegisterMe;
m_callbacks->PeripheralLib_UnRegisterMe = CAddonInterfaces::PeripheralLib_UnRegisterMe;
m_callbacks->GameLib_RegisterMe = CAddonInterfaces::GameLib_RegisterMe;
@@ -164,23 +161,6 @@ void CAddonInterfaces::GameLib_UnRegisterMe(void *addonData, void *cbTable)
}
/*\_____________________________________________________________________________
\*/
-void* CAddonInterfaces::INPUTSTREAMLib_RegisterMe(void *addonData)
-{
- CAddonInterfaces* addon = static_cast<CAddonInterfaces*>(addonData);
- if (addon == nullptr)
- {
- CLog::Log(LOGERROR, "CAddonInterfaces - %s - called with a null pointer", __FUNCTION__);
- return nullptr;
- }
-
- return dynamic_cast<ADDON::CInputStream*>(addon->m_addon)->GetInstanceInterface();
-}
-
-void CAddonInterfaces::INPUTSTREAMLib_UnRegisterMe(void *addonData, void* cbTable)
-{
-}
-/*\_____________________________________________________________________________
-\*/
void* CAddonInterfaces::PeripheralLib_RegisterMe(void *addonData)
{
CAddonInterfaces* addon = static_cast<CAddonInterfaces*>(addonData);
diff --git a/xbmc/addons/interfaces/AddonInterfaces.h b/xbmc/addons/interfaces/AddonInterfaces.h
index 63465141a9..b8db5dd678 100644
--- a/xbmc/addons/interfaces/AddonInterfaces.h
+++ b/xbmc/addons/interfaces/AddonInterfaces.h
@@ -62,10 +62,6 @@ namespace ADDON
static void PVRLib_UnRegisterMe (void* addonData, void* cbTable);
/*\_________________________________________________________________________
\*/
- static void* INPUTSTREAMLib_RegisterMe (void *addonData);
- static void INPUTSTREAMLib_UnRegisterMe (void *addonData, void* cbTable);
- /*\_________________________________________________________________________
- \*/
static void* PeripheralLib_RegisterMe (void *addonData);
static void PeripheralLib_UnRegisterMe (void *addonData, void* cbTable);
/*\_________________________________________________________________________
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
new file mode 100644
index 0000000000..bdb80bb742
--- /dev/null
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h
@@ -0,0 +1,585 @@
+#pragma once
+/*
+ * Copyright (C) 2005-2017 Team Kodi
+ * http://kodi.tv
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Kodi; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+ * Parts with a comment named "internal" are only used inside header and not
+ * used or accessed direct during add-on development!
+ */
+
+#include "../AddonBase.h"
+
+#ifdef BUILD_KODI_ADDON
+#include "../DVDDemuxPacket.h"
+#else
+#include "cores/VideoPlayer/DVDDemuxers/DVDDemuxPacket.h"
+#endif
+
+namespace kodi { namespace addon { class CInstanceInputStream; }}
+
+extern "C" {
+
+ /*!
+ * @brief InputStream add-on capabilities. All capabilities are set to "false" as default.
+ */
+ typedef 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)
+ };
+
+ /// set of supported capabilities
+ uint32_t m_mask;
+ } INPUTSTREAM_CAPABILITIES;
+
+ /*!
+ * @brief structure of key/value pairs passed to addon on Open()
+ */
+ typedef struct INPUTSTREAM
+ {
+ static const unsigned int MAX_INFO_COUNT = 8;
+
+ const char *m_strURL;
+
+ unsigned int m_nCountInfoValues;
+ struct LISTITEMPROPERTY
+ {
+ const char *m_strKey;
+ const char *m_strValue;
+ } m_ListItemProperties[MAX_INFO_COUNT];
+
+ const char *m_libFolder;
+ const char *m_profileFolder;
+ } INPUTSTREAM;
+
+ /*!
+ * @brief Array of stream IDs
+ */
+ typedef struct INPUTSTREAM_IDS
+ {
+ static const unsigned int MAX_STREAM_COUNT = 32;
+ unsigned int m_streamCount;
+ unsigned int m_streamIds[MAX_STREAM_COUNT];
+ } INPUTSTREAM_IDS;
+
+ /*!
+ * @brief stream properties
+ */
+ typedef struct INPUTSTREAM_INFO
+ {
+ enum STREAM_TYPE
+ {
+ TYPE_NONE,
+ TYPE_VIDEO,
+ TYPE_AUDIO,
+ TYPE_SUBTITLE,
+ TYPE_TELETEXT
+ } m_streamType;
+
+ char m_codecName[32]; /*!< @brief (required) name of codec according to ffmpeg */
+ char m_codecInternalName[32]; /*!< @brief (optional) internal name of codec (selectionstream info) */
+ unsigned int m_pID; /*!< @brief (required) physical index */
+
+ const uint8_t *m_ExtraData;
+ unsigned int m_ExtraSize;
+
+ char m_language[4]; /*!< @brief ISO 639 3-letter 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_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_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;
+ } INPUTSTREAM_INFO;
+
+ /*!
+ * @brief Structure to transfer the methods from xbmc_inputstream_dll.h to XBMC
+ */
+
+ // 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);
+ void (*free_demux_packet)(void* kodiInstance, DemuxPacket* packet);
+ } AddonToKodiFuncTable_InputStream;
+
+ struct AddonInstance_InputStream;
+ typedef struct KodiToAddonFuncTable_InputStream /* internal */
+ {
+ kodi::addon::CInstanceInputStream* 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);
+ 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);
+
+ // 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);
+ } KodiToAddonFuncTable_InputStream;
+
+ typedef struct AddonInstance_InputStream /* internal */
+ {
+ AddonProps_InputStream props;
+ AddonToKodiFuncTable_InputStream toKodi;
+ KodiToAddonFuncTable_InputStream toAddon;
+ } AddonInstance_InputStream;
+
+} /* extern "C" */
+
+namespace kodi
+{
+namespace addon
+{
+
+ class CInstanceInputStream : public IAddonInstance
+ {
+ public:
+ 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!");
+
+ SetAddonStruct(instance);
+ }
+
+ virtual ~CInstanceInputStream() = 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() { return INPUTSTREAM_IDS(); }
+
+ /*!
+ * Get stream properties of a stream.
+ * @param streamid unique id of stream
+ * @return struc of stream properties
+ * @remarks
+ */
+ virtual INPUTSTREAM_INFO GetStream(int streamid) { return INPUTSTREAM_INFO(); }
+
+ /*!
+ * 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) { }
+
+ /*!
+ * 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 occured.
+ * @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; }
+
+ /*!
+ * Positions inputstream to playing time given in ms
+ * @remarks
+ */
+ virtual bool PosTime(int ms) { return false; }
+
+
+ /*!
+ * 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; }
+
+ /*!
+ * 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; }
+
+ /*!
+ * 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; }
+
+
+ /*!
+ * @brief Notify the InputStream addon that Kodi (un)paused the currently playing stream
+ */
+ virtual void PauseStream(double time) { }
+
+
+ /*!
+ * 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 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:
+ 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<AddonInstance_InputStream*>(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.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.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;
+ }
+
+ inline static bool ADDON_Open(const AddonInstance_InputStream* instance, INPUTSTREAM* props)
+ {
+ return instance->toAddon.addonInstance->Open(*props);
+ }
+
+ inline static void ADDON_Close(const AddonInstance_InputStream* instance)
+ {
+ instance->toAddon.addonInstance->Close();
+ }
+
+ inline static void ADDON_GetCapabilities(const AddonInstance_InputStream* instance, INPUTSTREAM_CAPABILITIES* capabilities)
+ {
+ instance->toAddon.addonInstance->GetCapabilities(*capabilities);
+ }
+
+
+ // IDemux
+ inline static struct INPUTSTREAM_IDS ADDON_GetStreamIds(const AddonInstance_InputStream* instance)
+ {
+ return instance->toAddon.addonInstance->GetStreamIds();
+ }
+
+ 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);
+ }
+
+ inline static void ADDON_DemuxReset(const AddonInstance_InputStream* instance)
+ {
+ instance->toAddon.addonInstance->DemuxReset();
+ }
+
+ inline static void ADDON_DemuxAbort(const AddonInstance_InputStream* instance)
+ {
+ instance->toAddon.addonInstance->DemuxAbort();
+ }
+
+ inline static void ADDON_DemuxFlush(const AddonInstance_InputStream* instance)
+ {
+ instance->toAddon.addonInstance->DemuxFlush();
+ }
+
+ inline static DemuxPacket* ADDON_DemuxRead(const AddonInstance_InputStream* instance)
+ {
+ return instance->toAddon.addonInstance->DemuxRead();
+ }
+
+ 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_DemuxSetSpeed(const AddonInstance_InputStream* instance, int speed)
+ {
+ instance->toAddon.addonInstance->DemuxSetSpeed(speed);
+ }
+
+ inline static void ADDON_SetVideoResolution(const AddonInstance_InputStream* instance, int width, int height)
+ {
+ instance->toAddon.addonInstance->SetVideoResolution(width, height);
+ }
+
+
+ // IDisplayTime
+ inline static int ADDON_GetTotalTime(const AddonInstance_InputStream* instance)
+ {
+ return instance->toAddon.addonInstance->GetTotalTime();
+ }
+
+ inline static int ADDON_GetTime(const AddonInstance_InputStream* instance)
+ {
+ return instance->toAddon.addonInstance->GetTime();
+ }
+
+
+ // IPosTime
+ inline static bool ADDON_PosTime(const AddonInstance_InputStream* instance, int ms)
+ {
+ return instance->toAddon.addonInstance->PosTime(ms);
+ }
+
+ // Seekable (mandatory)
+ inline static bool ADDON_CanPauseStream(const AddonInstance_InputStream* instance)
+ {
+ return instance->toAddon.addonInstance->CanPauseStream();
+ }
+
+ inline static bool ADDON_CanSeekStream(const AddonInstance_InputStream* instance)
+ {
+ return instance->toAddon.addonInstance->CanSeekStream();
+ }
+
+
+ inline static int ADDON_ReadStream(const AddonInstance_InputStream* instance, uint8_t* buffer, unsigned int bufferSize)
+ {
+ return instance->toAddon.addonInstance->ReadStream(buffer, bufferSize);
+ }
+
+ inline static int64_t ADDON_SeekStream(const AddonInstance_InputStream* instance, int64_t position, int whence)
+ {
+ return instance->toAddon.addonInstance->SeekStream(position, whence);
+ }
+
+ inline static int64_t ADDON_PositionStream(const AddonInstance_InputStream* instance)
+ {
+ return instance->toAddon.addonInstance->PositionStream();
+ }
+
+ inline static int64_t ADDON_LengthStream(const AddonInstance_InputStream* instance)
+ {
+ return instance->toAddon.addonInstance->LengthStream();
+ }
+
+ inline static void ADDON_PauseStream(const AddonInstance_InputStream* instance, double time)
+ {
+ instance->toAddon.addonInstance->PauseStream(time);
+ }
+
+ inline static bool ADDON_IsRealTimeStream(const AddonInstance_InputStream* instance)
+ {
+ return instance->toAddon.addonInstance->IsRealTimeStream();
+ }
+
+ AddonInstance_InputStream* m_instanceData;
+ };
+
+} /* namespace addon */
+} /* namespace kodi */
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_inputstream_dll.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_inputstream_dll.h
deleted file mode 100644
index ab8475d9bb..0000000000
--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_inputstream_dll.h
+++ /dev/null
@@ -1,256 +0,0 @@
-#pragma once
-
-/*
-* Copyright (C) 2005-2016 Team Kodi
-* http://kodi.tv
-*
-* This Program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2, or (at your option)
-* any later version.
-*
-* This Program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with Kodi; see the file COPYING. If not, see
-* <http://www.gnu.org/licenses/>.
-*
-*/
-
-#include "kodi_inputstream_types.h"
-#include "xbmc_addon_dll.h"
-
-/*!
-* Functions that the InputStream client add-on must implement, but some can be empty.
-*
-* The 'remarks' field indicates which methods should be implemented, and which ones are optional.
-*/
-
-extern "C"
-{
- /*!
- * Open a stream.
- * @param props
- * @return True if the stream has been opened successfully, false otherwise.
- * @remarks
- */
- bool Open(INPUTSTREAM& props);
-
- /*!
- * Close an open stream.
- * @remarks
- */
- void Close(void);
-
- /*!
- * Get path/url for this addon.
- * @remarks
- */
- const char* GetPathList(void);
-
- /*!
- * Get Capabilities of this addon.
- * @remarks
- */
- struct INPUTSTREAM_CAPABILITIES GetCapabilities();
-
-
- /*!
- * Get IDs of available streams
- * @remarks
- */
- INPUTSTREAM_IDS GetStreamIds();
-
- /*!
- * Get stream properties of a stream.
- * @param streamId unique id of stream
- * @return struc of stream properties
- * @remarks
- */
- INPUTSTREAM_INFO GetStream(int streamid);
-
- /*!
- * 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
- */
- void EnableStream(int streamid, bool enable);
-
- /*!
- * Reset the demultiplexer in the add-on.
- * @remarks Required if bHandlesDemuxing is set to true.
- */
- void DemuxReset(void);
-
- /*!
- * Abort the demultiplexer thread in the add-on.
- * @remarks Required if bHandlesDemuxing is set to true.
- */
- void DemuxAbort(void);
-
- /*!
- * Flush all data that's currently in the demultiplexer buffer in the add-on.
- * @remarks Required if bHandlesDemuxing is set to true.
- */
- void DemuxFlush(void);
-
- /*!
- * 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 XBMC'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 occured.
- * @remarks Return NULL if this add-on won't provide this function.
- */
- DemuxPacket* DemuxRead(void);
-
- /*!
- * Notify the InputStream addon/demuxer that XBMC 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.
- */
- bool DemuxSeekTime(double time, bool backwards, double *startpts);
-
- /*!
- * Notify the InputStream addon/demuxer that XBMC wishes to change playback speed
- * @param speed The requested playback speed
- * @remarks Optional, and only used if addon has its own demuxer.
- */
- void DemuxSetSpeed(int speed);
-
- /*!
- * Sets desired width / height
- * @param width / hight
- */
- void SetVideoResolution(int width, int height);
-
- /*!
- * Totel time in ms
- * @remarks
- */
- int GetTotalTime();
-
- /*!
- * Playing time in ms
- * @remarks
- */
- int GetTime();
-
- /*!
- * Positions inputstream to playing time given in ms
- * @remarks
- */
- bool PosTime(int ms);
-
-
- /*!
- * Check if the backend support pausing the currently playing stream
- * This will enable/disable the pause button in XBMC based on the return value
- * @return false if the InputStream addon/backend does not support pausing, true if possible
- */
- bool CanPauseStream();
-
- /*!
- * Check if the backend supports seeking for the currently playing stream
- * This will enable/disable the rewind/forward buttons in XBMC based on the return value
- * @return false if the InputStream addon/backend does not support seeking, true if possible
- */
- bool CanSeekStream();
-
-
- /*!
- * Read from an open stream.
- * @param pBuffer The buffer to store the data in.
- * @param iBufferSize 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.
- */
- int ReadStream(uint8_t* pBuffer, unsigned int iBufferSize);
-
- /*!
- * Seek in a stream.
- * @param iPosition The position to seek to.
- * @param iWhence ?
- * @return The new position.
- * @remarks Return -1 if this add-on won't provide this function.
- */
- int64_t SeekStream(int64_t iPosition, int iWhence = SEEK_SET);
-
- /*!
- * @return The position in the stream that's currently being read.
- * @remarks Return -1 if this add-on won't provide this function.
- */
- int64_t PositionStream(void);
-
- /*!
- * @return The total length of the stream that's currently being read.
- * @remarks Return -1 if this add-on won't provide this function.
- */
- int64_t LengthStream(void);
-
-
- /*!
- * @brief Notify the InputStream addon that XBMC (un)paused the currently playing stream
- */
- void PauseStream(double time);
-
-
- /*!
- * Check for real-time streaming
- * @return true if current stream is real-time
- */
- bool IsRealTimeStream();
-
- /*!
- * Called by XBMC to assign the function pointers of this add-on to pClient.
- * @param pClient The struct to assign the function pointers to.
- */
- void __declspec(dllexport) get_addon(void* ptr)
- {
- AddonInstance_InputStream* pClient = static_cast<AddonInstance_InputStream*>(ptr);
-
- pClient->toAddon.Open = Open;
- pClient->toAddon.Close = Close;
- pClient->toAddon.GetPathList = GetPathList;
- pClient->toAddon.GetCapabilities = GetCapabilities;
-
- pClient->toAddon.GetStreamIds = GetStreamIds;
- pClient->toAddon.GetStream = GetStream;
- pClient->toAddon.EnableStream = EnableStream;
- pClient->toAddon.DemuxReset = DemuxReset;
- pClient->toAddon.DemuxAbort = DemuxAbort;
- pClient->toAddon.DemuxFlush = DemuxFlush;
- pClient->toAddon.DemuxRead = DemuxRead;
- pClient->toAddon.DemuxSeekTime = DemuxSeekTime;
- pClient->toAddon.DemuxSetSpeed = DemuxSetSpeed;
- pClient->toAddon.SetVideoResolution = SetVideoResolution;
-
- pClient->toAddon.GetTotalTime = GetTotalTime;
- pClient->toAddon.GetTime = GetTime;
-
- pClient->toAddon.PosTime = PosTime;
-
- pClient->toAddon.CanPauseStream = CanPauseStream;
- pClient->toAddon.CanSeekStream = CanSeekStream;
-
- pClient->toAddon.ReadStream = ReadStream;
- pClient->toAddon.SeekStream = SeekStream;
- pClient->toAddon.PositionStream = PositionStream;
- pClient->toAddon.LengthStream = LengthStream;
- pClient->toAddon.PauseStream = PauseStream;
- pClient->toAddon.IsRealTimeStream = IsRealTimeStream;
- };
-};
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_inputstream_types.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_inputstream_types.h
deleted file mode 100644
index 9597e8a5fc..0000000000
--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/kodi_inputstream_types.h
+++ /dev/null
@@ -1,187 +0,0 @@
-#pragma once
-
-/*
- * Copyright (C) 2005-2016 Team Kodi
- * http://kodi.tv
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Kodi; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef TARGET_WINDOWS
-#ifndef __cdecl
-#define __cdecl
-#endif
-#ifndef __declspec
-#define __declspec(X)
-#endif
-#endif
-
-#include "xbmc_addon_types.h"
-
-#ifdef BUILD_KODI_ADDON
-#include "DVDDemuxPacket.h"
-#else
-#include "cores/VideoPlayer/DVDDemuxers/DVDDemuxPacket.h"
-#endif
-
-extern "C" {
-
- /*!
- * @brief InputStream add-on capabilities. All capabilities are set to "false" as default.
- */
- typedef struct INPUTSTREAM_CAPABILITIES
- {
- bool m_supportsIDemux; /*!< @brief supports interface IDemux */
- bool m_supportsIPosTime; /*!< @brief supports interface IPosTime */
- bool m_supportsIDisplayTime; /*!< @brief supports interface IDisplayTime */
- bool m_supportsSeek; /*!< @brief supports seek */
- bool m_supportsPause; /*!< @brief supports pause */
- } INPUTSTREAM_CAPABILITIES;
-
- /*!
- * @brief structure of key/value pairs passed to addon on Open()
- */
- typedef struct INPUTSTREAM
- {
- static const unsigned int MAX_INFO_COUNT = 8;
-
- const char *m_strURL;
-
- unsigned int m_nCountInfoValues;
- struct LISTITEMPROPERTY
- {
- const char *m_strKey;
- const char *m_strValue;
- } m_ListItemProperties[MAX_INFO_COUNT];
-
- const char *m_libFolder;
- const char *m_profileFolder;
- } INPUTSTREAM;
-
- /*!
- * @brief Array of stream IDs
- */
- typedef struct INPUTSTREAM_IDS
- {
- static const unsigned int MAX_STREAM_COUNT = 32;
- unsigned int m_streamCount;
- unsigned int m_streamIds[MAX_STREAM_COUNT];
- } INPUTSTREAM_IDS;
-
- /*!
- * @brief stream properties
- */
- typedef struct INPUTSTREAM_INFO
- {
- enum STREAM_TYPE
- {
- TYPE_NONE,
- TYPE_VIDEO,
- TYPE_AUDIO,
- TYPE_SUBTITLE,
- TYPE_TELETEXT
- } m_streamType;
-
- char m_codecName[32]; /*!< @brief (required) name of codec according to ffmpeg */
- char m_codecInternalName[32]; /*!< @brief (optional) internal name of codec (selectionstream info) */
- unsigned int m_pID; /*!< @brief (required) physical index */
-
- const uint8_t *m_ExtraData;
- unsigned int m_ExtraSize;
-
- char m_language[4]; /*!< @brief ISO 639 3-letter 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_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_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;
- } INPUTSTREAM_INFO;
-
- /*!
- * @brief Structure to transfer the methods from xbmc_inputstream_dll.h to XBMC
- */
-
- // this are properties given to the addon on create
- // at this time we have no parameters for the addon
- typedef struct AddonProps_InputStream
- {
- int dummy;
- } AddonProps_InputStream;
-
- typedef AddonProps_InputStream INPUTSTREAM_PROPS;
-
- typedef struct AddonToKodiFuncTable_InputStream
- {
- KODI_HANDLE kodiInstance;
- DemuxPacket* (*AllocateDemuxPacket)(void* kodiInstance, int iDataSize);
- void (*FreeDemuxPacket)(void* kodiInstance, DemuxPacket* pPacket);
- } AddonToKodiFuncTable_InputStream;
-
- typedef struct KodiToAddonFuncTable_InputStream
- {
- bool (__cdecl* Open)(INPUTSTREAM&);
- void (__cdecl* Close)(void);
- const char* (__cdecl* GetPathList)(void);
- struct INPUTSTREAM_CAPABILITIES (__cdecl* GetCapabilities)(void);
-
- // IDemux
- struct INPUTSTREAM_IDS (__cdecl* GetStreamIds)();
- struct INPUTSTREAM_INFO (__cdecl* GetStream)(int);
- void (__cdecl* EnableStream)(int, bool);
- void (__cdecl* DemuxReset)(void);
- void (__cdecl* DemuxAbort)(void);
- void (__cdecl* DemuxFlush)(void);
- DemuxPacket* (__cdecl* DemuxRead)(void);
- bool (__cdecl* DemuxSeekTime)(double, bool, double*);
- void (__cdecl* DemuxSetSpeed)(int);
- void (__cdecl* SetVideoResolution)(int, int);
-
- // IDisplayTime
- int (__cdecl* GetTotalTime)(void);
- int (__cdecl* GetTime)(void);
-
- // IPosTime
- bool (__cdecl* PosTime)(int);
-
- // Seekable (mandatory)
- bool (__cdecl* CanPauseStream)(void);
- bool (__cdecl* CanSeekStream)(void);
-
- int (__cdecl* ReadStream)(uint8_t*, unsigned int);
- int64_t(__cdecl* SeekStream)(int64_t, int);
- int64_t (__cdecl* PositionStream)(void);
- int64_t (__cdecl* LengthStream)(void);
- void (__cdecl* PauseStream)(double);
- bool (__cdecl* IsRealTimeStream)(void);
- } KodiToAddonFuncTable_InputStream;
-
- typedef struct AddonInstance_InputStream
- {
- AddonProps_InputStream props;
- AddonToKodiFuncTable_InputStream toKodi;
- KodiToAddonFuncTable_InputStream toAddon;
- } AddonInstance_InputStream;
-
-}
-
-
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_inputstream.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_inputstream.h
deleted file mode 100644
index d37d24ef6f..0000000000
--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/libKODI_inputstream.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2005-2016 Team XBMC
- * http://www.xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#pragma once
-
-#include <string>
-#include <vector>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "kodi_inputstream_types.h"
-#include "versions.h"
-
-#ifdef BUILD_KODI_ADDON
-#include "DVDDemuxPacket.h"
-#else
-#include "cores/VideoPlayer/DVDDemuxers/DVDDemuxPacket.h"
-#endif
-
-class CHelper_libKODI_inputstream
-{
-public:
- CHelper_libKODI_inputstream(void)
- {
- m_Handle = nullptr;
- m_Callbacks = nullptr;
- }
-
- ~CHelper_libKODI_inputstream(void)
- {
- }
-
- /*!
- * @brief Resolve all callback methods
- * @param handle Pointer to the add-on
- * @return True when all methods were resolved, false otherwise.
- */
- bool RegisterMe(void* handle)
- {
- m_Handle = static_cast<AddonCB*>(handle);
- if (m_Handle)
- m_Callbacks = (AddonInstance_InputStream*)m_Handle->INPUTSTREAMLib_RegisterMe(m_Handle->addonData);
- if (!m_Callbacks)
- fprintf(stderr, "libKODI_inputstream-ERROR: InputStream_RegisterMe can't get callback table from Kodi !!!\n");
-
- return m_Callbacks != nullptr;
- }
-
- /*!
- * @brief Allocate a demux packet. Free with FreeDemuxPacket
- * @param iDataSize The size of the data that will go into the packet
- * @return The allocated packet
- */
- DemuxPacket* AllocateDemuxPacket(int iDataSize)
- {
- return m_Callbacks->toKodi.AllocateDemuxPacket(m_Callbacks->toKodi.kodiInstance, iDataSize);
- }
-
- /*!
- * @brief Free a packet that was allocated with AllocateDemuxPacket
- * @param pPacket The packet to free
- */
- void FreeDemuxPacket(DemuxPacket* pPacket)
- {
- return m_Callbacks->toKodi.FreeDemuxPacket(m_Callbacks->toKodi.kodiInstance, pPacket);
- }
-
-private:
- AddonCB* m_Handle;
- AddonInstance_InputStream* m_Callbacks;
-};
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h
index e3ffd1965e..34c2861a99 100644
--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h
@@ -103,12 +103,10 @@
#define ADDON_INSTANCE_VERSION_IMAGEDECODER_XML_ID "kodi.binary.instance.imagedecoder"
#define ADDON_INSTANCE_VERSION_IMAGEDECODER_DEPENDS "addon-instance/ImageDecoder.h"
-#define ADDON_INSTANCE_VERSION_INPUTSTREAM "1.0.8"
-#define ADDON_INSTANCE_VERSION_INPUTSTREAM_MIN "1.0.8"
+#define ADDON_INSTANCE_VERSION_INPUTSTREAM "2.0.0"
+#define ADDON_INSTANCE_VERSION_INPUTSTREAM_MIN "2.0.0"
#define ADDON_INSTANCE_VERSION_INPUTSTREAM_XML_ID "kodi.binary.instance.inputstream"
-#define ADDON_INSTANCE_VERSION_INPUTSTREAM_DEPENDS "libKODI_inputstream.h" \
- "kodi_inputstream_dll.h" \
- "kodi_inputstream_types.h"
+#define ADDON_INSTANCE_VERSION_INPUTSTREAM_DEPENDS "addon-instance/Inputstream.h"
#define ADDON_INSTANCE_VERSION_PERIPHERAL "1.3.3"
#define ADDON_INSTANCE_VERSION_PERIPHERAL_MIN "1.3.3"
diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp
index 08da796bb1..17113b8e9a 100644
--- a/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp
+++ b/xbmc/cores/VideoPlayer/DVDInputStreams/DVDFactoryInputStream.cpp
@@ -40,13 +40,14 @@
#include "filesystem/File.h"
#include "utils/URIUtils.h"
#include "ServiceBroker.h"
-#include "addons/InputStream.h"
-#include "addons/BinaryAddonCache.h"
+#include "addons/binary-addons/BinaryAddonManager.h"
#include "Util.h"
CDVDInputStream* CDVDFactoryInputStream::CreateInputStream(IVideoPlayer* pPlayer, const CFileItem &fileitem, bool scanforextaudio)
{
+ using namespace ADDON;
+
std::string file = fileitem.GetPath();
if (scanforextaudio)
{
@@ -61,28 +62,12 @@ CDVDInputStream* CDVDFactoryInputStream::CreateInputStream(IVideoPlayer* pPlayer
}
}
- ADDON::VECADDONS addons;
- ADDON::CBinaryAddonCache &addonCache = CServiceBroker::GetBinaryAddonCache();
- addonCache.GetAddons(addons, ADDON::ADDON_INPUTSTREAM);
- for (size_t i=0; i<addons.size(); ++i)
+ BinaryAddonBaseList addonInfos;
+ CServiceBroker::GetBinaryAddonManager().GetAddonInfos(addonInfos, true /*enabled only*/, ADDON_INPUTSTREAM);
+ for (auto addonInfo : addonInfos)
{
- std::shared_ptr<ADDON::CInputStream> input(std::static_pointer_cast<ADDON::CInputStream>(addons[i]));
-
- if (input->Supports(fileitem))
- {
- std::shared_ptr<ADDON::CInputStream> addon = input;
- if (!input->UseParent())
- addon = std::shared_ptr<ADDON::CInputStream>(new ADDON::CInputStream(*input));
-
- if (addon->Create())
- {
- unsigned int videoWidth, videoHeight;
- pPlayer->GetVideoResolution(videoWidth, videoHeight);
- addon->SetVideoResolution(videoWidth, videoHeight);
-
- return new CInputStreamAddon(fileitem, addon);
- }
- }
+ if (CInputStreamAddon::Supports(addonInfo, fileitem))
+ return new CInputStreamAddon(addonInfo, pPlayer, fileitem);
}
if (fileitem.IsDiscImage())
diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp
index 420190341c..05066127a0 100644
--- a/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp
+++ b/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp
@@ -20,40 +20,138 @@
#include "InputStreamAddon.h"
#include "TimingConstants.h"
-#include "addons/InputStream.h"
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/binary-addons/BinaryAddonBase.h"
#include "cores/VideoPlayer/DVDClock.h"
-
-CInputStreamAddon::CInputStreamAddon(const CFileItem& fileitem, std::shared_ptr<ADDON::CInputStream> inputStream)
-: CDVDInputStream(DVDSTREAM_TYPE_ADDON, fileitem), m_addon(inputStream)
+#include "cores/VideoPlayer/DVDDemuxers/DVDDemux.h"
+#include "cores/VideoPlayer/DVDDemuxers/DVDDemuxUtils.h"
+#include "filesystem/SpecialProtocol.h"
+#include "utils/StringUtils.h"
+#include "utils/URIUtils.h"
+
+using namespace ADDON;
+
+CInputStreamAddon::CInputStreamAddon(BinaryAddonBasePtr& addonBase, IVideoPlayer* player, const CFileItem& fileitem)
+ : IAddonInstanceHandler(ADDON_INSTANCE_INPUTSTREAM, addonBase),
+ CDVDInputStream(DVDSTREAM_TYPE_ADDON, fileitem),
+ m_player(player)
{
+ std::string listitemprops = addonBase->Type(ADDON_INPUTSTREAM)->GetValue("@listitemprops").asString();
+ std::string name(addonBase->ID());
+
+ m_fileItemProps = StringUtils::Tokenize(listitemprops, "|");
+ for (auto &key : m_fileItemProps)
+ {
+ StringUtils::Trim(key);
+ key = name + "." + key;
+ }
+
+ m_struct = {{ 0 }};
}
CInputStreamAddon::~CInputStreamAddon()
{
Close();
- m_addon.reset();
+}
+
+bool CInputStreamAddon::Supports(BinaryAddonBasePtr& addonBase, const CFileItem &fileitem)
+{
+ // check if a specific inputstream addon is requested
+ CVariant addon = fileitem.GetProperty("inputstreamaddon");
+ if (!addon.isNull())
+ return (addon.asString() == addonBase->ID());
+
+ // check protocols
+ std::string protocol = fileitem.GetURL().GetProtocol();
+ if (!protocol.empty())
+ {
+ std::string protocols = addonBase->Type(ADDON_INPUTSTREAM)->GetValue("@protocols").asString();
+ if (!protocols.empty())
+ {
+ std::vector<std::string> protocolsList = StringUtils::Tokenize(protocols, "|");
+ for (auto& value : protocolsList)
+ {
+ StringUtils::Trim(value);
+ if (value == protocol)
+ return true;
+ }
+ }
+ }
+
+ std::string filetype = fileitem.GetURL().GetFileType();
+ if (!filetype.empty())
+ {
+ std::string extensions = addonBase->Type(ADDON_INPUTSTREAM)->GetValue("@extension").asString();
+ if (!extensions.empty())
+ {
+ std::vector<std::string> extensionsList = StringUtils::Tokenize(extensions, "|");
+ for (auto& value : extensionsList)
+ {
+ StringUtils::Trim(value);
+ if (value == filetype)
+ return true;
+ }
+ }
+ }
+
+ return false;
}
bool CInputStreamAddon::Open()
{
- bool ret = false;
- if (m_addon)
- ret = m_addon->Open(m_item);
+ m_struct.toKodi.kodiInstance = this;
+ m_struct.toKodi.free_demux_packet = cb_free_demux_packet;
+ m_struct.toKodi.allocate_demux_packet = cb_allocate_demux_packet;
+ if (!CreateInstance(&m_struct) || !m_struct.toAddon.open)
+ return false;
+
+ INPUTSTREAM props;
+ std::map<std::string, std::string> propsMap;
+ for (auto &key : m_fileItemProps)
+ {
+ if (m_item.GetProperty(key).isNull())
+ continue;
+ propsMap[key] = m_item.GetProperty(key).asString();
+ }
+
+ props.m_nCountInfoValues = 0;
+ for (auto &pair : propsMap)
+ {
+ props.m_ListItemProperties[props.m_nCountInfoValues].m_strKey = pair.first.c_str();
+ props.m_ListItemProperties[props.m_nCountInfoValues].m_strValue = pair.second.c_str();
+ props.m_nCountInfoValues++;
+ }
+
+ props.m_strURL = m_item.GetPath().c_str();
+
+ std::string libFolder = URIUtils::GetDirectory(Addon()->Path());
+ std::string profileFolder = CSpecialProtocol::TranslatePath(Addon()->Profile());
+ props.m_libFolder = libFolder.c_str();
+ props.m_profileFolder = profileFolder.c_str();
+
+ unsigned int videoWidth = 1280;
+ unsigned int videoHeight = 720;
+ if (m_player)
+ m_player->GetVideoResolution(videoWidth, videoHeight);
+ SetVideoResolution(videoWidth, videoHeight);
+
+ bool ret = m_struct.toAddon.open(&m_struct, &props);
if (ret)
{
- m_hasDemux = m_addon->HasDemux();
- m_hasDisplayTime = m_addon->HasDisplayTime();
- m_hasPosTime = m_addon->HasPosTime();
- m_canPause = m_addon->CanPause();
- m_canSeek = m_addon->CanSeek();
+ memset(&m_caps, 0, sizeof(m_caps));
+ m_struct.toAddon.get_capabilities(&m_struct, &m_caps);
}
+
+ UpdateStreams();
return ret;
}
void CInputStreamAddon::Close()
{
- if (m_addon)
- return m_addon->Close();
+ if (m_struct.toAddon.close)
+ m_struct.toAddon.close(&m_struct);
+ DestroyInstance();
+ m_struct = {{ 0 }};
}
bool CInputStreamAddon::IsEOF()
@@ -63,53 +161,58 @@ bool CInputStreamAddon::IsEOF()
int CInputStreamAddon::Read(uint8_t* buf, int buf_size)
{
- if (!m_addon)
+ if (!m_struct.toAddon.read_stream)
return -1;
- return m_addon->ReadStream(buf, buf_size);
+ return m_struct.toAddon.read_stream(&m_struct, buf, buf_size);
}
int64_t CInputStreamAddon::Seek(int64_t offset, int whence)
{
- if (!m_addon)
+ if (!m_struct.toAddon.seek_stream)
return -1;
- return m_addon->SeekStream(offset, whence);
+ return m_struct.toAddon.seek_stream(&m_struct, offset, whence);
}
+int64_t CInputStreamAddon::PositionStream()
+{
+ if (!m_struct.toAddon.position_stream)
+ return -1;
+
+ return m_struct.toAddon.position_stream(&m_struct);
+}
int64_t CInputStreamAddon::GetLength()
{
- if (!m_addon)
+ if (!m_struct.toAddon.length_stream)
return -1;
- return m_addon->LengthStream();
+ return m_struct.toAddon.length_stream(&m_struct);
}
-bool CInputStreamAddon::Pause(double dTime)
+bool CInputStreamAddon::Pause(double time)
{
- if (!m_addon)
+ if (!m_struct.toAddon.pause_stream)
return false;
- m_addon->PauseStream(dTime);
+ m_struct.toAddon.pause_stream(&m_struct, time);
return true;
}
bool CInputStreamAddon::CanSeek()
{
- return m_canSeek;
+ return (m_caps.m_mask & INPUTSTREAM_CAPABILITIES::SUPPORTS_SEEK) != 0;
}
bool CInputStreamAddon::CanPause()
{
- return m_canPause;
+ return (m_caps.m_mask & INPUTSTREAM_CAPABILITIES::SUPPORTS_PAUSE) != 0;
}
// IDisplayTime
CDVDInputStream::IDisplayTime* CInputStreamAddon::GetIDisplayTime()
{
- if (!m_addon)
- return nullptr;
- if (!m_hasDisplayTime)
+ if ((m_caps.m_mask & INPUTSTREAM_CAPABILITIES::SUPPORTS_IDISPLAYTIME) == 0)
return nullptr;
return this;
@@ -117,26 +220,24 @@ CDVDInputStream::IDisplayTime* CInputStreamAddon::GetIDisplayTime()
int CInputStreamAddon::GetTotalTime()
{
- if (!m_addon)
+ if (!m_struct.toAddon.get_total_time)
return 0;
- return m_addon->GetTotalTime();
+ return m_struct.toAddon.get_total_time(&m_struct);
}
int CInputStreamAddon::GetTime()
{
- if (!m_addon)
+ if (!m_struct.toAddon.get_time)
return 0;
- return m_addon->GetTime();
+ return m_struct.toAddon.get_time(&m_struct);
}
// IPosTime
CDVDInputStream::IPosTime* CInputStreamAddon::GetIPosTime()
{
- if (!m_addon)
- return nullptr;
- if (!m_hasPosTime)
+ if ((m_caps.m_mask & INPUTSTREAM_CAPABILITIES::SUPPORTS_IPOSTIME) == 0)
return nullptr;
return this;
@@ -144,18 +245,16 @@ CDVDInputStream::IPosTime* CInputStreamAddon::GetIPosTime()
bool CInputStreamAddon::PosTime(int ms)
{
- if (!m_addon)
+ if (!m_struct.toAddon.pos_time)
return false;
- return m_addon->PosTime(ms);
+ return m_struct.toAddon.pos_time(&m_struct, ms);
}
// IDemux
CDVDInputStream::IDemux* CInputStreamAddon::GetIDemux()
{
- if (!m_addon)
- return nullptr;
- if (!m_hasDemux)
+ if ((m_caps.m_mask & INPUTSTREAM_CAPABILITIES::SUPPORTS_IDEMUX) == 0)
return nullptr;
return this;
@@ -163,7 +262,7 @@ CDVDInputStream::IDemux* CInputStreamAddon::GetIDemux()
bool CInputStreamAddon::OpenDemux()
{
- if (m_hasDemux)
+ if ((m_caps.m_mask & INPUTSTREAM_CAPABILITIES::SUPPORTS_IDEMUX) != 0)
return true;
else
return false;
@@ -171,61 +270,77 @@ bool CInputStreamAddon::OpenDemux()
DemuxPacket* CInputStreamAddon::ReadDemux()
{
- if (!m_addon)
+ if (!m_struct.toAddon.demux_read)
+ return nullptr;
+
+ DemuxPacket* pPacket = m_struct.toAddon.demux_read(&m_struct);
+
+ if (!pPacket)
+ {
return nullptr;
+ }
+ else if (pPacket->iStreamId == DMX_SPECIALID_STREAMINFO)
+ {
+ UpdateStreams();
+ }
+ else if (pPacket->iStreamId == DMX_SPECIALID_STREAMCHANGE)
+ {
+ UpdateStreams();
+ }
- return m_addon->ReadDemux();
+ return pPacket;
}
std::vector<CDemuxStream*> CInputStreamAddon::GetStreams() const
{
std::vector<CDemuxStream*> streams;
- if (!m_addon)
- return streams;
+ for (auto stream : m_streams)
+ streams.push_back(stream.second);
- return m_addon->GetStreams();
+ return streams;
}
-CDemuxStream* CInputStreamAddon::GetStream(int iStreamId) const
+CDemuxStream* CInputStreamAddon::GetStream(int streamId) const
{
- if (!m_addon)
- return nullptr;
+ auto stream = m_streams.find(streamId);
+ if (stream != m_streams.end())
+ return stream->second;
- return m_addon->GetStream(iStreamId);
+ return nullptr;
}
-void CInputStreamAddon::EnableStream(int iStreamId, bool enable)
+void CInputStreamAddon::EnableStream(int streamId, bool enable)
{
- if (!m_addon)
+ if (!m_struct.toAddon.enable_stream)
return;
- return m_addon->EnableStream(iStreamId, enable);
+ auto stream = m_streams.find(streamId);
+ if (stream == m_streams.end())
+ return;
+
+ m_struct.toAddon.enable_stream(&m_struct, stream->second->uniqueId, enable);
}
int CInputStreamAddon::GetNrOfStreams() const
{
- if (!m_addon)
- return 0;
-
- int count = m_addon->GetNrOfStreams();
- return count;
+ return m_streams.size();
}
-void CInputStreamAddon::SetSpeed(int iSpeed)
+void CInputStreamAddon::SetSpeed(int speed)
{
- if (!m_addon)
+ if (!m_struct.toAddon.demux_set_speed)
return;
- m_addon->SetSpeed(iSpeed);
+ m_struct.toAddon.demux_set_speed(&m_struct, speed);
}
bool CInputStreamAddon::SeekTime(double time, bool backward, double* startpts)
{
- if (!m_addon)
+ if (!m_struct.toAddon.demux_seek_time)
return false;
- if (m_hasPosTime)
+ if ((m_caps.m_mask & INPUTSTREAM_CAPABILITIES::SUPPORTS_IPOSTIME) != 0)
{
if (!PosTime(static_cast<int>(time)))
return false;
@@ -237,29 +352,129 @@ bool CInputStreamAddon::SeekTime(double time, bool backward, double* startpts)
return true;
}
- return m_addon->SeekTime(time, backward, startpts);
+ return m_struct.toAddon.demux_seek_time(&m_struct, time, backward, startpts);
}
void CInputStreamAddon::AbortDemux()
{
- if (!m_addon)
- return;
-
- m_addon->AbortDemux();
+ if (m_struct.toAddon.demux_abort)
+ m_struct.toAddon.demux_abort(&m_struct);
}
void CInputStreamAddon::FlushDemux()
{
- if (!m_addon)
- return;
-
- m_addon->FlushDemux();
+ if (m_struct.toAddon.demux_flush)
+ m_struct.toAddon.demux_flush(&m_struct);
}
void CInputStreamAddon::SetVideoResolution(int width, int height)
{
- if (!m_addon)
+ if (m_struct.toAddon.set_video_resolution)
+ m_struct.toAddon.set_video_resolution(&m_struct, width, height);
+}
+
+bool CInputStreamAddon::IsRealTimeStream()
+{
+ if (m_struct.toAddon.is_real_time_stream)
+ return m_struct.toAddon.is_real_time_stream(&m_struct);
+ return false;
+}
+
+void CInputStreamAddon::UpdateStreams()
+{
+ DisposeStreams();
+
+ INPUTSTREAM_IDS streamIDs = m_struct.toAddon.get_stream_ids(&m_struct);
+ if (streamIDs.m_streamCount > INPUTSTREAM_IDS::MAX_STREAM_COUNT)
+ {
+ DisposeStreams();
return;
+ }
+
+ for (unsigned int i = 0; i < streamIDs.m_streamCount; ++i)
+ {
+ INPUTSTREAM_INFO stream = m_struct.toAddon.get_stream(&m_struct, streamIDs.m_streamIds[i]);
+ if (stream.m_streamType == INPUTSTREAM_INFO::TYPE_NONE)
+ continue;
+
+ std::string codecName(stream.m_codecName);
+ StringUtils::ToLower(codecName);
+ AVCodec *codec = avcodec_find_decoder_by_name(codecName.c_str());
+ if (!codec)
+ continue;
+
+ CDemuxStream *demuxStream;
+
+ if (stream.m_streamType == INPUTSTREAM_INFO::TYPE_AUDIO)
+ {
+ CDemuxStreamAudio *audioStream = new CDemuxStreamAudio();
+
+ audioStream->iChannels = stream.m_Channels;
+ audioStream->iSampleRate = stream.m_SampleRate;
+ audioStream->iBlockAlign = stream.m_BlockAlign;
+ audioStream->iBitRate = stream.m_BitRate;
+ audioStream->iBitsPerSample = stream.m_BitsPerSample;
+ demuxStream = audioStream;
+ }
+ else if (stream.m_streamType == INPUTSTREAM_INFO::TYPE_VIDEO)
+ {
+ CDemuxStreamVideo *videoStream = new CDemuxStreamVideo();
+
+ videoStream->iFpsScale = stream.m_FpsScale;
+ videoStream->iFpsRate = stream.m_FpsRate;
+ videoStream->iWidth = stream.m_Width;
+ videoStream->iHeight = stream.m_Height;
+ videoStream->fAspect = stream.m_Aspect;
+ videoStream->stereo_mode = "mono";
+ videoStream->iBitRate = stream.m_BitRate;
+ demuxStream = videoStream;
+ }
+ else if (stream.m_streamType == INPUTSTREAM_INFO::TYPE_SUBTITLE)
+ {
+ CDemuxStreamSubtitle *subtitleStream = new CDemuxStreamSubtitle();
+ demuxStream = subtitleStream;
+ }
+ else
+ continue;
+
+ demuxStream->codec = codec->id;
+ demuxStream->codecName = stream.m_codecInternalName;
+ demuxStream->uniqueId = streamIDs.m_streamIds[i];
+ demuxStream->language[0] = stream.m_language[0];
+ demuxStream->language[1] = stream.m_language[1];
+ demuxStream->language[2] = stream.m_language[2];
+ demuxStream->language[3] = stream.m_language[3];
+
+ if (stream.m_ExtraData && stream.m_ExtraSize)
+ {
+ demuxStream->ExtraData = new uint8_t[stream.m_ExtraSize];
+ demuxStream->ExtraSize = stream.m_ExtraSize;
+ for (unsigned int j = 0; j < stream.m_ExtraSize; ++j)
+ demuxStream->ExtraData[j] = stream.m_ExtraData[j];
+ }
+
+ m_streams[demuxStream->uniqueId] = demuxStream;
+ }
+}
- m_addon->SetVideoResolution(width, height);
+void CInputStreamAddon::DisposeStreams()
+{
+ for (auto &stream : m_streams)
+ delete stream.second;
+ m_streams.clear();
+}
+
+/*!
+ * Callbacks from add-on to kodi
+ */
+//@{
+DemuxPacket* CInputStreamAddon::cb_allocate_demux_packet(void* kodiInstance, int data_size)
+{
+ return CDVDDemuxUtils::AllocateDemuxPacket(data_size);
+}
+
+void CInputStreamAddon::cb_free_demux_packet(void* kodiInstance, DemuxPacket* packet)
+{
+ CDVDDemuxUtils::FreeDemuxPacket(packet);
}
+//@}
diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.h b/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.h
index 04c5b4c557..f893b5cc0d 100644
--- a/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.h
+++ b/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.h
@@ -24,45 +24,35 @@
#include <vector>
#include "DVDInputStream.h"
-#include "addons/InputStream.h"
+#include "IVideoPlayer.h"
+#include "addons/binary-addons/AddonInstanceHandler.h"
+#include "addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h"
//! \brief Input stream class
-class CInputStreamAddon :
- public CDVDInputStream,
- public CDVDInputStream::IDisplayTime,
- public CDVDInputStream::IPosTime,
- public CDVDInputStream::IDemux
+class CInputStreamAddon
+ : public ADDON::IAddonInstanceHandler,
+ public CDVDInputStream,
+ public CDVDInputStream::IDisplayTime,
+ public CDVDInputStream::IPosTime,
+ public CDVDInputStream::IDemux
{
public:
- //! \brief constructor
- CInputStreamAddon(const CFileItem& fileitem, std::shared_ptr<ADDON::CInputStream> inputStream);
-
- //! \brief Destructor.
+ CInputStreamAddon(ADDON::BinaryAddonBasePtr& addonBase, IVideoPlayer* player, const CFileItem& fileitem);
virtual ~CInputStreamAddon();
- //! \brief Open a MPD file
- virtual bool Open() override;
+ static bool Supports(ADDON::BinaryAddonBasePtr& addonBase, const CFileItem& fileitem);
- //! \brief Close input stream
+ // CDVDInputStream
+ virtual bool Open() override;
virtual void Close() override;
-
- //! \brief Read data from stream
virtual int Read(uint8_t* buf, int buf_size) override;
-
- //! \brief Seek in stream
virtual int64_t Seek(int64_t offset, int whence) override;
-
- //! \brief Pause stream
virtual bool Pause(double dTime) override;
- //! \brief Return true if we have reached EOF
+ virtual int64_t GetLength() override;
virtual bool IsEOF() override;
-
virtual bool CanSeek() override;
virtual bool CanPause() override;
- //! \brief Get length of input data
- virtual int64_t GetLength() override;
-
// IDisplayTime
virtual CDVDInputStream::IDisplayTime* GetIDisplayTime() override;
virtual int GetTotalTime() override;
@@ -72,25 +62,52 @@ public:
virtual CDVDInputStream::IPosTime* GetIPosTime() override;
virtual bool PosTime(int ms) override;
- //IDemux
+ // IDemux
CDVDInputStream::IDemux* GetIDemux() override;
virtual bool OpenDemux() override;
virtual DemuxPacket* ReadDemux() override;
- virtual CDemuxStream* GetStream(int iStreamId) const override;
+ virtual CDemuxStream* GetStream(int streamId) const override;
virtual std::vector<CDemuxStream*> GetStreams() const override;
- virtual void EnableStream(int iStreamId, bool enable) override;
+ virtual void EnableStream(int streamId, bool enable) override;
virtual int GetNrOfStreams() const override;
- virtual void SetSpeed(int iSpeed) override;
- virtual bool SeekTime(double time, bool backward = false, double* startpts = NULL) override;
+ virtual void SetSpeed(int speed) override;
+ virtual bool SeekTime(double time, bool backward = false, double* startpts = nullptr) override;
virtual void AbortDemux() override;
virtual void FlushDemux() override;
virtual void SetVideoResolution(int width, int height) override;
+ int64_t PositionStream();
+ bool IsRealTimeStream();
protected:
- std::shared_ptr<ADDON::CInputStream> m_addon;
- bool m_hasDemux = false;
- bool m_hasDisplayTime = false;
- bool m_hasPosTime = false;
- bool m_canPause = false;
- bool m_canSeek = false;
+ void UpdateStreams();
+ void DisposeStreams();
+
+ IVideoPlayer* m_player;
+
+private:
+ std::vector<std::string> m_fileItemProps;
+ INPUTSTREAM_CAPABILITIES m_caps;
+ std::map<int, CDemuxStream*> m_streams;
+
+ AddonInstance_InputStream m_struct;
+
+ /*!
+ * Callbacks from add-on to kodi
+ */
+ //@{
+ /*!
+ * @brief Allocate a demux packet. Free with FreeDemuxPacket
+ * @param kodiInstance A pointer to the add-on.
+ * @param iDataSize The size of the data that will go into the packet
+ * @return The allocated packet.
+ */
+ static DemuxPacket* cb_allocate_demux_packet(void* kodiInstance, int iDataSize = 0);
+
+ /*!
+ * @brief Free a packet that was allocated with AllocateDemuxPacket
+ * @param kodiInstance A pointer to the add-on.
+ * @param pPacket The packet to free.
+ */
+ static void cb_free_demux_packet(void* kodiInstance, DemuxPacket* pPacket);
+ //@}
};