Skip to content

Commit 35310d2

Browse files
authored
Merge pull request xbmc#27431 from quietvoid/dovi-zero-level5
[Android] [webOS] Add Dolby Vision setting to set zero L5 metadata
2 parents f611492 + a059f5a commit 35310d2

File tree

7 files changed

+99
-33
lines changed

7 files changed

+99
-33
lines changed

addons/resource.language.en_gb/resources/strings.po

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24358,7 +24358,19 @@ msgctxt "#39208"
2435824358
msgid "Starfish is the hardware video decoder for LG's webOS. Disable it for troubleshooting or testing."
2435924359
msgstr ""
2436024360

24361-
#empty strings from id 39209 to 39999
24361+
#. Title of Dolby Vision level 5 metadata zero override setting
24362+
#: system/settings/settings.xml
24363+
msgctxt "#39209"
24364+
msgid "Dolby Vision: Override level 5 metadata to zero"
24365+
msgstr ""
24366+
24367+
#. Help text for setting "Dolby Vision: Override level 5 metadata to zero" of label #39209
24368+
#: system/settings/settings.xml
24369+
msgctxt "#39210"
24370+
msgid "If enabled, Dolby Vision files will have level 5 (active area) metadata overridden to zero offsets. Enable if your display has issues with incorrectly cropped image in Dolby Vision playback."
24371+
msgstr ""
24372+
24373+
#empty strings from id 39211 to 39999
2436224374

2436324375
# 40000 to 40800 are reserved for Video Versions feature
2436424376

system/settings/settings.xml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,25 @@
241241
<hidevalue>false</hidevalue>
242242
</control>
243243
</setting>
244+
<setting id="videoplayer.dovizerolevel5" type="boolean" label="39209" help="39210">
245+
<requirement><!-- Android and webOS use CBitstreamConverter -->
246+
<or>
247+
<condition>HAS_MEDIACODEC</condition>
248+
<condition>HAVE_WEBOS</condition>
249+
</or>
250+
</requirement>
251+
<dependencies>
252+
<dependency type="visible">
253+
<or>
254+
<condition on="property" name="supportsdolbyvision" />
255+
<condition>HAVE_WEBOS</condition>
256+
</or>
257+
</dependency>
258+
</dependencies>
259+
<level>2</level>
260+
<default>false</default>
261+
<control type="toggle" />
262+
</setting>
244263
</group>
245264
<group id="4" label="14232">
246265
<setting id="videoplayer.stereoscopicplaybackmode" type="integer" label="36520" help="36537">

xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,10 +500,12 @@ bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio
500500
bool convertDovi{false};
501501
bool removeDovi{false};
502502
bool removeHdr10Plus{false};
503+
bool doviZeroLevel5{false};
503504

504505
if (settings)
505506
{
506507
convertDovi = settings->GetBool(CSettings::SETTING_VIDEOPLAYER_CONVERTDOVI);
508+
doviZeroLevel5 = settings->GetBool(CSettings::SETTING_VIDEOPLAYER_DOVIZEROLEVEL5);
507509

508510
const std::shared_ptr<CSettingList> allowedHdrFormatsSetting(
509511
std::dynamic_pointer_cast<CSettingList>(
@@ -600,6 +602,7 @@ bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio
600602
{
601603
m_bitstream->SetRemoveDovi(removeDovi);
602604
m_bitstream->SetRemoveHdr10Plus(removeHdr10Plus);
605+
m_bitstream->SetDoviZeroLevel5(doviZeroLevel5);
603606

604607
// Only set for profile 7, container hint allows to skip parsing unnecessarily
605608
if (m_hints.dovi.dv_profile == 7)

xbmc/cores/VideoPlayer/MediaPipelineWebOS.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,7 @@ void CMediaPipelineWebOS::SetupBitstreamConverter(CDVDStreamInfo& hint)
846846
const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings();
847847
const bool convertDovi =
848848
hint.dovi.el_present_flag || settings->GetBool(CSettings::SETTING_VIDEOPLAYER_CONVERTDOVI);
849+
const bool doviZeroLevel5 = settings->GetBool(CSettings::SETTING_VIDEOPLAYER_DOVIZEROLEVEL5);
849850

850851
const std::shared_ptr allowedHdrFormatsSetting(std::dynamic_pointer_cast<CSettingList>(
851852
settings->GetSetting(CSettings::SETTING_VIDEOPLAYER_ALLOWEDHDRFORMATS)));
@@ -864,6 +865,7 @@ void CMediaPipelineWebOS::SetupBitstreamConverter(CDVDStreamInfo& hint)
864865
if (hint.codec == AV_CODEC_ID_HEVC)
865866
{
866867
m_bitstream->SetRemoveDovi(removeDovi);
868+
m_bitstream->SetDoviZeroLevel5(doviZeroLevel5);
867869

868870
// webOS doesn't support HDR10+ and it can cause issues
869871
m_bitstream->SetRemoveHdr10Plus(true);

xbmc/settings/Settings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ class CSettings : public CSettingsBase, public CSettingCreator, public CSettingC
137137
static constexpr auto SETTING_VIDEOPLAYER_SUPPORTMVC = "videoplayer.supportmvc";
138138
static constexpr auto SETTING_VIDEOPLAYER_CONVERTDOVI = "videoplayer.convertdovi";
139139
static constexpr auto SETTING_VIDEOPLAYER_ALLOWEDHDRFORMATS = "videoplayer.allowedhdrformats";
140+
static constexpr auto SETTING_VIDEOPLAYER_DOVIZEROLEVEL5 = "videoplayer.dovizerolevel5";
140141
static constexpr auto SETTING_VIDEOPLAYER_QUEUETIMESIZE = "videoplayer.queuetimesize";
141142
static constexpr auto SETTING_VIDEOPLAYER_QUEUEDATASIZE = "videoplayer.queuedatasize";
142143
static constexpr auto SETTING_MYVIDEOS_SELECTACTION = "myvideos.selectaction";

xbmc/utils/BitstreamConverter.cpp

Lines changed: 51 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@
2222
extern "C"
2323
{
2424
#include <libavutil/intreadwrite.h>
25-
#ifdef HAVE_LIBDOVI
26-
#include <libdovi/rpu_parser.h>
27-
#endif
2825
}
2926

3027
enum {
@@ -264,32 +261,6 @@ static bool has_sei_recovery_point(const uint8_t *p, const uint8_t *end)
264261
return false;
265262
}
266263

267-
#ifdef HAVE_LIBDOVI
268-
// The returned data must be freed with `dovi_data_free`
269-
// May be NULL if no conversion was done
270-
static const DoviData* convert_dovi_rpu_nal(uint8_t* buf, uint32_t nal_size)
271-
{
272-
DoviRpuOpaque* rpu = dovi_parse_unspec62_nalu(buf, nal_size);
273-
const DoviRpuDataHeader* header = dovi_rpu_get_header(rpu);
274-
const DoviData* rpu_data = NULL;
275-
276-
if (header && header->guessed_profile == 7)
277-
{
278-
int ret = dovi_convert_rpu_with_mode(rpu, 2);
279-
if (ret < 0)
280-
goto done;
281-
282-
rpu_data = dovi_write_unspec62_nalu(rpu);
283-
}
284-
285-
done:
286-
dovi_rpu_free_header(header);
287-
dovi_rpu_free(rpu);
288-
289-
return rpu_data;
290-
}
291-
#endif
292-
293264
////////////////////////////////////////////////////////////////////////////////////////////
294265
/////////////////////////////////////////////////////////////////////////////////////////////
295266
CBitstreamParser::CBitstreamParser() = default;
@@ -358,6 +329,7 @@ CBitstreamConverter::CBitstreamConverter()
358329
m_convert_dovi = false;
359330
m_removeDovi = false;
360331
m_removeHdr10Plus = false;
332+
m_setDoviZeroLevel5 = false;
361333
}
362334

363335
CBitstreamConverter::~CBitstreamConverter()
@@ -1005,21 +977,21 @@ bool CBitstreamConverter::BitstreamConvert(uint8_t* pData, int iSize, uint8_t **
1005977
}
1006978
}
1007979

1008-
if (write_buf && m_convert_dovi)
980+
if (write_buf)
1009981
{
1010982
if (unit_type == HEVC_NAL_UNSPEC62)
1011983
{
1012984
#ifdef HAVE_LIBDOVI
1013985
// Convert the RPU itself
1014-
rpu_data = convert_dovi_rpu_nal(buf, nal_size);
986+
rpu_data = processDoviRpu(buf, nal_size);
1015987
if (rpu_data)
1016988
{
1017989
buf_to_write = rpu_data->data;
1018990
final_nal_size = rpu_data->len;
1019991
}
1020992
#endif
1021993
}
1022-
else if (unit_type == HEVC_NAL_UNSPEC63)
994+
else if (m_convert_dovi && unit_type == HEVC_NAL_UNSPEC63)
1023995
{
1024996
// Ignore the enhancement layer, may or may not help
1025997
write_buf = false;
@@ -1334,3 +1306,50 @@ bool CBitstreamConverter::mpeg2_sequence_header(const uint8_t *data, const uint3
13341306
return changed;
13351307
}
13361308

1309+
#ifdef HAVE_LIBDOVI
1310+
// Processes Dolby Vision RPU
1311+
// - Converts to profile 8.1 if `m_convert_dovi` is enabled
1312+
// - Sets level 5 metadata to 0 offsets if `m_setDoviZeroLevel5` is enabled
1313+
//
1314+
// The returned data must be freed with `dovi_data_free`
1315+
// May be NULL if no processing was done or if parsing errored
1316+
const DoviData* CBitstreamConverter::processDoviRpu(uint8_t* buf, uint32_t nalSize)
1317+
{
1318+
// early exit if no processing option is enabled
1319+
if (!m_convert_dovi && !m_setDoviZeroLevel5)
1320+
return NULL;
1321+
1322+
DoviRpuOpaque* rpu = dovi_parse_unspec62_nalu(buf, nalSize);
1323+
const DoviRpuDataHeader* header = dovi_rpu_get_header(rpu);
1324+
const DoviData* rpuData = NULL;
1325+
1326+
int ret = 0;
1327+
bool processed = false;
1328+
1329+
if (!header)
1330+
{
1331+
dovi_rpu_free(rpu);
1332+
return rpuData;
1333+
}
1334+
1335+
if (m_convert_dovi && header->guessed_profile == 7)
1336+
{
1337+
ret = dovi_convert_rpu_with_mode(rpu, 2);
1338+
processed = true;
1339+
}
1340+
1341+
if (ret == 0 && m_setDoviZeroLevel5)
1342+
{
1343+
ret = dovi_rpu_set_active_area_offsets(rpu, 0, 0, 0, 0);
1344+
processed = true;
1345+
}
1346+
1347+
if (ret == 0 && processed)
1348+
rpuData = dovi_write_unspec62_nalu(rpu);
1349+
1350+
dovi_rpu_free_header(header);
1351+
dovi_rpu_free(rpu);
1352+
1353+
return rpuData;
1354+
}
1355+
#endif

xbmc/utils/BitstreamConverter.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ extern "C" {
1717
#include <libavformat/avformat.h>
1818
#include <libavfilter/avfilter.h>
1919
#include <libavcodec/avcodec.h>
20+
21+
#ifdef HAVE_LIBDOVI
22+
#include <libdovi/rpu_parser.h>
23+
#endif
2024
}
2125

2226
typedef struct
@@ -102,6 +106,7 @@ class CBitstreamConverter
102106
void SetConvertDovi(bool value) { m_convert_dovi = value; }
103107
void SetRemoveDovi(bool value) { m_removeDovi = value; }
104108
void SetRemoveHdr10Plus(bool value) { m_removeHdr10Plus = value; }
109+
void SetDoviZeroLevel5(bool value) { m_setDoviZeroLevel5 = value; }
105110

106111
static bool mpeg2_sequence_header(const uint8_t *data, const uint32_t size, mpeg2_sequence *sequence);
107112

@@ -123,6 +128,10 @@ class CBitstreamConverter
123128
uint32_t in_size,
124129
uint8_t nal_type);
125130

131+
#ifdef HAVE_LIBDOVI
132+
const DoviData* processDoviRpu(uint8_t* buf, uint32_t nalSize);
133+
#endif
134+
126135
typedef struct omx_bitstream_ctx {
127136
uint8_t length_size;
128137
uint8_t first_idr;
@@ -149,4 +158,5 @@ class CBitstreamConverter
149158
bool m_convert_dovi;
150159
bool m_removeDovi;
151160
bool m_removeHdr10Plus;
161+
bool m_setDoviZeroLevel5;
152162
};

0 commit comments

Comments
 (0)