Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 37 additions & 3 deletions src/CompKodiProps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ constexpr std::string_view PROP_MANIFEST_CONFIG = "inputstream.adaptive.manifest
constexpr std::string_view PROP_STREAM_PARAMS = "inputstream.adaptive.stream_params";
constexpr std::string_view PROP_STREAM_HEADERS = "inputstream.adaptive.stream_headers";

constexpr std::string_view PROP_AUDIO_LANG_ORIG = "inputstream.adaptive.original_audio_language";
constexpr std::string_view PROP_AUDIO_LANG_ORIG = "inputstream.adaptive.original_audio_language"; //! @todo: deprecated, to be removed on Kodi 23
constexpr std::string_view PROP_PLAY_TIMESHIFT_BUFFER = "inputstream.adaptive.play_timeshift_buffer";
constexpr std::string_view PROP_LIVE_DELAY = "inputstream.adaptive.live_delay"; //! @todo: deprecated to be removed on Kodi 23
constexpr std::string_view PROP_PRE_INIT_DATA = "inputstream.adaptive.pre_init_data"; //! @todo: deprecated to be removed on Kodi 23
Expand Down Expand Up @@ -183,10 +183,14 @@ void ADP::KODI_PROPS::CCompKodiProps::InitStage1(const std::map<std::string, std
LogProp(prop.first, prop.second);
ParseHeaderString(m_streamHeaders, prop.second);
}
else if (prop.first == PROP_AUDIO_LANG_ORIG)
else if (prop.first == PROP_AUDIO_LANG_ORIG) //! @todo: deprecated, to be removed on Kodi 23
{
LOG::Log(LOGWARNING, "Warning \"inputstream.adaptive.original_audio_language\" property is "
"deprecated and will be removed on next Kodi version.\n"
"Please read Wiki \"Integration\" page to learn more about the new "
"parameters of \"inputstream.adaptive.config\".");
LogProp(prop.first, prop.second);
m_audioLanguageOrig = prop.second;
m_config.mediaAudioLangCodeOrig = prop.second;
}
else if (prop.first == PROP_PLAY_TIMESHIFT_BUFFER)
{
Expand Down Expand Up @@ -357,6 +361,36 @@ void ADP::KODI_PROPS::CCompKodiProps::ParseConfig(const std::string& data)
}
}
}
else if (configName == "media_audio_langcode_default" && jValue.is_string())
{
m_config.mediaAudioLangCodeDef = jValue.get<std::string>();
}
else if (configName == "media_audio_langcode_original" && jValue.is_string())
{
m_config.mediaAudioLangCodeOrig = jValue.get<std::string>();
}
else if (configName == "media_subtitle_langcode_default" && jValue.is_string())
{
m_config.mediaSubtitleLangCodeDef = jValue.get<std::string>();
}
else if (configName == "media_audio_type_pref" && jValue.is_string())
{
// Accepted values mimic Kodi VP language settings: "original", "impaired", "default"
if (jValue == "" || jValue == "default")
m_config.mediaAudioTypePref = MediaFlagType::DEFAULT;
else if (jValue == "original")
m_config.mediaAudioTypePref = MediaFlagType::ORIGINAL;
else if (jValue == "impaired")
m_config.mediaAudioTypePref = MediaFlagType::IMPAIRED;
else
LOG::LogF(LOGERROR, "Value \"%s\" isnt supported on \"%s\" parameter of \"%s\" property",
jValue.get<std::string>().c_str(), configName.c_str(),
PROP_MANIFEST_CONFIG.data());
}
else if (configName == "media_audio_stereo_pref" && jValue.is_boolean())
{
m_config.mediaAudioStereoPref = jValue.get<bool>();
}
else
{
LOG::LogF(LOGERROR, "Unsupported \"%s\" config or wrong data type on \"%s\" property",
Expand Down
24 changes: 20 additions & 4 deletions src/CompKodiProps.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ enum class HdcpCheckType
LICENSE, // To check HDCP values from DRM license response
};

enum class MediaFlagType
{
DEFAULT,
ORIGINAL,
IMPAIRED,
};

// Generic add-on configuration
struct Config
{
Expand All @@ -53,6 +60,19 @@ struct Config
HdcpCheckType hdcpCheck{HdcpCheckType::DEFAULT};
// Force limit resolutions of manifest streams to the specified value included (value in px, height x width)
int resolutionLimit{0};

// To override "default" media flag on audio streams that have the specified language code (IETF BCP-47)
std::string mediaAudioLangCodeDef;
// To override "original" media flag on audio streams that have the specified language code (IETF BCP-47)
std::string mediaAudioLangCodeOrig;
// To override "default" media flag on subtitles streams that have the specified language code (IETF BCP-47)
std::string mediaSubtitleLangCodeDef;
// Defines what type of audio tracks should be preferred for the "default"/"impaired" flag
// (applicable when using media flag override)
MediaFlagType mediaAudioTypePref{MediaFlagType::DEFAULT};
// Defines if stereo audio tracks are preferred over multichannels one
// (applicable when using media flag override)
bool mediaAudioStereoPref{false};
};

struct ManifestConfig
Expand Down Expand Up @@ -154,9 +174,6 @@ class ATTR_DLL_LOCAL CCompKodiProps
// \brief HTTP headers used to download streams
std::map<std::string, std::string> GetStreamHeaders() const { return m_streamHeaders; }

// \brief Get language code to identify the audio track in original language
std::string GetAudioLangOrig() const { return m_audioLanguageOrig; }

// \brief Specify to start playing a LIVE stream from the beginning of the buffer instead of its end
bool IsPlayTimeshift() const { return m_playTimeshiftBuffer; }

Expand Down Expand Up @@ -192,7 +209,6 @@ class ATTR_DLL_LOCAL CCompKodiProps
std::map<std::string, std::string> m_manifestHeaders;
std::string m_streamParams;
std::map<std::string, std::string> m_streamHeaders;
std::string m_audioLanguageOrig;
bool m_playTimeshiftBuffer{false};
ChooserProps m_chooserProps;
Config m_config;
Expand Down
16 changes: 3 additions & 13 deletions src/Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,12 +314,6 @@ void SESSION::CSession::InitializePeriod()
return;

CHOOSER::StreamSelection streamSelectionMode = m_reprChooser->GetStreamSelectionMode();
//! @todo: GetAudioLangOrig property should be reworked to allow override or set
//! manifest a/v and subtitles streams attributes such as default/original etc..
//! since Kodi stream flags dont have always the same meaning of manifest attributes
//! and some video services dont follow exactly the specs so can lead to wrong Kodi flags sets.
//! An idea is add/move these override of attributes on post manifest parsing.
std::string audioLanguageOrig = CSrvBroker::GetKodiProps().GetAudioLangOrig();

// For multi-codec manifests, determine which codec to use by default,
// then choose the appropriate AdaptationSet. It may also depend on the Chooser behavior.
Expand Down Expand Up @@ -369,7 +363,7 @@ void SESSION::CSession::InitializePeriod()
const uint32_t uniqueId = MakeUniqueId(periodIndex, streamIndex);
const bool isDefaultVideoRepr{isDefaultAdpSet && repr == defaultRepr};

AddStream(adp.get(), repr, isDefaultVideoRepr, uniqueId, audioLanguageOrig);
AddStream(adp.get(), repr, isDefaultVideoRepr, uniqueId);
++streamIndex;
return true;
};
Expand Down Expand Up @@ -417,8 +411,7 @@ void SESSION::CSession::InitializePeriod()
void SESSION::CSession::AddStream(PLAYLIST::CAdaptationSet* adp,
PLAYLIST::CRepresentation* initialRepr,
bool isDefaultVideoRepr,
uint32_t uniqueId,
std::string_view audioLanguageOrig)
uint32_t uniqueId)
{
m_streams.push_back(std::make_shared<CStream>(m_adaptiveTree, adp, initialRepr));

Expand All @@ -443,11 +436,8 @@ void SESSION::CSession::AddStream(PLAYLIST::CAdaptationSet* adp,
flags |= INPUTSTREAM_FLAG_VISUAL_IMPAIRED;
if (adp->IsDefault())
flags |= INPUTSTREAM_FLAG_DEFAULT;
if (adp->IsOriginal() || (!audioLanguageOrig.empty() &&
adp->GetLanguage() == audioLanguageOrig))
{
if (adp->IsOriginal())
flags |= INPUTSTREAM_FLAG_ORIGINAL;
}
break;
}
case StreamType::SUBTITLE:
Expand Down
3 changes: 1 addition & 2 deletions src/Session.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ class ATTR_DLL_LOCAL CSession : public adaptive::AdaptiveStreamObserver
void AddStream(PLAYLIST::CAdaptationSet* adp,
PLAYLIST::CRepresentation* repr,
bool isDefaultVideoRepr,
uint32_t uniqueId,
std::string_view audioLanguageOrig);
uint32_t uniqueId);

/*! \brief Update stream's InputstreamInfo
* \param stream The stream to update
Expand Down
60 changes: 60 additions & 0 deletions src/common/AdaptationSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,3 +247,63 @@ PLAYLIST::CAdaptationSet* PLAYLIST::CAdaptationSet::FindByFirstAVStream(

return adp;
}

std::vector<std::unique_ptr<CAdaptationSet>>::const_iterator PLAYLIST::CAdaptationSet::
FindAudioAdpSet(const std::vector<std::unique_ptr<CAdaptationSet>>& adpSets,
const std::string langCode,
bool isPreferStereo)
{
for (auto itAdpSet = adpSets.cbegin(); itAdpSet != adpSets.cend(); ++itAdpSet)
{
auto adpSet = itAdpSet->get();
if (adpSet->GetStreamType() == StreamType::AUDIO &&
STRING::CompareNoCase(adpSet->GetLanguage(), langCode) &&
!adpSet->GetRepresentations().empty() &&
(isPreferStereo ? adpSet->GetRepresentations()[0]->GetAudioChannels() <= 2
: adpSet->GetRepresentations()[0]->GetAudioChannels() > 2))
{
return itAdpSet;
}
}
return adpSets.end();
}

std::vector<std::unique_ptr<CAdaptationSet>>::const_iterator PLAYLIST::CAdaptationSet::
FindAudioAdpSet(const std::vector<std::unique_ptr<CAdaptationSet>>& adpSets,
const std::string langCode,
bool isPreferStereo,
bool filterImpaired)
{
for (auto itAdpSet = adpSets.cbegin(); itAdpSet != adpSets.cend(); ++itAdpSet)
{
auto adpSet = itAdpSet->get();
if (adpSet->GetStreamType() == StreamType::AUDIO &&
STRING::CompareNoCase(adpSet->GetLanguage(), langCode) &&
!adpSet->GetRepresentations().empty() &&
(isPreferStereo ? adpSet->GetRepresentations()[0]->GetAudioChannels() <= 2
: adpSet->GetRepresentations()[0]->GetAudioChannels() > 2) &&
adpSet->IsImpaired() == filterImpaired)
Comment thread
CastagnaIT marked this conversation as resolved.
{
return itAdpSet;
}
}
return adpSets.end();
}

std::vector<std::unique_ptr<CAdaptationSet>>::const_iterator PLAYLIST::CAdaptationSet::
FindSubtitleAdpSet(const std::vector<std::unique_ptr<CAdaptationSet>>& adpSets,
const std::string langCode,
bool filterImpaired)
{
for (auto itAdpSet = adpSets.cbegin(); itAdpSet != adpSets.cend(); ++itAdpSet)
{
auto adpSet = itAdpSet->get();
if (adpSet->GetStreamType() == StreamType::SUBTITLE &&
STRING::CompareNoCase(adpSet->GetLanguage(), langCode) &&
!adpSet->GetRepresentations().empty() && adpSet->IsImpaired() == filterImpaired)
{
return itAdpSet;
}
}
return adpSets.end();
}
16 changes: 16 additions & 0 deletions src/common/AdaptationSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,22 @@ class ATTR_DLL_LOCAL CAdaptationSet : public CCommonSegAttribs, public CCommonAt
*/
static CAdaptationSet* FindByFirstAVStream(std::vector<std::unique_ptr<CAdaptationSet>>& adpSets);

static std::vector<std::unique_ptr<CAdaptationSet>>::const_iterator FindAudioAdpSet(
const std::vector<std::unique_ptr<CAdaptationSet>>& adpSets,
const std::string langCode,
bool isPreferStereo);

static std::vector<std::unique_ptr<CAdaptationSet>>::const_iterator FindAudioAdpSet(
const std::vector<std::unique_ptr<CAdaptationSet>>& adpSets,
const std::string langCode,
bool isPreferStereo,
bool filterImpaired);

static std::vector<std::unique_ptr<CAdaptationSet>>::const_iterator FindSubtitleAdpSet(
const std::vector<std::unique_ptr<CAdaptationSet>>& adpSets,
const std::string langCode,
bool filterImpaired);

protected:
std::vector<std::unique_ptr<CRepresentation>> m_representations;

Expand Down
Loading
Loading