aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--addons/kodi.binary.instance.videocodec/addon.xml.in7
-rw-r--r--system/addon-manifest.xml1
-rw-r--r--xbmc/addons/AddonInfo.h1
-rw-r--r--xbmc/addons/AddonProvider.h46
-rw-r--r--xbmc/addons/CMakeLists.txt1
-rw-r--r--xbmc/addons/binary-addons/AddonInstanceHandler.h1
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/StreamCodec.h33
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/StreamCrypto.h33
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h28
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VideoCodec.h247
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h18
-rw-r--r--xbmc/cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.cpp19
-rw-r--r--xbmc/cores/VideoPlayer/DVDCodecs/Video/AddonVideoCodec.cpp361
-rw-r--r--xbmc/cores/VideoPlayer/DVDCodecs/Video/AddonVideoCodec.h66
-rw-r--r--xbmc/cores/VideoPlayer/DVDCodecs/Video/CMakeLists.txt6
-rw-r--r--xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp74
-rw-r--r--xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.h25
-rw-r--r--xbmc/video/dialogs/GUIDialogVideoSettings.cpp9
18 files changed, 967 insertions, 9 deletions
diff --git a/addons/kodi.binary.instance.videocodec/addon.xml.in b/addons/kodi.binary.instance.videocodec/addon.xml.in
new file mode 100644
index 0000000000..c3b035cc16
--- /dev/null
+++ b/addons/kodi.binary.instance.videocodec/addon.xml.in
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<addon id="kodi.binary.instance.videocodec" version="@ADDON_INSTANCE_VERSION_VIDEOCODEC@" provider-name="Team Kodi">
+ <backwards-compatibility abi="@ADDON_INSTANCE_VERSION_VIDEOCODEC_MIN@"/>
+ <requires>
+ <import addon="xbmc.core" version="0.1.0"/>
+ </requires>
+</addon>
diff --git a/system/addon-manifest.xml b/system/addon-manifest.xml
index b70114bf7d..79012d73ad 100644
--- a/system/addon-manifest.xml
+++ b/system/addon-manifest.xml
@@ -18,6 +18,7 @@
<addon>kodi.binary.instance.pvr</addon>
<addon>kodi.binary.instance.screensaver</addon>
<addon>kodi.binary.instance.vfs</addon>
+ <addon>kodi.binary.instance.videocodec</addon>
<addon>kodi.binary.instance.visualization</addon>
<addon>kodi.resource</addon>
<addon>metadata.album.universal</addon>
diff --git a/xbmc/addons/AddonInfo.h b/xbmc/addons/AddonInfo.h
index dc4d321950..a94bb64381 100644
--- a/xbmc/addons/AddonInfo.h
+++ b/xbmc/addons/AddonInfo.h
@@ -66,6 +66,7 @@ namespace ADDON
ADDON_SCRIPT_LIBRARY,
ADDON_SCRIPT_MODULE,
ADDON_GAME_CONTROLLER,
+ ADDON_VIDEOCODEC,
/**
* @brief virtual addon types
diff --git a/xbmc/addons/AddonProvider.h b/xbmc/addons/AddonProvider.h
new file mode 100644
index 0000000000..3b8392369b
--- /dev/null
+++ b/xbmc/addons/AddonProvider.h
@@ -0,0 +1,46 @@
+#pragma once
+
+/*
+* Copyright (C) 2017 Team XBMC
+* http://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/>.
+*
+*/
+
+/*
+* CAddonProvider
+* IUnknown implementation to retrieve sub-addons from already active addons
+* See Inputstream.cpp/h for an explaric use case
+*/
+
+namespace kodi { namespace addon { class IAddonInstance; } }
+
+namespace ADDON
+{
+ class CBinaryAddonBase;
+ typedef std::shared_ptr<CBinaryAddonBase> BinaryAddonBasePtr;
+
+ class IAddonProvider
+ {
+ public:
+ enum INSTANCE_TYPE
+ {
+ INSTANCE_VIDEOCODEC
+ };
+ virtual void getAddonInstance(INSTANCE_TYPE instance_type, ADDON::BinaryAddonBasePtr& addonBase, kodi::addon::IAddonInstance*& parentInstance) = 0;
+ };
+
+ } //Namespace
diff --git a/xbmc/addons/CMakeLists.txt b/xbmc/addons/CMakeLists.txt
index 8145bce0de..169dead9a8 100644
--- a/xbmc/addons/CMakeLists.txt
+++ b/xbmc/addons/CMakeLists.txt
@@ -41,6 +41,7 @@ set(HEADERS Addon.h
AddonInfo.h
AddonInstaller.h
AddonManager.h
+ AddonProvider.h
AddonStatusHandler.h
AddonSystemSettings.h
AddonVersion.h
diff --git a/xbmc/addons/binary-addons/AddonInstanceHandler.h b/xbmc/addons/binary-addons/AddonInstanceHandler.h
index f18524ab26..048f770b6a 100644
--- a/xbmc/addons/binary-addons/AddonInstanceHandler.h
+++ b/xbmc/addons/binary-addons/AddonInstanceHandler.h
@@ -48,6 +48,7 @@ namespace ADDON
bool CreateInstance(KODI_HANDLE instance);
void DestroyInstance();
const AddonDllPtr& Addon() { return m_addon; }
+ BinaryAddonBasePtr GetAddonBase() { return m_addonBase; };
private:
ADDON_TYPE m_type;
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/StreamCodec.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/StreamCodec.h
new file mode 100644
index 0000000000..85de3eccf9
--- /dev/null
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/StreamCodec.h
@@ -0,0 +1,33 @@
+#pragma once
+/*
+ * Copyright (C) 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/>.
+ *
+ */
+
+enum STREAMCODEC_PROFILE
+{
+ CodecProfileUnknown = 0,
+ CodecProfileNotNeeded,
+ H264CodecProfileBaseline,
+ H264CodecProfileMain,
+ H264CodecProfileExtended,
+ H264CodecProfileHigh,
+ H264CodecProfileHigh10,
+ H264CodecProfileHigh422,
+ H264CodecProfileHigh444Predictive
+};
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/StreamCrypto.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/StreamCrypto.h
new file mode 100644
index 0000000000..52ef860262
--- /dev/null
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/StreamCrypto.h
@@ -0,0 +1,33 @@
+#pragma once
+/*
+ * Copyright (C) 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/>.
+ *
+ */
+
+typedef struct CRYPTO_INFO
+{
+ enum CRYPTO_KEY_SYSTEM : uint16_t
+ {
+ CRYPTO_KEY_SYSTEM_NONE = 0,
+ CRYPTO_KEY_SYSTEM_WIDEVINE,
+ CRYPTO_KEY_SYSTEM_PLAYREADY,
+ CRYPTO_KEY_SYSTEM_COUNT
+ } m_CryptoKeySystem; /*!< @brief keysystem for encrypted media, KEY_SYSTEM_NONE for unencrypted media */
+ const char *m_CryptoSessionId; /*!< @brief The crypto session key id */
+ uint16_t m_CryptoSessionIdSize; /*!< @brief The size of the crypto session key id */
+} CRYPTO_INFO;
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h
index bdb80bb742..ebafa9d838 100644
--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h
@@ -25,6 +25,8 @@
*/
#include "../AddonBase.h"
+#include "../StreamCrypto.h"
+#include "../StreamCodec.h"
#ifdef BUILD_KODI_ADDON
#include "../DVDDemuxPacket.h"
@@ -107,8 +109,15 @@ extern "C" {
TYPE_TELETEXT
} m_streamType;
+ enum Codec_FEATURES
+ {
+ FEATURE_DECODE = 1
+ };
+ unsigned int m_features;
+
char m_codecName[32]; /*!< @brief (required) name of codec according to ffmpeg */
char m_codecInternalName[32]; /*!< @brief (optional) internal name of codec (selectionstream info) */
+ STREAMCODEC_PROFILE m_codecProfile; /*!< @brief (optional) the profile of the codec */
unsigned int m_pID; /*!< @brief (required) physical index */
const uint8_t *m_ExtraData;
@@ -127,6 +136,8 @@ extern "C" {
unsigned int m_BitRate; /*!< @brief (required) bit rate */
unsigned int m_BitsPerSample; /*!< @brief (required) bits per sample */
unsigned int m_BlockAlign;
+
+ CRYPTO_INFO m_cryptoInfo;
} INPUTSTREAM_INFO;
/*!
@@ -144,6 +155,7 @@ extern "C" {
{
KODI_HANDLE kodiInstance;
DemuxPacket* (*allocate_demux_packet)(void* kodiInstance, int data_size);
+ DemuxPacket* (*allocate_encrypted_demux_packet)(void* kodiInstance, unsigned int data_size, unsigned int encrypted_subsample_count);
void (*free_demux_packet)(void* kodiInstance, DemuxPacket* packet);
} AddonToKodiFuncTable_InputStream;
@@ -241,7 +253,7 @@ namespace addon
* Get IDs of available streams
* @remarks
*/
- virtual INPUTSTREAM_IDS GetStreamIds() { return INPUTSTREAM_IDS(); }
+ virtual INPUTSTREAM_IDS GetStreamIds() = 0;
/*!
* Get stream properties of a stream.
@@ -249,7 +261,7 @@ namespace addon
* @return struc of stream properties
* @remarks
*/
- virtual INPUTSTREAM_INFO GetStream(int streamid) { return INPUTSTREAM_INFO(); }
+ virtual INPUTSTREAM_INFO GetStream(int streamid) = 0;
/*!
* Enable or disable a stream.
@@ -258,7 +270,7 @@ namespace addon
* @param enable true for enable, false for disable
* @remarks
*/
- virtual void EnableStream(int streamid, bool enable) { }
+ virtual void EnableStream(int streamid, bool enable) = 0;
/*!
* Reset the demultiplexer in the add-on.
@@ -403,6 +415,16 @@ namespace addon
}
/*!
+ * @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
*/
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VideoCodec.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VideoCodec.h
new file mode 100644
index 0000000000..2800fc0edf
--- /dev/null
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VideoCodec.h
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2017 Team XBMC
+ * http://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 "../AddonBase.h"
+#include "../StreamCrypto.h"
+#include "../StreamCodec.h"
+
+#ifdef BUILD_KODI_ADDON
+#include "../DVDDemuxPacket.h"
+#else
+#include "cores/VideoPlayer/DVDDemuxers/DVDDemuxPacket.h"
+#endif
+
+namespace kodi { namespace addon { class CInstanceVideoCodec; } }
+
+extern "C"
+{
+ enum VIDEOCODEC_FORMAT
+ {
+ UnknownVideoFormat = 0,
+ VideoFormatYV12,
+ VideoFormatI420,
+ MaxVideoFormats
+ };
+
+
+ struct VIDEOCODEC_INITDATA
+ {
+ enum Codec {
+ CodecUnknown = 0,
+ CodecVp8,
+ CodecH264,
+ CodecVp9
+ } codec;
+
+ STREAMCODEC_PROFILE codecProfile;
+
+ //UnknownVideoFormat is terminator
+ VIDEOCODEC_FORMAT *videoFormats;
+
+ uint32_t width, height;
+
+ const uint8_t *extraData;
+ unsigned int extraDataSize;
+
+ CRYPTO_INFO cryptoInfo;
+ };
+
+ struct VIDEOCODEC_PICTURE
+ {
+ enum VideoPlane {
+ YPlane = 0,
+ UPlane,
+ VPlane,
+ MaxPlanes = 3,
+ };
+
+ enum Flags : uint32_t {
+ FLAG_DROP,
+ FLAG_DRAIN
+ };
+
+ VIDEOCODEC_FORMAT videoFormat;
+ uint32_t flags;
+
+ uint32_t width, height;
+
+ uint8_t *decodedData;
+ size_t decodedDataSize;
+
+ uint32_t planeOffsets[VideoPlane::MaxPlanes];
+ uint32_t stride[VideoPlane::MaxPlanes];
+
+ int64_t pts;
+ };
+
+ enum VIDEOCODEC_RETVAL
+ {
+ VC_NONE = 0, //< noop
+ VC_ERROR, //< an error occured, no other messages will be returned
+ VC_BUFFER, //< the decoder needs more data
+ VC_PICTURE, //< the decoder got a picture
+ VC_EOF, //< the decoder signals EOF
+ };
+
+ // this are properties given to the addon on create
+ // at this time we have no parameters for the addon
+ typedef struct AddonProps_VideoCodec
+ {
+ int dummy;
+ } AddonProps_VideoCodec;
+
+ struct AddonInstance_VideoCodec;
+ typedef struct KodiToAddonFuncTable_VideoCodec
+ {
+ kodi::addon::CInstanceVideoCodec* addonInstance;
+
+ //! \brief Opens a codec
+ bool (__cdecl* open) (const AddonInstance_VideoCodec* instance, VIDEOCODEC_INITDATA *initData);
+
+ //! \brief Reconfigures a codec
+ bool (__cdecl* reconfigure) (const AddonInstance_VideoCodec* instance, VIDEOCODEC_INITDATA *initData);
+
+ //! \brief Feed codec if requested from GetPicture() (return VC_BUFFER)
+ bool (__cdecl* add_data) (const AddonInstance_VideoCodec* instance, const DemuxPacket *packet);
+
+ //! \brief Get a decoded picture / request new data
+ VIDEOCODEC_RETVAL (__cdecl* get_picture) (const AddonInstance_VideoCodec* instance, VIDEOCODEC_PICTURE *picture);
+
+ //! \brief Get the name of this video decoder
+ const char *(__cdecl* get_name) (const AddonInstance_VideoCodec* instance);
+
+ //! \brief Reset the codec
+ void (__cdecl* reset)(const AddonInstance_VideoCodec* instance);
+ } KodiToAddonFuncTable_VideoCodec;
+
+ typedef struct AddonToKodiFuncTable_VideoCodec
+ {
+ KODI_HANDLE kodiInstance;
+ bool(*get_frame_buffer)(void* kodiInstance, VIDEOCODEC_PICTURE *picture);
+ } AddonToKodiFuncTable_VideoCodec;
+
+ typedef struct AddonInstance_VideoCodec
+ {
+ AddonProps_VideoCodec props;
+ AddonToKodiFuncTable_VideoCodec toKodi;
+ KodiToAddonFuncTable_VideoCodec toAddon;
+ } AddonInstance_VideoCodec;
+}
+
+namespace kodi
+{
+ namespace addon
+ {
+
+ class CInstanceVideoCodec : public IAddonInstance
+ {
+ public:
+ CInstanceVideoCodec(KODI_HANDLE instance)
+ : IAddonInstance(ADDON_INSTANCE_VIDEOCODEC)
+ {
+ if (CAddonBase::m_interface->globalSingleInstance != nullptr)
+ throw std::logic_error("kodi::addon::CInstanceVideoCodec: Creation of multiple together with single instance way is not allowed!");
+
+ SetAddonStruct(instance);
+ }
+
+ virtual ~CInstanceVideoCodec() = default;
+
+ //! \copydoc CInstanceVideoCodec::Open
+ virtual bool Open(VIDEOCODEC_INITDATA &initData) { return false; };
+
+ //! \copydoc CInstanceVideoCodec::Reconfigure
+ virtual bool Reconfigure(VIDEOCODEC_INITDATA &initData) { return false; };
+
+ //! \copydoc CInstanceVideoCodec::AddData
+ virtual bool AddData(const DemuxPacket &packet) { return false; };
+
+ //! \copydoc CInstanceVideoCodec::GetPicture
+ virtual VIDEOCODEC_RETVAL GetPicture(VIDEOCODEC_PICTURE &picture) { return VC_ERROR; };
+
+ //! \copydoc CInstanceVideoCodec::GetName
+ virtual const char *GetName() { return nullptr; };
+
+ //! \copydoc CInstanceVideoCodec::Reset
+ virtual void Reset() {};
+
+ /*!
+ * @brief AddonToKodi interface
+ */
+
+ //! \copydoc CInstanceVideoCodec::GetFrameBuffer
+ bool GetFrameBuffer(VIDEOCODEC_PICTURE &picture)
+ {
+ return m_instanceData->toKodi.get_frame_buffer(m_instanceData->toKodi.kodiInstance, &picture);
+ }
+
+ private:
+ void SetAddonStruct(KODI_HANDLE instance)
+ {
+ if (instance == nullptr)
+ throw std::logic_error("kodi::addon::CInstanceVideoCodec: Creation with empty addon structure not allowed, table must be given from Kodi!");
+
+ m_instanceData = static_cast<AddonInstance_VideoCodec*>(instance);
+
+ m_instanceData->toAddon.addonInstance = this;
+ m_instanceData->toAddon.open = ADDON_Open;
+ m_instanceData->toAddon.reconfigure = ADDON_Reconfigure;
+ m_instanceData->toAddon.add_data = ADDON_AddData;
+ m_instanceData->toAddon.get_picture = ADDON_GetPicture;
+ m_instanceData->toAddon.get_name = ADDON_GetName;
+ m_instanceData->toAddon.reset = ADDON_Reset;
+ }
+
+ inline static bool ADDON_Open(const AddonInstance_VideoCodec* instance, VIDEOCODEC_INITDATA *initData)
+ {
+ return instance->toAddon.addonInstance->Open(*initData);
+ }
+
+ inline static bool ADDON_Reconfigure(const AddonInstance_VideoCodec* instance, VIDEOCODEC_INITDATA *initData)
+ {
+ return instance->toAddon.addonInstance->Reconfigure(*initData);
+ }
+
+ inline static bool ADDON_AddData(const AddonInstance_VideoCodec* instance, const DemuxPacket *packet)
+ {
+ return instance->toAddon.addonInstance->AddData(*packet);
+ }
+
+ inline static VIDEOCODEC_RETVAL ADDON_GetPicture(const AddonInstance_VideoCodec* instance, VIDEOCODEC_PICTURE *picture)
+ {
+ return instance->toAddon.addonInstance->GetPicture(*picture);
+ }
+
+ inline static const char *ADDON_GetName(const AddonInstance_VideoCodec* instance)
+ {
+ return instance->toAddon.addonInstance->GetName();
+ }
+
+ inline static void ADDON_Reset(const AddonInstance_VideoCodec* instance)
+ {
+ return instance->toAddon.addonInstance->Reset();
+ }
+
+ AddonInstance_VideoCodec* m_instanceData;
+ };
+ } // namespace addon
+} // namespace kodi
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 34c2861a99..72394d1fde 100644
--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h
@@ -141,6 +141,13 @@
#define ADDON_INSTANCE_VERSION_VISUALIZATION_XML_ID "kodi.binary.instance.visualization"
#define ADDON_INSTANCE_VERSION_VISUALIZATION_DEPENDS "addon-instance/Visualization.h"
+#define ADDON_INSTANCE_VERSION_VIDEOCODEC "1.0.0"
+#define ADDON_INSTANCE_VERSION_VIDEOCODEC_MIN "1.0.0"
+#define ADDON_INSTANCE_VERSION_VIDEOCODEC_XML_ID "kodi.binary.instance.videocodec"
+#define ADDON_INSTANCE_VERSION_VIDEOCODEC_DEPENDS "addon-instance/VideoCodec.h" \
+ "StreamCodec.h" \
+ "StreamCrypto.h"
+
///
/// The currently available instance types for Kodi add-ons
///
@@ -172,6 +179,7 @@ typedef enum ADDON_TYPE
ADDON_INSTANCE_VISUALIZATION = 109,
ADDON_INSTANCE_VFS = 110,
ADDON_INSTANCE_IMAGEDECODER = 111,
+ ADDON_INSTANCE_VIDEOCODEC = 112,
} ADDON_TYPE;
#ifdef __cplusplus
@@ -264,6 +272,10 @@ inline const char* GetTypeVersion(int type)
case ADDON_INSTANCE_VISUALIZATION:
return ADDON_INSTANCE_VERSION_VISUALIZATION;
#endif
+#if !defined(BUILD_KODI_ADDON) || defined(ADDON_INSTANCE_VERSION_VIDEOCODEC_USED)
+ case ADDON_INSTANCE_VIDEOCODEC:
+ return ADDON_INSTANCE_VERSION_VIDEOCODEC;
+#endif
}
return "0.0.0";
}
@@ -317,6 +329,8 @@ inline const char* GetTypeMinVersion(int type)
return ADDON_INSTANCE_VERSION_VFS_MIN;
case ADDON_INSTANCE_VISUALIZATION:
return ADDON_INSTANCE_VERSION_VISUALIZATION_MIN;
+ case ADDON_INSTANCE_VIDEOCODEC:
+ return ADDON_INSTANCE_VERSION_VIDEOCODEC_MIN;
}
return "0.0.0";
}
@@ -367,6 +381,8 @@ inline const char* GetTypeName(int type)
return "ScreenSaver";
case ADDON_INSTANCE_VISUALIZATION:
return "Visualization";
+ case ADDON_INSTANCE_VIDEOCODEC:
+ return "VideoCodec";
}
return "unknown";
}
@@ -418,6 +434,8 @@ inline int GetTypeId(const char* name)
return ADDON_INSTANCE_VFS;
else if (strcmp(name, "visualization") == 0)
return ADDON_INSTANCE_VISUALIZATION;
+ else if (strcmp(name, "videocodec") == 0)
+ return ADDON_INSTANCE_VIDEOCODEC;
}
return -1;
}
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.cpp
index 85a3a22f18..734dce22de 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.cpp
@@ -22,11 +22,14 @@
#include "utils/log.h"
#include "DVDFactoryCodec.h"
+#include "Video/AddonVideoCodec.h"
#include "Video/DVDVideoCodec.h"
#include "Audio/DVDAudioCodec.h"
#include "Overlay/DVDOverlayCodec.h"
#include "cores/VideoPlayer/DVDCodecs/DVDCodecs.h"
+#include "addons/AddonProvider.h"
+
#include "Video/DVDVideoCodecFFmpeg.h"
#include "Audio/DVDAudioCodecFFmpeg.h"
@@ -67,6 +70,22 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, CProces
options.m_opaque_pointer = info.opaque_pointer;
+ // addon handler for this stream ?
+
+ if (hint.externalInterfaces)
+ {
+ ADDON::BinaryAddonBasePtr addonInfo;
+ kodi::addon::IAddonInstance* parentInstance;
+ hint.externalInterfaces->getAddonInstance(ADDON::IAddonProvider::INSTANCE_VIDEOCODEC, addonInfo, parentInstance);
+ if (addonInfo && parentInstance)
+ {
+ pCodec.reset(new CAddonVideoCodec(processInfo, addonInfo, parentInstance));
+ if (pCodec && pCodec->Open(hint, options))
+ return pCodec.release();
+ }
+ return nullptr;
+ }
+
// platform specifig video decoders
if (!(hint.codecOptions & CODEC_FORCE_SOFTWARE))
{
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AddonVideoCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AddonVideoCodec.cpp
new file mode 100644
index 0000000000..55359206a6
--- /dev/null
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AddonVideoCodec.cpp
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "AddonVideoCodec.h"
+#include "addons/binary-addons/BinaryAddonBase.h"
+#include "cores/VideoPlayer/DVDStreamInfo.h"
+#include "cores/VideoPlayer/DVDDemuxers/DemuxCrypto.h"
+#include "cores/VideoPlayer/DVDCodecs/DVDCodecs.h"
+#include "cores/VideoPlayer/TimingConstants.h"
+#include "utils/log.h"
+#include "settings/AdvancedSettings.h"
+
+using namespace kodi::addon;
+
+#define ALIGN(value, alignment) (((value)+(alignment-1))&~(alignment-1))
+
+class BufferPool
+{
+public:
+ ~BufferPool()
+ {
+ for (BUFFER &buf : freeBuffer)
+ free(buf.mem);
+ for (BUFFER &buf : usedBuffer)
+ free(buf.mem);
+ }
+
+ bool GetBuffer(VIDEOCODEC_PICTURE &picture)
+ {
+ if (freeBuffer.empty())
+ freeBuffer.resize(1);
+
+ BUFFER &buf(freeBuffer.back());
+ if (buf.memSize < picture.decodedDataSize)
+ {
+ buf.memSize = picture.decodedDataSize;
+ buf.mem = malloc(buf.memSize);
+ if (buf.mem == nullptr)
+ {
+ buf.memSize = 0;
+ picture.decodedData = nullptr;
+ return false;
+ }
+ }
+ picture.decodedData = (uint8_t*)buf.mem;
+
+ usedBuffer.push_back(buf);
+ freeBuffer.pop_back();
+ return true;
+ }
+
+ void ReleaseBuffer(void *bufferPtr)
+ {
+ std::vector<BUFFER>::iterator res(std::find(usedBuffer.begin(), usedBuffer.end(), bufferPtr));
+ if (res == usedBuffer.end())
+ return;
+ freeBuffer.push_back(*res);
+ usedBuffer.erase(res);
+ }
+
+private:
+ struct BUFFER
+ {
+ BUFFER():mem(nullptr), memSize(0) {};
+ BUFFER(void* m, size_t s) :mem(m), memSize(s) {};
+ bool operator == (const void* data) const { return mem == data; };
+
+ void *mem;
+ size_t memSize;
+ };
+ std::vector<BUFFER> freeBuffer, usedBuffer;
+};
+
+CAddonVideoCodec::CAddonVideoCodec(CProcessInfo &processInfo, ADDON::BinaryAddonBasePtr& addonInfo, kodi::addon::IAddonInstance* parentInstance)
+ : CDVDVideoCodec(processInfo),
+ IAddonInstanceHandler(ADDON_INSTANCE_VIDEOCODEC, addonInfo, parentInstance)
+ , m_codecFlags(0)
+ , m_displayAspect(0.0f)
+ , m_lastPictureBuffer(nullptr)
+ , m_bufferPool(new BufferPool())
+{
+ m_struct = { { 0 } };
+ m_struct.toKodi.kodiInstance = this;
+ m_struct.toKodi.get_frame_buffer = get_frame_buffer;
+ if (!CreateInstance(&m_struct) || !m_struct.toAddon.open)
+ {
+ CLog::Log(LOGERROR, "CInputStreamAddon: Failed to create add-on instance for '%s'", addonInfo->ID().c_str());
+ return;
+ }
+ m_processInfo.SetVideoDecoderName(GetName(), false);
+}
+
+CAddonVideoCodec::~CAddonVideoCodec()
+{
+ DestroyInstance();
+
+ m_bufferPool->ReleaseBuffer(m_lastPictureBuffer);
+
+ delete m_bufferPool;
+}
+
+bool CAddonVideoCodec::CopyToInitData(VIDEOCODEC_INITDATA &initData, CDVDStreamInfo &hints)
+{
+ initData.codecProfile = STREAMCODEC_PROFILE::CodecProfileNotNeeded;
+ switch (hints.codec)
+ {
+ case AV_CODEC_ID_H264:
+ initData.codec = VIDEOCODEC_INITDATA::CodecH264;
+ switch (hints.profile)
+ {
+ case 0:
+ case FF_PROFILE_UNKNOWN:
+ initData.codecProfile = STREAMCODEC_PROFILE::CodecProfileUnknown;
+ break;
+ case FF_PROFILE_H264_BASELINE:
+ initData.codecProfile = STREAMCODEC_PROFILE::H264CodecProfileBaseline;
+ break;
+ case FF_PROFILE_H264_MAIN:
+ initData.codecProfile = STREAMCODEC_PROFILE::H264CodecProfileMain;
+ break;
+ case FF_PROFILE_H264_EXTENDED:
+ initData.codecProfile = STREAMCODEC_PROFILE::H264CodecProfileExtended;
+ break;
+ case FF_PROFILE_H264_HIGH:
+ initData.codecProfile = STREAMCODEC_PROFILE::H264CodecProfileHigh;
+ break;
+ case FF_PROFILE_H264_HIGH_10:
+ initData.codecProfile = STREAMCODEC_PROFILE::H264CodecProfileHigh10;
+ break;
+ case FF_PROFILE_H264_HIGH_422:
+ initData.codecProfile = STREAMCODEC_PROFILE::H264CodecProfileHigh422;
+ break;
+ case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
+ initData.codecProfile = STREAMCODEC_PROFILE::H264CodecProfileHigh444Predictive;
+ break;
+ default:
+ return false;
+ }
+ break;
+ case AV_CODEC_ID_VP8:
+ initData.codec = VIDEOCODEC_INITDATA::CodecVp8;
+ break;
+ case AV_CODEC_ID_VP9:
+ initData.codec = VIDEOCODEC_INITDATA::CodecVp9;
+ break;
+ default:
+ return false;
+ }
+ if (hints.cryptoSession)
+ {
+ switch (hints.cryptoSession->keySystem)
+ {
+ case CRYPTO_SESSION_SYSTEM_NONE:
+ initData.cryptoInfo.m_CryptoKeySystem = CRYPTO_INFO::CRYPTO_KEY_SYSTEM_NONE;
+ break;
+ case CRYPTO_SESSION_SYSTEM_WIDEVINE:
+ initData.cryptoInfo.m_CryptoKeySystem = CRYPTO_INFO::CRYPTO_KEY_SYSTEM_WIDEVINE;
+ break;
+ case CRYPTO_SESSION_SYSTEM_PLAYREADY:
+ initData.cryptoInfo.m_CryptoKeySystem = CRYPTO_INFO::CRYPTO_KEY_SYSTEM_PLAYREADY;
+ break;
+ default:
+ return false;
+ }
+ initData.cryptoInfo.m_CryptoSessionIdSize = hints.cryptoSession->sessionIdSize;
+ //We assume that we need this sessionid only for the directly following call
+ initData.cryptoInfo.m_CryptoSessionId = hints.cryptoSession->sessionId;
+ }
+
+ initData.extraData = reinterpret_cast<const uint8_t*>(hints.extradata);
+ initData.extraDataSize = hints.extrasize;
+ initData.width = hints.width;
+ initData.height = hints.height;
+ initData.videoFormats = m_formats;
+
+ m_displayAspect = (hints.aspect > 0.0 && !hints.forced_aspect) ? static_cast<float>(hints.aspect) : 0.0f;
+ m_width = hints.width;
+ m_height = hints.height;
+
+ m_processInfo.SetVideoDimensions(hints.width, hints.height);
+
+ return true;
+}
+
+bool CAddonVideoCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
+{
+ if (!m_struct.toAddon.open)
+ return false;
+
+ unsigned int nformats(0);
+ for (auto fmt : options.m_formats)
+ if (fmt == RENDER_FMT_YUV420P)
+ {
+ m_formats[nformats++] = VideoFormatYV12;
+ break;
+ }
+ m_formats[nformats] = UnknownVideoFormat;
+
+ if (nformats == 0)
+ return false;
+
+ VIDEOCODEC_INITDATA initData;
+ if (!CopyToInitData(initData, hints))
+ return false;
+
+ m_lastPictureBuffer = nullptr;
+
+ return m_struct.toAddon.open(&m_struct, &initData);
+}
+
+bool CAddonVideoCodec::Reconfigure(CDVDStreamInfo &hints)
+{
+ if (!m_struct.toAddon.reconfigure)
+ return false;
+
+ VIDEOCODEC_INITDATA initData;
+ if (!CopyToInitData(initData, hints))
+ return false;
+
+ return m_struct.toAddon.reconfigure(&m_struct, &initData);
+}
+
+bool CAddonVideoCodec::AddData(const DemuxPacket &packet)
+{
+ if (!m_struct.toAddon.add_data)
+ return false;
+
+ return m_struct.toAddon.add_data(&m_struct, &packet);
+}
+
+CDVDVideoCodec::VCReturn CAddonVideoCodec::GetPicture(VideoPicture* pVideoPicture)
+{
+ if (!m_struct.toAddon.get_picture)
+ return CDVDVideoCodec::VC_ERROR;
+
+ VIDEOCODEC_PICTURE picture;
+ picture.flags = (m_codecFlags & DVD_CODEC_CTRL_DRAIN) ? VIDEOCODEC_PICTURE::FLAG_DRAIN : 0;
+
+ switch (m_struct.toAddon.get_picture(&m_struct, &picture))
+ {
+ case VIDEOCODEC_RETVAL::VC_NONE:
+ return CDVDVideoCodec::VC_NONE;
+ case VIDEOCODEC_RETVAL::VC_ERROR:
+ return CDVDVideoCodec::VC_ERROR;
+ case VIDEOCODEC_RETVAL::VC_BUFFER:
+ return CDVDVideoCodec::VC_BUFFER;
+ case VIDEOCODEC_RETVAL::VC_PICTURE:
+ pVideoPicture->data[0] = picture.decodedData + picture.planeOffsets[0];
+ pVideoPicture->data[1] = picture.decodedData + picture.planeOffsets[1];
+ pVideoPicture->data[2] = picture.decodedData + picture.planeOffsets[2];
+ pVideoPicture->iLineSize[0] = picture.stride[0];
+ pVideoPicture->iLineSize[1] = picture.stride[1];
+ pVideoPicture->iLineSize[2] = picture.stride[2];
+ pVideoPicture->iWidth = picture.width;
+ pVideoPicture->iHeight = picture.height;
+ pVideoPicture->pts = DVD_NOPTS_VALUE;
+ pVideoPicture->dts = DVD_NOPTS_VALUE;
+ pVideoPicture->color_range = 0;
+ pVideoPicture->color_matrix = 4;
+ pVideoPicture->iFlags = DVP_FLAG_ALLOCATED;
+ if (m_codecFlags & DVD_CODEC_CTRL_DROP)
+ pVideoPicture->iFlags |= DVP_FLAG_DROPPED;
+ pVideoPicture->format = RENDER_FMT_YUV420P;
+
+ pVideoPicture->iDisplayWidth = pVideoPicture->iWidth;
+ pVideoPicture->iDisplayHeight = pVideoPicture->iHeight;
+ if (m_displayAspect > 0.0)
+ {
+ pVideoPicture->iDisplayWidth = ((int)lrint(pVideoPicture->iHeight * m_displayAspect)) & ~3;
+ if (pVideoPicture->iDisplayWidth > pVideoPicture->iWidth)
+ {
+ pVideoPicture->iDisplayWidth = pVideoPicture->iWidth;
+ pVideoPicture->iDisplayHeight = ((int)lrint(pVideoPicture->iWidth / m_displayAspect)) & ~3;
+ }
+ }
+
+ if (g_advancedSettings.CanLogComponent(LOGVIDEO))
+ CLog::Log(LOGDEBUG, "CAddonVideoCodec: GetPicture::VC_PICTURE with pts %llu", picture.pts);
+
+ m_bufferPool->ReleaseBuffer(m_lastPictureBuffer);
+ m_lastPictureBuffer = picture.decodedData;
+
+ if (picture.width != m_width || picture.height != m_height)
+ {
+ m_width = picture.width;
+ m_height = picture.height;
+ m_processInfo.SetVideoDimensions(m_width, m_height);
+ }
+
+ return CDVDVideoCodec::VC_PICTURE;
+ case VIDEOCODEC_RETVAL::VC_EOF:
+ return CDVDVideoCodec::VC_EOF;
+ default:
+ return CDVDVideoCodec::VC_ERROR;
+ }
+}
+
+const char* CAddonVideoCodec::GetName()
+{
+ if (m_struct.toAddon.get_name)
+ return m_struct.toAddon.get_name(&m_struct);
+ return "";
+}
+
+void CAddonVideoCodec::Reset()
+{
+ if (!m_struct.toAddon.reset)
+ return;
+
+ CLog::Log(LOGDEBUG, "CAddonVideoCodec: Reset");
+
+ // Get the remaining pictures out of the external decoder
+ VIDEOCODEC_PICTURE picture;
+ picture.flags = VIDEOCODEC_PICTURE::FLAG_DRAIN;
+
+ VIDEOCODEC_RETVAL ret;
+ while ((ret = m_struct.toAddon.get_picture(&m_struct, &picture)) != VIDEOCODEC_RETVAL::VC_EOF)
+ {
+ if (ret == VIDEOCODEC_RETVAL::VC_PICTURE)
+ {
+ m_bufferPool->ReleaseBuffer(m_lastPictureBuffer);
+ m_lastPictureBuffer = picture.decodedData;
+ }
+ }
+ m_bufferPool->ReleaseBuffer(m_lastPictureBuffer);
+ m_lastPictureBuffer = nullptr;
+
+ m_struct.toAddon.reset(&m_struct);
+}
+
+bool CAddonVideoCodec::GetFrameBuffer(VIDEOCODEC_PICTURE &picture)
+{
+ return m_bufferPool->GetBuffer(picture);
+}
+
+/********************* ADDON-TO-KODI **********************/
+
+bool CAddonVideoCodec::get_frame_buffer(void* kodiInstance, VIDEOCODEC_PICTURE *picture)
+{
+ if (!kodiInstance)
+ return false;
+
+ return static_cast<CAddonVideoCodec*>(kodiInstance)->GetFrameBuffer(*picture);
+}
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AddonVideoCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AddonVideoCodec.h
new file mode 100644
index 0000000000..449dc15af4
--- /dev/null
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AddonVideoCodec.h
@@ -0,0 +1,66 @@
+#pragma once
+/*
+ * Copyright (C) 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "DVDVideoCodec.h"
+#include "addons/AddonProvider.h"
+#include "addons/binary-addons/AddonInstanceHandler.h"
+#include "addons/kodi-addon-dev-kit/include/kodi/addon-instance/VideoCodec.h"
+
+class BufferPool;
+
+class CAddonVideoCodec
+ : public CDVDVideoCodec
+ , public ADDON::IAddonInstanceHandler
+{
+public:
+ CAddonVideoCodec(CProcessInfo &processInfo, ADDON::BinaryAddonBasePtr& addonInfo, kodi::addon::IAddonInstance* parentInstance);
+ ~CAddonVideoCodec();
+
+ virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) override;
+ virtual bool Reconfigure(CDVDStreamInfo &hints) override;
+ virtual bool AddData(const DemuxPacket &packet) override;
+ virtual void Reset() override;
+ virtual VCReturn GetPicture(VideoPicture* pVideoPicture) override;
+ virtual const char* GetName() override;
+ virtual void SetCodecControl(int flags) override { m_codecFlags = flags; }
+
+private:
+ bool CopyToInitData(VIDEOCODEC_INITDATA &initData, CDVDStreamInfo &hints);
+
+ /*!
+ * @brief All picture members can be expected to be set correctly except decodedData and pts.
+ * GetFrameBuffer has to set decodedData to a valid memory adress and return true.
+ * In case buffer allocation fails, return false.
+ */
+ bool GetFrameBuffer(VIDEOCODEC_PICTURE &picture);
+
+ static bool get_frame_buffer(void* kodiInstance, VIDEOCODEC_PICTURE *picture);
+
+ AddonInstance_VideoCodec m_struct;
+ int m_codecFlags;
+ VIDEOCODEC_FORMAT m_formats[VIDEOCODEC_FORMAT::MaxVideoFormats + 1];
+ float m_displayAspect;
+ unsigned int m_width, m_height;
+
+ void * m_lastPictureBuffer;
+
+ BufferPool *m_bufferPool;
+};
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/CMakeLists.txt b/xbmc/cores/VideoPlayer/DVDCodecs/Video/CMakeLists.txt
index c3bafb4780..f4f5b07ad2 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/CMakeLists.txt
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/CMakeLists.txt
@@ -1,7 +1,9 @@
-set(SOURCES DVDVideoCodec.cpp
+set(SOURCES AddonVideoCodec.cpp
+ DVDVideoCodec.cpp
DVDVideoCodecFFmpeg.cpp)
-set(HEADERS DVDVideoCodec.h
+set(HEADERS AddonVideoCodec.h
+ DVDVideoCodec.h
DVDVideoCodecFFmpeg.h)
if(NOT ENABLE_EXTERNAL_LIBAV)
diff --git a/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp b/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp
index 05066127a0..0d9311837c 100644
--- a/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp
+++ b/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.cpp
@@ -22,14 +22,34 @@
#include "TimingConstants.h"
#include "addons/binary-addons/AddonDll.h"
#include "addons/binary-addons/BinaryAddonBase.h"
+#include "addons/kodi-addon-dev-kit/include/kodi/addon-instance/VideoCodec.h"
#include "cores/VideoPlayer/DVDClock.h"
#include "cores/VideoPlayer/DVDDemuxers/DVDDemux.h"
#include "cores/VideoPlayer/DVDDemuxers/DVDDemuxUtils.h"
+#include "cores/VideoPlayer/DVDDemuxers/DemuxCrypto.h"
#include "filesystem/SpecialProtocol.h"
#include "utils/StringUtils.h"
#include "utils/URIUtils.h"
+CInputStreamProvider::CInputStreamProvider(ADDON::BinaryAddonBasePtr addonBase, kodi::addon::IAddonInstance* parentInstance)
+ : m_addonBase(addonBase)
+ , m_parentInstance(parentInstance)
+{
+}
+
+void CInputStreamProvider::getAddonInstance(INSTANCE_TYPE instance_type, ADDON::BinaryAddonBasePtr& addonBase, kodi::addon::IAddonInstance*& parentInstance)
+{
+ if (instance_type == ADDON::IAddonProvider::INSTANCE_VIDEOCODEC)
+ {
+ addonBase = m_addonBase;
+ parentInstance = m_parentInstance;
+ }
+}
+
+/*****************************************************************************************************************/
+
using namespace ADDON;
+using namespace kodi::addon;
CInputStreamAddon::CInputStreamAddon(BinaryAddonBasePtr& addonBase, IVideoPlayer* player, const CFileItem& fileitem)
: IAddonInstanceHandler(ADDON_INSTANCE_INPUTSTREAM, addonBase),
@@ -45,8 +65,8 @@ CInputStreamAddon::CInputStreamAddon(BinaryAddonBasePtr& addonBase, IVideoPlayer
StringUtils::Trim(key);
key = name + "." + key;
}
-
m_struct = {{ 0 }};
+ m_caps.m_mask = 0;
}
CInputStreamAddon::~CInputStreamAddon()
@@ -102,6 +122,7 @@ bool CInputStreamAddon::Open()
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;
+ m_struct.toKodi.allocate_encrypted_demux_packet = cb_allocate_encrypted_demux_packet;
if (!CreateInstance(&m_struct) || !m_struct.toAddon.open)
return false;
@@ -306,7 +327,6 @@ CDemuxStream* CInputStreamAddon::GetStream(int streamId) const
auto stream = m_streams.find(streamId);
if (stream != m_streams.end())
return stream->second;
-
return nullptr;
}
@@ -427,6 +447,7 @@ void CInputStreamAddon::UpdateStreams()
videoStream->fAspect = stream.m_Aspect;
videoStream->stereo_mode = "mono";
videoStream->iBitRate = stream.m_BitRate;
+ videoStream->profile = ConvertVideoCodecProfile(stream.m_codecProfile);
demuxStream = videoStream;
}
else if (stream.m_streamType == INPUTSTREAM_INFO::TYPE_SUBTITLE)
@@ -453,6 +474,26 @@ void CInputStreamAddon::UpdateStreams()
demuxStream->ExtraData[j] = stream.m_ExtraData[j];
}
+ if (stream.m_cryptoInfo.m_CryptoKeySystem != CRYPTO_INFO::CRYPTO_KEY_SYSTEM_NONE &&
+ stream.m_cryptoInfo.m_CryptoKeySystem < CRYPTO_INFO::CRYPTO_KEY_SYSTEM_COUNT)
+ {
+ static const CryptoSessionSystem map[] =
+ {
+ CRYPTO_SESSION_SYSTEM_NONE,
+ CRYPTO_SESSION_SYSTEM_WIDEVINE,
+ CRYPTO_SESSION_SYSTEM_PLAYREADY
+ };
+ demuxStream->cryptoSession = std::shared_ptr<DemuxCryptoSession>(new DemuxCryptoSession(
+ map[stream.m_cryptoInfo.m_CryptoKeySystem], stream.m_cryptoInfo.m_CryptoSessionIdSize, stream.m_cryptoInfo.m_CryptoSessionId));
+
+ if ((stream.m_features & INPUTSTREAM_INFO::FEATURE_DECODE) != 0)
+ {
+ if (!m_subAddonProvider)
+ m_subAddonProvider = std::shared_ptr<CInputStreamProvider>(new CInputStreamProvider(GetAddonBase(), m_struct.toAddon.addonInstance));
+
+ demuxStream->externalInterfaces = m_subAddonProvider;
+ }
+ }
m_streams[demuxStream->uniqueId] = demuxStream;
}
}
@@ -464,6 +505,29 @@ void CInputStreamAddon::DisposeStreams()
m_streams.clear();
}
+int CInputStreamAddon::ConvertVideoCodecProfile(STREAMCODEC_PROFILE profile)
+{
+ switch (profile)
+ {
+ case H264CodecProfileBaseline:
+ return FF_PROFILE_H264_BASELINE;
+ case H264CodecProfileMain:
+ return FF_PROFILE_H264_MAIN;
+ case H264CodecProfileExtended:
+ return FF_PROFILE_H264_EXTENDED;
+ case H264CodecProfileHigh:
+ return FF_PROFILE_H264_HIGH;
+ case H264CodecProfileHigh10:
+ return FF_PROFILE_H264_HIGH_10;
+ case H264CodecProfileHigh422:
+ return FF_PROFILE_H264_HIGH_422;
+ case H264CodecProfileHigh444Predictive:
+ return FF_PROFILE_H264_HIGH_444_PREDICTIVE;
+ default:
+ return FF_PROFILE_UNKNOWN;
+ }
+}
+
/*!
* Callbacks from add-on to kodi
*/
@@ -473,8 +537,14 @@ DemuxPacket* CInputStreamAddon::cb_allocate_demux_packet(void* kodiInstance, int
return CDVDDemuxUtils::AllocateDemuxPacket(data_size);
}
+DemuxPacket* CInputStreamAddon::cb_allocate_encrypted_demux_packet(void* kodiInstance, unsigned int dataSize, unsigned int encryptedSubsampleCount)
+{
+ return CDVDDemuxUtils::AllocateDemuxPacket(dataSize, encryptedSubsampleCount);
+}
+
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 f893b5cc0d..4f23448422 100644
--- a/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.h
+++ b/xbmc/cores/VideoPlayer/DVDInputStreams/InputStreamAddon.h
@@ -25,9 +25,23 @@
#include "DVDInputStream.h"
#include "IVideoPlayer.h"
+#include "addons/AddonProvider.h"
#include "addons/binary-addons/AddonInstanceHandler.h"
#include "addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h"
+class CInputStreamProvider
+ : public ADDON::IAddonProvider
+{
+public:
+ CInputStreamProvider(ADDON::BinaryAddonBasePtr addonBase, kodi::addon::IAddonInstance* parentInstance);
+
+ virtual void getAddonInstance(INSTANCE_TYPE instance_type, ADDON::BinaryAddonBasePtr& addonBase, kodi::addon::IAddonInstance*& parentInstance) override;
+
+private:
+ ADDON::BinaryAddonBasePtr m_addonBase;
+ kodi::addon::IAddonInstance* m_parentInstance;
+};
+
//! \brief Input stream class
class CInputStreamAddon
: public ADDON::IAddonInstanceHandler,
@@ -81,6 +95,7 @@ public:
protected:
void UpdateStreams();
void DisposeStreams();
+ int ConvertVideoCodecProfile(STREAMCODEC_PROFILE profile);
IVideoPlayer* m_player;
@@ -90,6 +105,7 @@ private:
std::map<int, CDemuxStream*> m_streams;
AddonInstance_InputStream m_struct;
+ std::shared_ptr<CInputStreamProvider> m_subAddonProvider;
/*!
* Callbacks from add-on to kodi
@@ -104,6 +120,15 @@ private:
static DemuxPacket* cb_allocate_demux_packet(void* kodiInstance, int iDataSize = 0);
/*!
+ * @brief Allocate an encrypted demux packet. Free with FreeDemuxPacket
+ * @param kodiInstance A pointer to the add-on.
+ * @param dataSize The size of the data that will go into the packet
+ * @param encryptedSubsampleCount The number of subsample description blocks to allocate
+ * @return The allocated packet.
+ */
+ static DemuxPacket* cb_allocate_encrypted_demux_packet(void* kodiInstance, unsigned int dataSize, unsigned int encryptedSubsampleCount);
+
+ /*!
* @brief Free a packet that was allocated with AllocateDemuxPacket
* @param kodiInstance A pointer to the add-on.
* @param pPacket The packet to free.
diff --git a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp
index 0be22dab20..4745351b28 100644
--- a/xbmc/video/dialogs/GUIDialogVideoSettings.cpp
+++ b/xbmc/video/dialogs/GUIDialogVideoSettings.cpp
@@ -405,9 +405,14 @@ void CGUIDialogVideoSettings::VideoStreamsOptionFiller(std::shared_ptr<const CSe
}
if (info.videoCodecName.empty())
- strItem += StringUtils::Format(" (%ix%i)", info.width, info.height);
+ strItem += StringUtils::Format(" (%ix%i", info.width, info.height);
else
- strItem += StringUtils::Format(" (%s, %ix%i)", info.videoCodecName.c_str(), info.width, info.height);
+ strItem += StringUtils::Format(" (%s, %ix%i", info.videoCodecName.c_str(), info.width, info.height);
+
+ if (info.bitrate)
+ strItem += StringUtils::Format(", %i bps)", info.bitrate);
+ else
+ strItem += ")";
strItem += StringUtils::Format(" (%i/%i)", i + 1, videoStreamCount);
list.push_back(make_pair(strItem, i));