Skip to content

Commit

Permalink
[Android] Optionally convert Dolby Vision
Browse files Browse the repository at this point in the history
To improve compatibility
  • Loading branch information
quietvoid committed Jan 22, 2023
1 parent 54f1d4b commit 151ff19
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 1 deletion.
12 changes: 12 additions & 0 deletions addons/resource.language.en_gb/resources/strings.po
Expand Up @@ -23405,3 +23405,15 @@ msgstr ""
msgctxt "#39189"
msgid "Available only with manual subtitle position"
msgstr ""

#. Title of Dolby Vision RPU conversion setting
#: system/settings/settings.xml
msgctxt "#39190"
msgid "Convert Dolby Vision for compatibility"
msgstr ""

#. Help text for setting "Convert Dolby Vision for compatibility" of label #39190
#: system/settings/settings.xml
msgctxt "#39191"
msgid "Converts Dolby Vision profile 7 to profile 8.1, ignores enhancement layer"
msgstr ""
9 changes: 9 additions & 0 deletions system/settings/settings.xml
Expand Up @@ -153,6 +153,15 @@
<default>true</default>
<control type="toggle" />
</setting>
<setting id="videoplayer.convertdovi" type="boolean" label="39190" help="39191">
<requirement>HAS_MEDIACODEC</requirement>
<level>2</level>
<default>false</default>
<updates>
<update type="change" />
</updates>
<control type="toggle" />
</setting>
</group>
<group id="4" label="14232">
<setting id="videoplayer.stereoscopicplaybackmode" type="integer" label="36520" help="36537">
Expand Down
Expand Up @@ -537,6 +537,10 @@ bool CDVDVideoCodecAndroidMediaCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptio
{
m_bitstream.reset();
}

bool convertDovi = CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
CSettings::SETTING_VIDEOPLAYER_CONVERTDOVI);
m_bitstream->SetConvertDovi(convertDovi);
}
break;
}
Expand Down
1 change: 1 addition & 0 deletions xbmc/settings/Settings.cpp
Expand Up @@ -153,6 +153,7 @@ constexpr const char* CSettings::SETTING_VIDEOPLAYER_USEPRIMEDECODER;
constexpr const char* CSettings::SETTING_VIDEOPLAYER_USESTAGEFRIGHT;
constexpr const char* CSettings::SETTING_VIDEOPLAYER_LIMITGUIUPDATE;
constexpr const char* CSettings::SETTING_VIDEOPLAYER_SUPPORTMVC;
constexpr const char* CSettings::SETTING_VIDEOPLAYER_CONVERTDOVI;
constexpr const char* CSettings::SETTING_MYVIDEOS_SELECTACTION;
constexpr const char* CSettings::SETTING_MYVIDEOS_USETAGS;
constexpr const char* CSettings::SETTING_MYVIDEOS_EXTRACTFLAGS;
Expand Down
1 change: 1 addition & 0 deletions xbmc/settings/Settings.h
Expand Up @@ -129,6 +129,7 @@ class CSettings : public CSettingsBase, public CSettingCreator, public CSettingC
static constexpr auto SETTING_VIDEOPLAYER_USESTAGEFRIGHT = "videoplayer.usestagefright";
static constexpr auto SETTING_VIDEOPLAYER_LIMITGUIUPDATE = "videoplayer.limitguiupdate";
static constexpr auto SETTING_VIDEOPLAYER_SUPPORTMVC = "videoplayer.supportmvc";
static constexpr auto SETTING_VIDEOPLAYER_CONVERTDOVI = "videoplayer.convertdovi";
static constexpr auto SETTING_MYVIDEOS_SELECTACTION = "myvideos.selectaction";
static constexpr auto SETTING_MYVIDEOS_USETAGS = "myvideos.usetags";
static constexpr auto SETTING_MYVIDEOS_EXTRACTFLAGS = "myvideos.extractflags";
Expand Down
82 changes: 81 additions & 1 deletion xbmc/utils/BitstreamConverter.cpp
Expand Up @@ -20,6 +20,13 @@

#include <algorithm>

extern "C"
{
#ifdef HAVE_LIBDOVI
#include <libdovi/rpu_parser.h>
#endif
}

enum {
AVC_NAL_SLICE=1,
AVC_NAL_DPA,
Expand Down Expand Up @@ -257,6 +264,38 @@ static bool has_sei_recovery_point(const uint8_t *p, const uint8_t *end)
return false;
}

#ifdef HAVE_LIBDOVI
// The returned data must be freed with `dovi_data_free`
// May be NULL if no conversion was done
static const DoviData* convert_dovi_rpu_nal(uint8_t* buf, uint32_t nal_size)
{
DoviRpuOpaque* rpu = dovi_parse_unspec62_nalu(buf, nal_size);
const DoviRpuDataHeader* header = dovi_rpu_get_header(rpu);
const DoviData* rpu_data = NULL;

if (header && header->guessed_profile == 7)
{
int ret = dovi_convert_rpu_with_mode(rpu, 2);
if (ret < 0)
goto fail;

ret = dovi_rpu_remove_mapping(rpu);
if (ret < 0)
goto fail;

rpu_data = dovi_write_unspec62_nalu(rpu);
}

fail:
if (header)
dovi_rpu_free_header(header);

dovi_rpu_free(rpu);

return rpu_data;
}
#endif

////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
CBitstreamParser::CBitstreamParser() = default;
Expand Down Expand Up @@ -324,6 +363,7 @@ CBitstreamConverter::CBitstreamConverter()
m_convert_bytestream = false;
m_sps_pps_context.sps_pps_data = NULL;
m_start_decode = true;
m_convert_dovi = false;
}

CBitstreamConverter::~CBitstreamConverter()
Expand Down Expand Up @@ -882,6 +922,10 @@ bool CBitstreamConverter::BitstreamConvert(uint8_t* pData, int iSize, uint8_t **
uint32_t cumul_size = 0;
const uint8_t *buf_end = buf + buf_size;

#ifdef HAVE_LIBDOVI
const DoviData* rpu_data = NULL;
#endif

switch (m_codec)
{
case AV_CODEC_ID_H264:
Expand Down Expand Up @@ -935,12 +979,48 @@ bool CBitstreamConverter::BitstreamConvert(uint8_t* pData, int iSize, uint8_t **
}
else
{
BitstreamAllocAndCopy(poutbuf, poutbuf_size, NULL, 0, buf, nal_size, unit_type);
bool write_buf = true;
const uint8_t* buf_to_write = buf;
int32_t final_nal_size = nal_size;

if (!m_sps_pps_context.first_idr && IsSlice(unit_type))
{
m_sps_pps_context.first_idr = 1;
m_sps_pps_context.idr_sps_pps_seen = 0;
}

if (m_convert_dovi)
{
if (unit_type == HEVC_NAL_UNSPEC62)
{
#ifdef HAVE_LIBDOVI
// Convert the RPU itself
rpu_data = convert_dovi_rpu_nal(buf, nal_size);
if (rpu_data)
{
buf_to_write = rpu_data->data;
final_nal_size = rpu_data->len;
}
#endif
}
else if (unit_type == HEVC_NAL_UNSPEC63)
{
// Ignore the enhancement layer, may or may not help
write_buf = false;
}
}

if (write_buf)
BitstreamAllocAndCopy(poutbuf, poutbuf_size, NULL, 0, buf_to_write, final_nal_size,
unit_type);

#ifdef HAVE_LIBDOVI
if (rpu_data)
{
dovi_data_free(rpu_data);
rpu_data = NULL;
}
#endif
}

buf += nal_size;
Expand Down
2 changes: 2 additions & 0 deletions xbmc/utils/BitstreamConverter.h
Expand Up @@ -96,6 +96,7 @@ class CBitstreamConverter
int GetExtraSize() const;
void ResetStartDecode(void);
bool CanStartDecode() const;
void SetConvertDovi(bool value) { m_convert_dovi = value; }

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

Expand Down Expand Up @@ -141,4 +142,5 @@ class CBitstreamConverter
bool m_convert_bytestream;
AVCodecID m_codec;
bool m_start_decode;
bool m_convert_dovi;
};

0 comments on commit 151ff19

Please sign in to comment.