Skip to content

Commit

Permalink
dolby vision profileのコピーに対応。
Browse files Browse the repository at this point in the history
  • Loading branch information
rigaya committed Aug 1, 2024
1 parent 2c9d735 commit d63dea5
Show file tree
Hide file tree
Showing 21 changed files with 252 additions and 62 deletions.
14 changes: 12 additions & 2 deletions NVEnc/NVEnc_readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,18 @@ NVIDIA グラフィックドライバ 551.23
今後の更新で設定ファイルの互換性がなくなるかもしれません。

【メモ】
2024.07.2x (7.58)
- --vpp-frucでfps指定の時の処理速度を大幅に向上。
2024.08.01 (7.58)
[NVEncC]
- Dolby Vision profileのコピー機能を追加。(--dolby-vision-profile copy)
- Dolby Vision rpu metadataのコピー機能を追加。(--dolby-vision-rpu copy)
- --vpp-frucでfps指定の時の処理速度を大幅に向上。( #586 )
- --vpp-tweakにチャネルごとの制御を追加。
- H.264/HEVCのヘッダがうまく取得できない場合、最初のパケットから取得するように。( #604 )
- --vpp-nlmeansで search=3 にするとエラー終了していた問題を修正。
- 音声のmux用のバッファ不足になり、音声が同時刻の映像と違うfragmentにmuxされる問題を修正。

[NVEnc.auo]
- Windowsの登録拡張子の状況によっては、意図せず出力拡張子が設定されず、muxされなくなってしまう問題を回避。

2024.06.29 (7.57)
- --vpp-colorspace, --vpp-resize ngx-vsr, --vpp-ngx-truehdr が一部の言語のOSで正常に動作しない問題を修正。
Expand Down
24 changes: 16 additions & 8 deletions NVEncC_Options.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,9 @@
- [--atc-sei \<string\> or \<int\> \[HEVC only\]](#--atc-sei-string-or-int-hevc-only)
- [--dhdr10-info \<string\> \[HEVC, AV1\]](#--dhdr10-info-string-hevc-av1)
- [--dhdr10-info copy \[HEVC, AV1\]](#--dhdr10-info-copy-hevc-av1)
- [--dolby-vision-profile \<float\>](#--dolby-vision-profile-float)
- [--dolby-vision-rpu \<string\>](#--dolby-vision-rpu-string)
- [--dolby-vision-profile \<string\> \[HEVC, AV1\]](#--dolby-vision-profile-string-hevc-av1)
- [--dolby-vision-rpu \<string\> \[HEVC, AV1\]](#--dolby-vision-rpu-string-hevc-av1)
- [--dolby-vision-rpu copy \[HEVC\]](#--dolby-vision-rpu-copy-hevc)
- [--aud \[H.264/HEVC\]](#--aud-h264hevc)
- [--repeat-headers](#--repeat-headers)
- [--pic-struct \[H.264/HEVC\]](#--pic-struct-h264hevc)
Expand Down Expand Up @@ -887,16 +888,23 @@ Copy HDR10+ dynamic metadata from input file.
Limitations for avhw reader: this option uses timestamps to reorder frames to decoded order to presentation order.
Therefore, input files without timestamps (such as raw ES), are not supported. Please try for avsw reader for that case.

### --dolby-vision-profile &lt;float&gt;
Output file which is specified in Dolby Vision profile.
### --dolby-vision-profile &lt;string&gt; [HEVC, AV1]
Output file which is specified in Dolby Vision profile. Recommended to be used with [--dolby-vision-rpu](#--dolby-vision-rpu-string).

"copy" will use dolby vision profile from input file (available when using [avhw](#--avhw)/[avsw](#--avsw) reader).

```
5.0, 8.1, 8.2, 8.4
unset, copy, 5.0, 8.1, 8.2, 8.4
```

### --dolby-vision-rpu &lt;string&gt;
Interleave Dolby Vision RPU metadata from the specified file into the output file.
### --dolby-vision-rpu &lt;string&gt; [HEVC, AV1]
Interleave Dolby Vision RPU metadata from the specified file into the output file. Recommended to be used with [--dolby-vision-profile](#--dolby-vision-profile-string).

### --dolby-vision-rpu copy [HEVC]
Interleave Dolby Vision RPU metadata copied from HEVC input file. Recommended to be used with [--dolby-vision-profile](#--dolby-vision-profile-string).

Currently, the Dolby Vision info in the re-encoded file will not be detected by MediaInfo. In order to be able to detect the Dolby Vision info by MediaInfo, you will need to re-mux the output file by [tsMuxeR](https://github.com/justdan96/tsMuxer/releases) (nightly).
Limitations for avhw reader: this option uses timestamps to reorder frames to decoded order to presentation order.
Therefore, input files without timestamps (such as raw ES), are not supported. Please try for avsw reader for that case.

### --aud [H.264/HEVC]
Insert Access Unit Delimiter NAL.
Expand Down
23 changes: 15 additions & 8 deletions NVEncC_Options.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,9 @@
- [--atc-sei \<string\> or \<int\> \[HEVCのみ\]](#--atc-sei-string-or-int-hevcのみ)
- [--dhdr10-info \<string\> \[HEVC, AV1\]](#--dhdr10-info-string-hevc-av1)
- [--dhdr10-info copy \[HEVC, AV1\]](#--dhdr10-info-copy-hevc-av1)
- [--dolby-vision-profile \<float\> \[HEVC\]](#--dolby-vision-profile-float-hevc)
- [--dolby-vision-rpu \<string\> \[HEVC\]](#--dolby-vision-rpu-string-hevc)
- [--dolby-vision-profile \<string\> \[HEVC, AV1\]](#--dolby-vision-profile-string-hevc-av1)
- [--dolby-vision-rpu \<string\> \[HEVC, AV1\]](#--dolby-vision-rpu-string-hevc-av1)
- [--dolby-vision-rpu copy \[HEVC, AV1\]](#--dolby-vision-rpu-copy-hevc-av1)
- [--aud \[H.264/HEVC\]](#--aud-h264hevc)
- [--repeat-headers](#--repeat-headers)
- [--pic-struct \[H.264/HEVC\]](#--pic-struct-h264hevc)
Expand Down Expand Up @@ -893,18 +894,24 @@ HDR10+のメタデータを入力ファイルからそのままコピーしま
avhw読み込みでは、フレームの並び替えにタイムスタンプを使用するため、タイムスタンプの取得できないraw ESのような入力ファイルでは使用できません。
こうした場合には、avsw読み込みを使用してください。

### --dolby-vision-profile &lt;float&gt; [HEVC]
指定されたdolby visionプロファイルを適用します。
### --dolby-vision-profile &lt;string&gt; [HEVC, AV1]
指定されたdolby visionプロファイルを適用します。[--dolby-vision-rpu](#--dolby-vision-rpu-string)との併用が推奨です。

"copy" は、入力ファイルのdolby visionプロファイルを適用します。 ([avhw](#--avhw)/[avsw](#--avsw)読み込みのみ)

```
5.0, 8.1, 8.2, 8.4
unset, copy, 5.0, 8.1, 8.2, 8.4
```

### --dolby-vision-rpu &lt;string&gt; [HEVC]
### --dolby-vision-rpu &lt;string&gt; [HEVC, AV1]
指定のrpuファイルに含まれるdolby visionのmetadataを出力ファイルに挿入します。

現時点(2022年1月実装時点)では、このオプションを使用して出力した動画ファイルは、MediaInfoによりDolby Vision情報が検出されません。
### --dolby-vision-rpu copy [HEVC, AV1]
HEVCの入力ファイルから読み取ったdolby visionのmetadataを出力ファイルに挿入します。 [--dolby-vision-profile](#--dolby-vision-profile-string)との併用が推奨です。

avhw読み込みでは、フレームの並び替えにタイムスタンプを使用するため、タイムスタンプの取得できないraw ESのような入力ファイルでは使用できません。
こうした場合には、avsw読み込みを使用してください。

MediaInfoによるDolby Vision情報の検出を可能とするには、[tsMuxeR](https://github.com/justdan96/tsMuxer/releases) (nightly版) による再muxが必要です。

### --aud [H.264/HEVC]
Access Unit Delimiter NALを挿入する。
Expand Down
16 changes: 13 additions & 3 deletions NVEncCore/NVEncCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ NVEncCore::NVEncCore() :
m_hdrsei(),
m_dovirpu(),
m_dovirpuMetadataCopy(false),
m_doviProfile(RGY_DOVI_PROFILE_UNSET),
m_encTimestamp(),
m_encodeFrameID(0),
m_videoIgnoreTimestampError(DEFAULT_VIDEO_IGNORE_TIMESTAMP_ERROR),
Expand Down Expand Up @@ -635,6 +636,7 @@ NVENCSTATUS NVEncCore::InitInput(InEncodeVideoParam *inputParam, const std::vect
} else if (inputParam->common.doviRpuMetadataCopy) {
m_dovirpuMetadataCopy = true;
}
m_doviProfile = inputParam->common.doviProfile;
#endif

m_hdrsei = createHEVCHDRSei(inputParam->common.maxCll, inputParam->common.masterDisplay, inputParam->common.atcSei, m_pFileReader.get());
Expand Down Expand Up @@ -3421,7 +3423,6 @@ NVENCSTATUS NVEncCore::InitEncode(InEncodeVideoParam *inputParam) {
PrintMes(RGY_LOG_DEBUG, _T("Set Process priority: %s.\n"), rgy_thread_priority_mode_to_str(priority));
}

inputParam->applyDOVIProfile();
m_nAVSyncMode = inputParam->common.AVSyncMode;
m_nProcSpeedLimit = inputParam->ctrl.procSpeedLimit;
m_videoIgnoreTimestampError = inputParam->common.videoIgnoreTimestampError;
Expand Down Expand Up @@ -3476,6 +3477,8 @@ NVENCSTATUS NVEncCore::InitEncode(InEncodeVideoParam *inputParam) {
}
PrintMes(RGY_LOG_DEBUG, _T("InitInput: Success.\n"));

inputParam->applyDOVIProfile(m_pFileReader->getInputDOVIProfile());

bool bOutputHighBitDepth = encodeIsHighBitDepth(inputParam);
if (inputParam->lossless && inputParam->losslessIgnoreInputCsp == 0) {
const auto inputFrameInfo = m_pFileReader->GetInputFrameInfo();
Expand Down Expand Up @@ -5385,9 +5388,16 @@ tstring NVEncCore::GetEncodingParamsInfo(int output_level) {
}
}
if (m_hdr10plus) {
add_str(RGY_LOG_INFO, _T("Dynamic HDR10 %s\n"), m_hdr10plus->inputJson().c_str());
add_str(RGY_LOG_INFO, _T("Dynamic HDR10 %s\n"), m_hdr10plus->inputJson().c_str());
} else if (m_hdr10plusMetadataCopy) {
add_str(RGY_LOG_INFO, _T("Dynamic HDR10 copy\n"));
add_str(RGY_LOG_INFO, _T("Dynamic HDR10 copy\n"));
}
if (m_doviProfile != RGY_DOVI_PROFILE_UNSET) {
tstring profile_copy;
if (m_doviProfile == RGY_DOVI_PROFILE_COPY) {
profile_copy = tstring(_T(" (")) + get_cx_desc(list_dovi_profile, m_pFileReader->getInputDOVIProfile()) + tstring(_T(")"));
}
add_str(RGY_LOG_INFO, _T("dovi profile %s%s\n"), get_cx_desc(list_dovi_profile, m_doviProfile), profile_copy.c_str());
}
if (m_dovirpu) {
add_str(RGY_LOG_INFO, _T("dovi rpu %s\n"), m_dovirpu->get_filepath().c_str());
Expand Down
1 change: 1 addition & 0 deletions NVEncCore/NVEncCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ class NVEncCore : public NVEncCtrl {
unique_ptr<RGYHDRMetadata> m_hdrsei;
unique_ptr<DOVIRpu> m_dovirpu;
bool m_dovirpuMetadataCopy;
RGYDOVIProfile m_doviProfile;
std::unique_ptr<RGYTimestamp> m_encTimestamp;
int64_t m_encodeFrameID;
int m_videoIgnoreTimestampError;
Expand Down
7 changes: 4 additions & 3 deletions NVEncCore/NVEncParam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,15 +286,16 @@ InEncodeVideoParam::InEncodeVideoParam() :
input.vui = VideoVUIInfo();
}

void InEncodeVideoParam::applyDOVIProfile() {
void InEncodeVideoParam::applyDOVIProfile(const RGYDOVIProfile inputProfile) {
#if !FOR_AUO
if (codec_rgy != RGY_CODEC_HEVC) {
return;
}
if (common.doviProfile == 0) {
auto targetDoviProfile = (common.doviProfile == RGY_DOVI_PROFILE_COPY) ? inputProfile : common.doviProfile;
if (targetDoviProfile == 0) {
return;
}
auto profile = getDOVIProfile(common.doviProfile);
auto profile = getDOVIProfile(targetDoviProfile);
if (profile == nullptr) {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion NVEncCore/NVEncParam.h
Original file line number Diff line number Diff line change
Expand Up @@ -739,7 +739,7 @@ struct InEncodeVideoParam {

InEncodeVideoParam();

void applyDOVIProfile();
void applyDOVIProfile(const RGYDOVIProfile inputProfile);
};

static void setQP(NV_ENC_QP& nvencqp, const RGYQPSet& qp) {
Expand Down
25 changes: 25 additions & 0 deletions NVEncCore/rgy_avutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -921,4 +921,29 @@ tstring getDispositionStr(uint32_t disposition) {
return str;
}

RGYDOVIProfile getStreamDOVIProfile(const AVStream *stream) {
#if LIBAVUTIL_DOVI_META_AVAIL
size_t side_data_size = 0;
auto doviconf = AVStreamGetSideData<AVDOVIDecoderConfigurationRecord>(stream, AV_PKT_DATA_DOVI_CONF, side_data_size);
if (!doviconf) {
return RGY_DOVI_PROFILE_UNSET;
}
switch (doviconf->dv_profile) {
case 5:
return RGY_DOVI_PROFILE_50;
case 8:
switch (doviconf->dv_bl_signal_compatibility_id) {
case 1: return RGY_DOVI_PROFILE_81;
case 2: return RGY_DOVI_PROFILE_82;
case 4: return RGY_DOVI_PROFILE_84;
default: return RGY_DOVI_PROFILE_UNSET;
}
default:
return RGY_DOVI_PROFILE_UNSET;
}
#else
return RGY_DOVI_PROFILE_UNSET;
#endif
}

#endif //ENABLE_AVSW_READER
7 changes: 7 additions & 0 deletions NVEncCore/rgy_avutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ extern "C" {
#include <libavutil/pixdesc.h>
#include <libavutil/display.h>
#include <libavutil/mastering_display_metadata.h>
#if __has_include(<libavutil/dovi_meta.h>)
#define LIBAVUTIL_DOVI_META_AVAIL 1
#include <libavutil/dovi_meta.h>
#else
#define LIBAVUTIL_DOVI_META_AVAIL 0
#endif
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libavcodec/avcodec.h>
Expand Down Expand Up @@ -498,6 +504,7 @@ MAP_PAIR_0_1_PROTO(disposition, str, tstring, av, uint32_t);

uint32_t parseDisposition(const tstring &disposition_str);
tstring getDispositionStr(uint32_t disposition);
RGYDOVIProfile getStreamDOVIProfile(const AVStream *stream);

#else
#define AV_NOPTS_VALUE (-1)
Expand Down
15 changes: 10 additions & 5 deletions NVEncCore/rgy_cmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5364,11 +5364,11 @@ int parse_one_common_option(const TCHAR *option_name, const TCHAR *strInput[], i
i++;
int value = 0;
if (get_list_value(list_dovi_profile, strInput[i], &value)) {
common->doviProfile = value;
common->doviProfile = (RGYDOVIProfile)value;
} else if (_stscanf_s(strInput[i], _T("%d"), &value) == 1) {
common->doviProfile = value;
common->doviProfile = (RGYDOVIProfile)value;
} else {
print_cmd_error_invalid_value(option_name, strInput[i], list_colorprim);
print_cmd_error_invalid_value(option_name, strInput[i], list_dovi_profile);
return 1;
}
return 0;
Expand Down Expand Up @@ -7287,7 +7287,11 @@ tstring gen_cmd(const RGYParamCommon *param, const RGYParamCommon *defaultPrm, b
OPT_TSTR(_T("--dhdr10-info"), dynamicHdr10plusJson);
}
OPT_LST(_T("--dolby-vision-profile"), doviProfile, list_dovi_profile);
OPT_STR_PATH(_T("--dolby-vision-rpu"), doviRpuFile);
if (param->doviRpuMetadataCopy) {
cmd << _T("--dolby-vision-rpu copy");
} else {
OPT_STR_PATH(_T("--dolby-vision-rpu"), doviRpuFile);
}
if (param->timecode || param->timecodeFile.length() > 0) {
cmd << (param->timecode ? _T("--timecode ") : _T("--no-timecode "));
if (param->timecodeFile.length() > 0) {
Expand Down Expand Up @@ -7536,7 +7540,8 @@ tstring gen_cmd_help_common() {
#if ENABLE_DOVI_METADATA_OPTIONS
str += print_list_options(_T("--dolby-vision-profile <int>"), list_dovi_profile, 0);
str += strsprintf(
_T(" --dolby-vision-rpu <string> Copy dolby vision metadata from input rpu file.\n"));
_T(" --dolby-vision-rpu <string> Copy dolby vision metadata from input rpu file.\n")
_T(" --dolby-vision-rpu copy Copy dolby vision metadata from input file.\n"));
#endif //#if ENABLE_DOVI_METADATA_OPTIONS
str += strsprintf(
_T(" --input-analyze <int> set time (sec) which reader analyze input file.\n")
Expand Down
21 changes: 16 additions & 5 deletions NVEncCore/rgy_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -474,12 +474,23 @@ const CX_DESC list_videoformat[] = {
{ NULL, 0 }
};


enum RGYDOVIProfile {
RGY_DOVI_PROFILE_UNSET = 0,
RGY_DOVI_PROFILE_COPY = -1,
RGY_DOVI_PROFILE_50 = 50,
RGY_DOVI_PROFILE_81 = 81,
RGY_DOVI_PROFILE_82 = 82,
RGY_DOVI_PROFILE_84 = 84,
};

const CX_DESC list_dovi_profile[] = {
{ _T("unset"), 0 },
{ _T("5.0"), 50 },
{ _T("8.1"), 81 },
{ _T("8.2"), 82 },
{ _T("8.4"), 84 },
{ _T("unset"), RGY_DOVI_PROFILE_UNSET },
{ _T("copy"), RGY_DOVI_PROFILE_COPY },
{ _T("5.0"), RGY_DOVI_PROFILE_50 },
{ _T("8.1"), RGY_DOVI_PROFILE_81 },
{ _T("8.2"), RGY_DOVI_PROFILE_82 },
{ _T("8.4"), RGY_DOVI_PROFILE_84 },
{ NULL, 0 }
};

Expand Down
31 changes: 29 additions & 2 deletions NVEncCore/rgy_frame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,22 @@ std::vector<uint8_t> RGYFrameDataHDR10plus::gen_nal() const {
}

std::vector<uint8_t> RGYFrameDataHDR10plus::gen_obu() const {
return gen_av1_obu_metadata(AV1_METADATA_TYPE_ITUT_T35, m_data);
// https://aomediacodec.github.io/av1-hdr10plus/#hdr10-metadata
static const uint8_t itut_t35_header[] = {
0xB5, // country code
0x00, 0x3C, // provider_code
0x00, 0x01, // provider_oriented_code
0x04, // application_identifier
0x01 // application_mode
};
std::vector<uint8_t> buf;
if (m_data.size() > sizeof(itut_t35_header) && memcmp(m_data.data(), itut_t35_header, sizeof(itut_t35_header)) == 0) {
buf = m_data;
} else {
buf = make_vector<uint8_t>(itut_t35_header);
vector_cat(buf, m_data);
}
return gen_av1_obu_metadata(AV1_METADATA_TYPE_ITUT_T35, buf);
}

RGYFrameDataDOVIRpu::RGYFrameDataDOVIRpu() : RGYFrameDataMetadata() { m_dataType = RGY_FRAME_DATA_DOVIRPU; };
Expand All @@ -194,7 +209,19 @@ std::vector<uint8_t> RGYFrameDataDOVIRpu::gen_nal() const {
return ret;
}
std::vector<uint8_t> RGYFrameDataDOVIRpu::gen_obu() const {
return gen_av1_obu_metadata(AV1_METADATA_TYPE_ITUT_T35, m_data);
static const uint8_t itut_t35_header[] = {
0xB5, // country code
0x00, 0x3B, // provider_code
0x00, 0x00, 0x08, 0x00 // provider_oriented_code
};
std::vector<uint8_t> buf;
if (m_data.size() > sizeof(itut_t35_header) && memcmp(m_data.data(), itut_t35_header, sizeof(itut_t35_header)) == 0) {
buf = m_data;
} else {
buf = make_vector<uint8_t>(itut_t35_header);
vector_cat(buf, m_data);
}
return gen_av1_obu_metadata(AV1_METADATA_TYPE_ITUT_T35, buf);
}
#endif

Expand Down
3 changes: 3 additions & 0 deletions NVEncCore/rgy_input.h
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,9 @@ class RGYInput {
RGY_CODEC getInputCodec() {
return m_inputVideoInfo.codec;
}
virtual RGYDOVIProfile getInputDOVIProfile() {
return RGY_DOVI_PROFILE_UNSET;
}
protected:
virtual RGY_ERR Init(const TCHAR *strFileName, VideoInfo *pInputInfo, const RGYInputPrm *prm) = 0;
virtual void CreateInputInfo(const TCHAR *inputTypeName, const TCHAR *inputCSpName, const TCHAR *outputCSpName, const TCHAR *convSIMD, const VideoInfo *inputPrm);
Expand Down
4 changes: 4 additions & 0 deletions NVEncCore/rgy_input_avcodec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3279,6 +3279,10 @@ RGY_ERR RGYInputAvcodec::LoadNextFrameInternal(RGYFrame *pSurface) {
}
#pragma warning(pop)

RGYDOVIProfile RGYInputAvcodec::getInputDOVIProfile() {
return getStreamDOVIProfile(m_Demux.video.stream);
}

int RGYInputAvcodec::GetHWDecDeviceID() {
return m_Demux.video.HWDecodeDeviceId;
}
Expand Down
2 changes: 2 additions & 0 deletions NVEncCore/rgy_input_avcodec.h
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,8 @@ class RGYInputAvcodec : public RGYInput

virtual rgy_rational<int> getInputTimebase() override;

virtual RGYDOVIProfile getInputDOVIProfile() override;

virtual bool rffAware() override;

//入力ファイルに存在する音声のトラック数を返す
Expand Down
Loading

0 comments on commit d63dea5

Please sign in to comment.