Skip to content

Commit

Permalink
temp
Browse files Browse the repository at this point in the history
  • Loading branch information
phunkyfish committed Oct 4, 2024
1 parent 383e8c8 commit dae01b2
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 17 deletions.
7 changes: 5 additions & 2 deletions src/IptvSimple.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -412,11 +412,14 @@ PVR_ERROR IptvSimple::GetRecordings(bool deleted, kodi::addon::PVRRecordingsResu

PVR_ERROR IptvSimple::GetRecordingStreamProperties(const kodi::addon::PVRRecording& recording, std::vector<kodi::addon::PVRStreamProperty>& properties)
{
auto mediaEntry = m_media.GetMediaEntry(recording);
std::string url = m_media.GetMediaEntryURL(recording);

if (!url.empty())
if (mediaEntry && !url.empty())
{
properties.emplace_back(PVR_STREAM_PROPERTY_STREAMURL, url);
std::map<std::string, std::string> catchupProperties;

StreamUtils::SetAllStreamProperties(properties, mediaEntry, url, false, m_settings);

return PVR_ERROR_NO_ERROR;
}
Expand Down
12 changes: 12 additions & 0 deletions src/iptvsimple/Media.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,18 @@ bool Media::IsInVirtualMediaEntryFolder(const MediaEntry& mediaEntryToCheck) con
return false;
}

const MediaEntry* Media::GetMediaEntry(const kodi::addon::PVRRecording& recording)
{
Logger::Log(LEVEL_INFO, "%s", __func__);

auto mediaEntry = GetMediaEntry(recording.GetRecordingId());

if (mediaEntry)
return &myMediaEntry;

return nullptr;
}

const std::string Media::GetMediaEntryURL(const kodi::addon::PVRRecording& recording)
{
Logger::Log(LEVEL_INFO, "%s", __func__);
Expand Down
1 change: 1 addition & 0 deletions src/iptvsimple/Media.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ namespace iptvsimple
void GetMedia(std::vector<kodi::addon::PVRRecording>& kodiRecordings);
int GetNumMedia() const;
void Clear();
const MediaEntry* GetMediaEntry(const kodi::addon::PVRRecording& mediaEntry);
const std::string GetMediaEntryURL(const kodi::addon::PVRRecording& mediaEntry);
const iptvsimple::data::MediaEntry* FindMediaEntry(const std::string& id, const std::string& displayName) const;

Expand Down
4 changes: 2 additions & 2 deletions src/iptvsimple/StreamManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ StreamEntry StreamManager::StreamEntryLookup(const Channel& channel, const std::

if (!streamEntry)
{
StreamType streamType = StreamUtils::GetStreamType(streamTestUrl, channel);
StreamType streamType = StreamUtils::GetStreamType(streamTestUrl, channel.GetProperty(PVR_STREAM_PROPERTY_MIMETYPE), channel.IsCatchupTSStream());
if (streamType == StreamType::OTHER_TYPE)
streamType = StreamUtils::InspectStreamType(streamTestUrl, channel);
streamType = StreamUtils::InspectStreamType(streamTestUrl, channel.GetCatchupMode());

streamEntry = std::make_shared<StreamEntry>();
streamEntry->SetStreamKey(streamKey);
Expand Down
122 changes: 111 additions & 11 deletions src/iptvsimple/utilities/StreamUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ void StreamUtils::SetAllStreamProperties(std::vector<kodi::addon::PVRStreamPrope
}
else
{
StreamType streamType = StreamUtils::GetStreamType(streamURL, channel);
StreamType streamType = StreamUtils::GetStreamType(streamURL, channel.GetProperty(PVR_STREAM_PROPERTY_MIMETYPE), channel.IsCatchupTSStream());
if (streamType == StreamType::OTHER_TYPE)
streamType = StreamUtils::InspectStreamType(streamURL, channel);
streamType = StreamUtils::InspectStreamType(streamURL, channel.GetCatchupMode());

// Using kodi's built in inputstreams
if (!isISAdaptiveSet && StreamUtils::UseKodiInputstreams(streamType, settings))
Expand Down Expand Up @@ -132,7 +132,7 @@ void StreamUtils::SetAllStreamProperties(std::vector<kodi::addon::PVRStreamPrope

if (!isISAdaptiveSet)
properties.emplace_back(PVR_STREAM_PROPERTY_INPUTSTREAM, INPUTSTREAM_ADAPTIVE);

if (streamType == StreamType::HLS || streamType == StreamType::DASH ||
streamType == StreamType::SMOOTH_STREAMING)
properties.emplace_back(PVR_STREAM_PROPERTY_MIMETYPE, StreamUtils::GetMimeType(streamType));
Expand All @@ -151,6 +151,106 @@ void StreamUtils::SetAllStreamProperties(std::vector<kodi::addon::PVRStreamPrope
properties.emplace_back(prop.first, prop.second);
}
}

void StreamUtils::SetAllStreamProperties(std::vector<kodi::addon::PVRStreamProperty>& properties, const iptvsimple::data::MediaEntry& mediaEntry, const std::string& streamURL, std::shared_ptr<InstanceSettings>& settings)
{
// Check if the media entry has explicitly set up the use of inputstream.adaptive,
// if so, the best behaviour for media services is:
// - Always add mimetype to prevent kodi core to make an HTTP HEADER requests
// this because in some cases services refuse this request and can also deny downloads
// - If requested by settings, always add the "user-agent" header to ISA properties
const bool isISAdaptiveSet =
mediaEntry.GetProperty(PVR_STREAM_PROPERTY_INPUTSTREAM) == INPUTSTREAM_ADAPTIVE;

if (!isISAdaptiveSet && !mediaEntry.GetInputStreamName().empty())
{
// Media Entry has an inputstream class set so we only set the stream URL
properties.emplace_back(PVR_STREAM_PROPERTY_STREAMURL, streamURL);

if (mediaEntry.GetInputStreamName() != PVR_STREAM_PROPERTY_VALUE_INPUTSTREAMFFMPEG)
CheckInputstreamInstalledAndEnabled(mediaEntry.GetInputStreamName());

if (mediaEntry.GetInputStreamName() == INPUTSTREAM_FFMPEGDIRECT)
InspectAndSetFFmpegDirectStreamProperties(properties, channel, streamURL, isChannelURL, settings);
}
else
{
StreamType streamType = StreamUtils::GetStreamType(streamURL, mediaEntry.GetProperty(PVR_STREAM_PROPERTY_MIMETYPE), false);
if (streamType == StreamType::OTHER_TYPE)
streamType = StreamUtils::InspectStreamType(streamURL, CatchupMode::DISABLED);

// Using kodi's built in inputstreams
if (!isISAdaptiveSet && StreamUtils::UseKodiInputstreams(streamType, settings))
{
std::string ffmpegStreamURL = StreamUtils::GetURLWithFFmpegReconnectOptions(streamURL, streamType, channel, settings);

properties.emplace_back(PVR_STREAM_PROPERTY_STREAMURL, streamURL);
if (!channel.HasMimeType() && StreamUtils::HasMimeType(streamType))
properties.emplace_back(PVR_STREAM_PROPERTY_MIMETYPE, StreamUtils::GetMimeType(streamType));

if (streamType == StreamType::HLS || streamType == StreamType::TS || streamType == StreamType::OTHER_TYPE)
{
if (channel.SupportsLiveStreamTimeshifting() && isChannelURL &&
CheckInputstreamInstalledAndEnabled(INPUTSTREAM_FFMPEGDIRECT))
{
properties.emplace_back(PVR_STREAM_PROPERTY_INPUTSTREAM, INPUTSTREAM_FFMPEGDIRECT);
// this property is required to force VideoPlayer for Radio media entries
properties.emplace_back("inputstream-player", "videodefaultplayer");
SetFFmpegDirectManifestTypeStreamProperty(properties, channel, streamURL, streamType);
properties.emplace_back("inputstream.ffmpegdirect.stream_mode", "timeshift");
properties.emplace_back("inputstream.ffmpegdirect.is_realtime_stream", "true");
}
else if (streamType == StreamType::HLS || streamType == StreamType::TS)
{
properties.emplace_back(PVR_STREAM_PROPERTY_INPUTSTREAM, PVR_STREAM_PROPERTY_VALUE_INPUTSTREAMFFMPEG);
}
}
}
else // inputstream.adaptive
{
CheckInputstreamInstalledAndEnabled(INPUTSTREAM_ADAPTIVE);

bool streamUrlSet = false;

// If no media headers are explicitly set for inputstream.adaptive,
// strip the headers from streamURL and put it to media headers property

if (mediaEntry.GetProperty("inputstream.adaptive.manifest_headers").empty() &&
mediaEntry.GetProperty("inputstream.adaptive.stream_headers").empty())
{
// No stream headers declared by property, check if stream URL has any
std::string url;
std::string encodedProtocolOptions;
if (SplitUrlProtocolOpts(streamURL, url, encodedProtocolOptions))
{
// Set stream URL without headers and encoded headers as property
properties.emplace_back(PVR_STREAM_PROPERTY_STREAMURL, url);
properties.emplace_back("inputstream.adaptive.manifest_headers", encodedProtocolOptions);
properties.emplace_back("inputstream.adaptive.stream_headers", encodedProtocolOptions);
streamUrlSet = true;
}
}

// Set intact stream URL if not previously set
if (!streamUrlSet)
properties.emplace_back(PVR_STREAM_PROPERTY_STREAMURL, streamURL);

if (!isISAdaptiveSet)
properties.emplace_back(PVR_STREAM_PROPERTY_INPUTSTREAM, INPUTSTREAM_ADAPTIVE);

if (streamType == StreamType::HLS || streamType == StreamType::DASH ||
streamType == StreamType::SMOOTH_STREAMING)
properties.emplace_back(PVR_STREAM_PROPERTY_MIMETYPE, StreamUtils::GetMimeType(streamType));
}
}

if (!mediaEntry.GetProperties().empty())
{
for (auto& prop : channel.GetProperties())
properties.emplace_back(prop.first, prop.second);
}
}

bool StreamUtils::CheckInputstreamInstalledAndEnabled(const std::string& inputstreamName)
{
std::string version;
Expand Down Expand Up @@ -178,9 +278,9 @@ void StreamUtils::InspectAndSetFFmpegDirectStreamProperties(std::vector<kodi::ad
// If there is no MIME type and no manifest type (BOTH!) set then potentially inspect the stream and set them
if (!channel.HasMimeType() && !channel.GetProperty("inputstream.ffmpegdirect.manifest_type").empty())
{
StreamType streamType = StreamUtils::GetStreamType(streamURL, channel);
StreamType streamType = StreamUtils::GetStreamType(streamURL, channel.GetProperty(PVR_STREAM_PROPERTY_MIMETYPE), channel.IsCatchupTSStream());
if (streamType == StreamType::OTHER_TYPE)
streamType = StreamUtils::InspectStreamType(streamURL, channel);
streamType = StreamUtils::InspectStreamType(streamURL, channel.GetCatchupMode());

if (!channel.HasMimeType() && StreamUtils::HasMimeType(streamType))
properties.emplace_back(PVR_STREAM_PROPERTY_MIMETYPE, StreamUtils::GetMimeType(streamType));
Expand Down Expand Up @@ -232,7 +332,7 @@ std::string StreamUtils::GetEffectiveInputStreamName(const StreamType& streamTyp
return inputStreamName;
}

const StreamType StreamUtils::GetStreamType(const std::string& url, const Channel& channel)
const StreamType StreamUtils::GetStreamType(const std::string& url, const std::string& mimeType, bool isCatchupTSStream)
{
if (StringUtils::StartsWith(url, "plugin://"))
return StreamType::PLUGIN;
Expand Down Expand Up @@ -261,7 +361,7 @@ const StreamType StreamUtils::GetStreamType(const std::string& url, const Channe
return StreamType::OTHER_TYPE;
}

const StreamType StreamUtils::InspectStreamType(const std::string& url, const Channel& channel)
const StreamType StreamUtils::InspectStreamType(const std::string& url, CatchupMode catchupMode)
{
if (!FileUtils::FileExists(url))
return StreamType::OTHER_TYPE;
Expand All @@ -282,10 +382,10 @@ const StreamType StreamUtils::InspectStreamType(const std::string& url, const Ch
}

// If we can't inspect the stream type the only option left for default, append or shift mode is TS
if (channel.GetCatchupMode() == CatchupMode::DEFAULT ||
channel.GetCatchupMode() == CatchupMode::APPEND ||
channel.GetCatchupMode() == CatchupMode::SHIFT ||
channel.GetCatchupMode() == CatchupMode::TIMESHIFT)
if (catchupMode == CatchupMode::DEFAULT ||
catchupMode == CatchupMode::APPEND ||
catchupMode == CatchupMode::SHIFT ||
catchupMode == CatchupMode::TIMESHIFT)
return StreamType::TS;

return StreamType::OTHER_TYPE;
Expand Down
5 changes: 3 additions & 2 deletions src/iptvsimple/utilities/StreamUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ namespace iptvsimple
{
public:
static void SetAllStreamProperties(std::vector<kodi::addon::PVRStreamProperty>& properties, const iptvsimple::data::Channel& channel, const std::string& streamUrl, bool isChannelURL, std::map<std::string, std::string>& catchupProperties, std::shared_ptr<iptvsimple::InstanceSettings>& settings);
static const StreamType GetStreamType(const std::string& url, const iptvsimple::data::Channel& channel);
static const StreamType InspectStreamType(const std::string& url, const iptvsimple::data::Channel& channel);
static void SetAllStreamProperties(std::vector<kodi::addon::PVRStreamProperty>& properties, const iptvsimple::data::MediaEntry& mediaEntry, const std::string& streamUrl, std::shared_ptr<iptvsimple::InstanceSettings>& settings);
static const StreamType GetStreamType(const std::string& url, const std::string& mimeType, bool isCatchupTSStream);
static const StreamType InspectStreamType(const std::string& url, iptvsimple::CatchupMode catchupMode);
static const std::string GetManifestType(const StreamType& streamType);
static const std::string GetMimeType(const StreamType& streamType);
static bool HasMimeType(const StreamType& streamType);
Expand Down

0 comments on commit dae01b2

Please sign in to comment.