Skip to content

Commit

Permalink
Merge pull request #19983 from the-black-eagle/hdr_streamdetails
Browse files Browse the repository at this point in the history
Detect, store and process the type of HDR in a video file
  • Loading branch information
the-black-eagle committed Jan 8, 2022
2 parents 1d0dc77 + 246d5c8 commit 63c8427
Show file tree
Hide file tree
Showing 23 changed files with 135 additions and 13 deletions.
8 changes: 7 additions & 1 deletion addons/resource.language.en_gb/resources/strings.po
Expand Up @@ -13796,7 +13796,13 @@ msgctxt "#20473"
msgid "Premiered"
msgstr ""

#empty strings from id 20474 to 21329
#. Used in smart playlists to select items based on the HDR type (HDR10, HLG, Dolbyvision)
#: xbmc/playlists/SmartPlayList.cpp
msgctxt "#20474"
msgid "HDR type"
msgstr ""

#empty strings from id 20475 to 21329
#up to 21329 is reserved for the video db !! !

#: system/settings/settings.xml
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added addons/skin.estuary/media/flags/videohdr/hlg.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 5 additions & 1 deletion addons/skin.estuary/xml/DialogSeekBar.xml
Expand Up @@ -57,7 +57,7 @@
<align>right</align>
<include>Animation_BottomSlide</include>
<orientation>horizontal</orientation>
<itemgap>10</itemgap>
<itemgap>5</itemgap>
<visible>[Player.ShowInfo | Window.IsActive(fullscreeninfo)] + !Player.ChannelPreviewActive + Window.IsActive(fullscreenvideo)</visible>
<animation effect="fade" start="0" end="100" time="200" delay="1000">Visible</animation>
<include content="MediaFlag">
Expand All @@ -66,6 +66,10 @@
<include content="MediaFlag">
<param name="texture" value="$INFO[VideoPlayer.VideoResolution,flags/videoresolution/,.png]" />
</include>
<include content="MediaFlag">
<param name="texture" value="$INFO[VideoPlayer.HdrType,flags/videohdr/,.png]" />
<param name="visible" value="!String.IsEmpty(VideoPlayer.HdrType)" />
</include>
<include content="MediaFlag">
<param name="texture" value="$INFO[VideoPlayer.VideoAspect,flags/aspectratio/,.png]" />
</include>
Expand Down
4 changes: 4 additions & 0 deletions addons/skin.estuary/xml/Includes.xml
Expand Up @@ -402,6 +402,10 @@
<param name="texture" value="$PARAM[resolution_var]" />
<param name="visible" value="!String.IsEmpty($PARAM[infolabel_prefix]ListItem.VideoResolution)" />
</include>
<include content="MediaFlag">
<param name="texture" value="$INFO[ListItem.HdrType,flags/videohdr/,.png]" />
<param name="visible" value="!String.IsEmpty($PARAM[infolabel_prefix]ListItem.HdrType)" />
</include>
<include content="MediaFlag">
<param name="texture" value="$INFO[ListItem.VideoAspect,flags/aspectratio/,.png]" />
<param name="visible" value="!String.IsEmpty($PARAM[infolabel_prefix]ListItem.VideoAspect)" />
Expand Down
16 changes: 16 additions & 0 deletions xbmc/GUIInfoManager.cpp
Expand Up @@ -3759,6 +3759,13 @@ const infomap musicplayer[] = {{ "title", MUSICPLAYER_TITLE },
/// @skinning_v20 **[New Infolabel]** \link VideoPlayer_AudioStreamCount `VideoPlayer.AudioStreamCount`\endlink
/// <p>
/// }
///   \table_row3{   <b>`VideoPlayer.HdrType`</b>,
///                  \anchor VideoPlayer_HdrType
///                  _string_,
///     @return String containing the name of the detected HDR type or empty if not HDR. See \ref StreamHdrType for the list of possible values.
///     <p><hr>
///     @skinning_v20 **[New Infolabel]** \link ListItem_HdrType `ListItem.HdrType`\endlink
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -3832,6 +3839,7 @@ const infomap videoplayer[] = {{ "title", VIDEOPLAYER_TITLE },
{ "uniqueid", VIDEOPLAYER_UNIQUEID },
{ "tvshowdbid", VIDEOPLAYER_TVSHOWDBID },
{ "audiostreamcount", VIDEOPLAYER_AUDIOSTREAMCOUNT },
{ "hdrtype", VIDEOPLAYER_HDR_TYPE },
};

/// \page modules__infolabels_boolean_conditions
Expand Down Expand Up @@ -6700,6 +6708,13 @@ const infomap container_str[] = {{ "property", CONTAINER_PROPERTY },
/// <p><hr>
/// @skinning_v19 **[New Infolabel]** \link ListItem_AlbumStatus `ListItem.AlbumStatus`\endlink
/// }
///   \table_row3{   <b>`ListItem.HdrType`</b>,
///                  \anchor ListItem_HdrType
///                  _string_,
///     @return String containing the name of the detected HDR type or empty if not HDR. See \ref StreamHdrType for the list of possible values.
///     <p><hr>
///     @skinning_v20 **[New Infolabel]** \link ListItem_HdrType `ListItem.HdrType`\endlink
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -6911,6 +6926,7 @@ const infomap listitem_labels[]= {{ "thumb", LISTITEM_THUMB },
{ "tvshowdbid", LISTITEM_TVSHOWDBID },
{ "albumstatus", LISTITEM_ALBUMSTATUS },
{ "isautoupdateable", LISTITEM_ISAUTOUPDATEABLE },
{ "hdrtype", LISTITEM_VIDEO_HDR_TYPE },
};

/// \page modules__infolabels_boolean_conditions
Expand Down
1 change: 1 addition & 0 deletions xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemux.h
Expand Up @@ -148,6 +148,7 @@ class CDemuxStreamVideo : public CDemuxStream
std::shared_ptr<AVContentLightMetadata> contentLightMetaData;

std::string stereo_mode; // expected stereo mode
StreamHdrType hdr_type = StreamHdrType::HDR_TYPE_NONE; // type of HDR for this stream (hdr10, etc)
};

class CDemuxStreamAudio : public CDemuxStream
Expand Down
23 changes: 21 additions & 2 deletions xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
Expand Up @@ -511,13 +511,17 @@ bool CDVDDemuxFFmpeg::Open(const std::shared_ptr<CDVDInputStream>& pInput, bool

bool skipCreateStreams = false;
bool isBluray = pInput->IsStreamType(DVDSTREAM_TYPE_BLURAY);
if (iformat && (strcmp(iformat->name, "mpegts") == 0) && !fileinfo && !isBluray)
// don't re-open mpegts streams with hevc encoding as the params are not correctly detected again
if (iformat && (strcmp(iformat->name, "mpegts") == 0) && !fileinfo && !isBluray &&
m_pFormatContext->streams[0]->codecpar->codec_id != AV_CODEC_ID_HEVC)
{
av_opt_set_int(m_pFormatContext, "analyzeduration", 500000, 0);
m_checkTransportStream = true;
skipCreateStreams = true;
}
else if (!iformat || (strcmp(iformat->name, "mpegts") != 0))
else if (!iformat || ((strcmp(iformat->name, "mpegts") != 0) ||
((strcmp(iformat->name, "mpegts") == 0) &&
m_pFormatContext->streams[0]->codecpar->codec_id == AV_CODEC_ID_HEVC)))
{
m_streaminfo = true;
}
Expand Down Expand Up @@ -1643,11 +1647,26 @@ CDemuxStream* CDVDDemuxFFmpeg::AddStream(int streamIdx)
int size = 0;
uint8_t* side_data = nullptr;

side_data = av_stream_get_side_data(pStream, AV_PKT_DATA_DOVI_CONF, &size);
if (side_data && size)
st->hdr_type = StreamHdrType::HDR_TYPE_DOLBYVISION;
else if (st->colorPrimaries == AVCOL_PRI_BT2020)
{
if (st->colorTransferCharacteristic == AVCOL_TRC_SMPTE2084) // hdr10
st->hdr_type = StreamHdrType::HDR_TYPE_HDR10;
else if (st->colorTransferCharacteristic == AVCOL_TRC_ARIB_STD_B67) // hlg
st->hdr_type = StreamHdrType::HDR_TYPE_HLG;
}

side_data = av_stream_get_side_data(pStream, AV_PKT_DATA_MASTERING_DISPLAY_METADATA, &size);
if (side_data && size)
{
st->masteringMetaData = std::make_shared<AVMasteringDisplayMetadata>(
*reinterpret_cast<AVMasteringDisplayMetadata*>(side_data));
// file could be SMPTE2086 which FFmpeg currently returns as unknown so use the presence
// of static metadata to detect it
if (st->masteringMetaData->has_primaries && st->masteringMetaData->has_luminance)
st->hdr_type = StreamHdrType::HDR_TYPE_HDR10;
}

side_data = av_stream_get_side_data(pStream, AV_PKT_DATA_CONTENT_LIGHT_LEVEL, &size);
Expand Down
1 change: 1 addition & 0 deletions xbmc/cores/VideoPlayer/DVDFileInfo.cpp
Expand Up @@ -396,6 +396,7 @@ bool CDVDFileInfo::DemuxerToStreamDetails(const std::shared_ptr<CDVDInputStream>
p->m_iDuration = pDemux->GetStreamLength();
p->m_strStereoMode = vstream->stereo_mode;
p->m_strLanguage = vstream->language;
p->m_strHdrType = CStreamDetails::HdrTypeToString(vstream->hdr_type);

// stack handling
if (URIUtils::IsStack(path))
Expand Down
9 changes: 9 additions & 0 deletions xbmc/cores/VideoPlayer/Interface/StreamInfo.h
Expand Up @@ -30,6 +30,14 @@ enum StreamFlags
FLAG_STILL_IMAGES = 0x100000
};

enum class StreamHdrType
{
HDR_TYPE_NONE, /// < will return an empty string
HDR_TYPE_HDR10, /// < returns "hdr10" when converted to a string
HDR_TYPE_DOLBYVISION, /// < returns "dolbyvision"
HDR_TYPE_HLG /// < returns "hlg"
};

struct StreamInfo
{
bool valid = false;
Expand Down Expand Up @@ -64,6 +72,7 @@ struct VideoStreamInfo : StreamInfo
CRect VideoRect;
std::string stereoMode;
int angles = 0;
StreamHdrType hdrType = StreamHdrType::HDR_TYPE_NONE;
};

struct ProgramInfo
Expand Down
2 changes: 2 additions & 0 deletions xbmc/cores/VideoPlayer/VideoPlayer.cpp
Expand Up @@ -523,6 +523,7 @@ void CSelectionStreams::Update(const std::shared_ptr<CDVDInputStream>& input,
s.aspect_ratio = vstream->fAspect;
s.stereo_mode = vstream->stereo_mode;
s.bitrate = vstream->iBitRate;
s.hdrType = vstream->hdr_type;
}
if(stream->type == STREAM_AUDIO)
{
Expand Down Expand Up @@ -5122,6 +5123,7 @@ void CVideoPlayer::GetVideoStreamInfo(int streamId, VideoStreamInfo &info)
info.videoAspectRatio = s.aspect_ratio;
info.stereoMode = s.stereo_mode;
info.flags = s.flags;
info.hdrType = s.hdrType;
}

int CVideoPlayer::GetVideoStreamCount() const
Expand Down
1 change: 1 addition & 0 deletions xbmc/cores/VideoPlayer/VideoPlayer.h
Expand Up @@ -196,6 +196,7 @@ struct SelectionStream
CRect VideoRect;
std::string stereo_mode;
float aspect_ratio = 0.0f;
StreamHdrType hdrType = StreamHdrType::HDR_TYPE_NONE;
};

class CSelectionStreams
Expand Down
2 changes: 2 additions & 0 deletions xbmc/guilib/guiinfo/GUIInfoLabels.h
Expand Up @@ -253,6 +253,7 @@
#define VIDEOPLAYER_USER_RATING 277
#define VIDEOPLAYER_DBID 278
#define VIDEOPLAYER_TVSHOWDBID 279
#define VIDEOPLAYER_HDR_TYPE 280

// Range of videoplayer infolabels that work with offset and position
#define VIDEOPLAYER_OFFSET_POSITION_FIRST VIDEOPLAYER_TITLE
Expand Down Expand Up @@ -948,6 +949,7 @@
#define LISTITEM_TVSHOWDBID (LISTITEM_START + 205)
#define LISTITEM_ALBUMSTATUS (LISTITEM_START + 206)
#define LISTITEM_ISAUTOUPDATEABLE (LISTITEM_START + 207)
#define LISTITEM_VIDEO_HDR_TYPE (LISTITEM_START + 208)

#define LISTITEM_END (LISTITEM_START + 2500)

Expand Down
6 changes: 6 additions & 0 deletions xbmc/guilib/guiinfo/VideoGUIInfo.cpp
Expand Up @@ -492,6 +492,9 @@ bool CVideoGUIInfo::GetLabel(std::string& value, const CFileItem *item, int cont

value = CURL(value).GetWithoutUserDetails();
return true;
case LISTITEM_VIDEO_HDR_TYPE:
value = tag->m_streamDetails.GetVideoHdrType();
return true;
}
}

Expand Down Expand Up @@ -553,6 +556,9 @@ bool CVideoGUIInfo::GetLabel(std::string& value, const CFileItem *item, int cont
case VIDEOPLAYER_VIDEO_RESOLUTION:
value = CStreamDetails::VideoDimsToResolutionDescription(m_videoInfo.width, m_videoInfo.height);
return true;
case VIDEOPLAYER_HDR_TYPE:
value = CStreamDetails::HdrTypeToString(m_videoInfo.hdrType);
return true;
case VIDEOPLAYER_AUDIO_CODEC:
value = m_audioInfo.codecName;
return true;
Expand Down
3 changes: 2 additions & 1 deletion xbmc/interfaces/json-rpc/schema/types.json
Expand Up @@ -812,7 +812,8 @@
"aspect": { "type": "number" },
"width": { "type": "integer" },
"height": { "type": "integer" },
"duration": { "type": "integer" }
"duration": { "type": "integer" },
"hdrtype": { "type": "string"}
},
"additionalProperties": false
}
Expand Down
2 changes: 1 addition & 1 deletion xbmc/interfaces/json-rpc/schema/version.txt
@@ -1 +1 @@
JSONRPC_VERSION 12.7.0
JSONRPC_VERSION 12.8.0
4 changes: 4 additions & 0 deletions xbmc/playlists/SmartPlayList.cpp
Expand Up @@ -130,6 +130,7 @@ static const translateField fields[] = {
{ "channels", FieldNoOfChannels, CDatabaseQueryRule::NUMERIC_FIELD, StringValidation::IsPositiveInteger, false, 253 },
{ "albumstatus", FieldAlbumStatus, CDatabaseQueryRule::TEXT_FIELD, NULL, false, 38081 },
{ "albumduration", FieldAlbumDuration, CDatabaseQueryRule::SECONDS_FIELD, StringValidation::IsTime, false, 180 },
{ "hdrtype", FieldHdrType, CDatabaseQueryRule::TEXTIN_FIELD, NULL, false, 20474 },
};
// clang-format on

Expand Down Expand Up @@ -507,6 +508,7 @@ std::vector<Field> CSmartPlaylistRule::GetFields(const std::string &type)
fields.push_back(FieldAudioLanguage);
fields.push_back(FieldSubtitleLanguage);
fields.push_back(FieldVideoAspectRatio);
fields.push_back(FieldHdrType);
}
fields.push_back(FieldPlaylist);
fields.push_back(FieldVirtualFolder);
Expand Down Expand Up @@ -1047,6 +1049,8 @@ std::string CSmartPlaylistRule::FormatWhereClause(const std::string &negate, con
query = db.PrepareSQL(negate + " EXISTS (SELECT 1 FROM streamdetails WHERE streamdetails.idFile = " + table + ".idFile AND streamdetails.iStreamtype = %i GROUP BY streamdetails.idFile HAVING COUNT(streamdetails.iStreamType) " + parameter + ")",CStreamDetail::AUDIO);
else if (m_field == FieldSubtitleCount)
query = db.PrepareSQL(negate + " EXISTS (SELECT 1 FROM streamdetails WHERE streamdetails.idFile = " + table + ".idFile AND streamdetails.iStreamType = %i GROUP BY streamdetails.idFile HAVING COUNT(streamdetails.iStreamType) " + parameter + ")",CStreamDetail::SUBTITLE);
else if (m_field == FieldHdrType)
query = negate + " EXISTS (SELECT 1 FROM streamdetails WHERE streamdetails.idFile = " + table + ".idFile AND strHdrType " + parameter + ")";
if (m_field == FieldPlaycount && strType != "songs" && strType != "albums" && strType != "tvshows")
{ // playcount IS stored as NULL OR number IN video db
if ((m_operator == OPERATOR_EQUALS && param == "0") ||
Expand Down
1 change: 1 addition & 0 deletions xbmc/utils/DatabaseUtils.h
Expand Up @@ -145,6 +145,7 @@ typedef enum {
FieldNoOfChannels,
FieldAlbumStatus,
FieldAlbumDuration,
FieldHdrType,
FieldMax
} Field;

Expand Down
33 changes: 31 additions & 2 deletions xbmc/utils/StreamDetails.cpp
Expand Up @@ -10,7 +10,6 @@

#include "LangInfo.h"
#include "StreamUtils.h"
#include "cores/VideoPlayer/Interface/StreamInfo.h"
#include "utils/Archive.h"
#include "utils/LangCodeExpander.h"
#include "utils/Variant.h"
Expand All @@ -32,7 +31,8 @@ CStreamDetailVideo::CStreamDetailVideo(const VideoStreamInfo &info, int duration
m_iDuration(duration),
m_strCodec(info.codecName),
m_strStereoMode(info.stereoMode),
m_strLanguage(info.language)
m_strLanguage(info.language),
m_strHdrType(CStreamDetails::HdrTypeToString(info.hdrType))
{
}

Expand All @@ -47,6 +47,7 @@ void CStreamDetailVideo::Archive(CArchive& ar)
ar << m_iDuration;
ar << m_strStereoMode;
ar << m_strLanguage;
ar << m_strHdrType;
}
else
{
Expand All @@ -57,6 +58,7 @@ void CStreamDetailVideo::Archive(CArchive& ar)
ar >> m_iDuration;
ar >> m_strStereoMode;
ar >> m_strLanguage;
ar >> m_strHdrType;
}
}
void CStreamDetailVideo::Serialize(CVariant& value) const
Expand All @@ -68,6 +70,7 @@ void CStreamDetailVideo::Serialize(CVariant& value) const
value["duration"] = m_iDuration;
value["stereomode"] = m_strStereoMode;
value["language"] = m_strLanguage;
value["hdrtype"] = m_strHdrType;
}

bool CStreamDetailVideo::IsWorseThan(const CStreamDetail &that) const
Expand Down Expand Up @@ -398,6 +401,16 @@ int CStreamDetails::GetVideoHeight(int idx) const
return 0;
}

std::string CStreamDetails::GetVideoHdrType( int idx) const
{
const CStreamDetailVideo* item =
static_cast<const CStreamDetailVideo*>(GetNthStream(CStreamDetail::VIDEO, idx));
if (item)
return item->m_strHdrType;
else
return "";
}

int CStreamDetails::GetVideoDuration(int idx) const
{
const CStreamDetailVideo *item = static_cast<const CStreamDetailVideo*>(GetNthStream(CStreamDetail::VIDEO, idx));
Expand Down Expand Up @@ -625,3 +638,19 @@ bool CStreamDetails::SetStreams(const VideoStreamInfo& videoInfo, int videoDurat
DetermineBestStreams();
return true;
}

std::string CStreamDetails::HdrTypeToString(StreamHdrType hdrType)
{
switch (hdrType)
{
case StreamHdrType::HDR_TYPE_DOLBYVISION:
return "dolbyvision";
case StreamHdrType::HDR_TYPE_HDR10:
return "hdr10";
case StreamHdrType::HDR_TYPE_HLG:
return "hlg";
case StreamHdrType::HDR_TYPE_NONE:
default:
return "";
}
}
4 changes: 4 additions & 0 deletions xbmc/utils/StreamDetails.h
Expand Up @@ -9,6 +9,7 @@
#pragma once

#include "ISerializable.h"
#include "cores/VideoPlayer/Interface/StreamInfo.h"
#include "utils/IArchivable.h"

#include <memory>
Expand Down Expand Up @@ -57,6 +58,7 @@ class CStreamDetailVideo final : public CStreamDetail
std::string m_strCodec;
std::string m_strStereoMode;
std::string m_strLanguage;
std::string m_strHdrType;
};

class CStreamDetailAudio final : public CStreamDetail
Expand Down Expand Up @@ -103,12 +105,14 @@ class CStreamDetails final : public IArchivable, public ISerializable
int GetVideoStreamCount(void) const;
int GetAudioStreamCount(void) const;
int GetSubtitleStreamCount(void) const;
static std::string HdrTypeToString(StreamHdrType hdrType);
const CStreamDetail* GetNthStream(CStreamDetail::StreamType type, int idx) const;

std::string GetVideoCodec(int idx = 0) const;
float GetVideoAspect(int idx = 0) const;
int GetVideoWidth(int idx = 0) const;
int GetVideoHeight(int idx = 0) const;
std::string GetVideoHdrType (int idx = 0) const;
int GetVideoDuration(int idx = 0) const;
void SetVideoDuration(int idx, const int duration);
std::string GetStereoMode(int idx = 0) const;
Expand Down

0 comments on commit 63c8427

Please sign in to comment.