diff --git a/NVEncC_Options.en.md b/NVEncC_Options.en.md index 9a886891..70eb8d44 100644 --- a/NVEncC_Options.en.md +++ b/NVEncC_Options.en.md @@ -123,7 +123,7 @@ - [--dhdr10-info copy \[HEVC, AV1\]](#--dhdr10-info-copy-hevc-av1) - [--dolby-vision-profile \ \[HEVC, AV1\]](#--dolby-vision-profile-string-hevc-av1) - [--dolby-vision-rpu \ \[HEVC, AV1\]](#--dolby-vision-rpu-string-hevc-av1) - - [--dolby-vision-rpu copy \[HEVC\]](#--dolby-vision-rpu-copy-hevc) + - [--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) @@ -900,7 +900,7 @@ unset, copy, 5.0, 8.1, 8.2, 8.4 ### --dolby-vision-rpu <string> [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] +### --dolby-vision-rpu copy [HEVC, AV1] Interleave Dolby Vision RPU metadata copied from HEVC input file. Recommended to be used with [--dolby-vision-profile](#--dolby-vision-profile-string). Limitations for avhw reader: this option uses timestamps to reorder frames to decoded order to presentation order. diff --git a/NVEncCore/rgy_bitstream.cpp b/NVEncCore/rgy_bitstream.cpp index 3345d69c..490850a6 100644 --- a/NVEncCore/rgy_bitstream.cpp +++ b/NVEncCore/rgy_bitstream.cpp @@ -525,7 +525,7 @@ int DOVIRpu::get_next_rpu_nal(std::vector& bytes, const int64_t id) { if (int ret = get_next_rpu(rpu, id); ret != 0) { return ret; } - //to_nal(rpu); // NALU_HEVC_UNSPECIFIEDの場合は不要 + //to_nal(rpu); // get_next_rpuはすでにこの処理を実施済みのものを返す if (rpu.back() == 0x00) { // 最後が0x00の場合 rpu.push_back(0x03); } @@ -540,6 +540,38 @@ int DOVIRpu::get_next_rpu_nal(std::vector& bytes, const int64_t id) { return 0; } +int DOVIRpu::get_next_rpu_obu(std::vector& bytes, const int64_t id) { + std::vector tmp; + if (int ret = get_next_rpu(tmp, id); ret != 0) { + return ret; + } + + auto rpu = unnal(tmp.data(), tmp.size()); + + static const uint8_t itut_t35_header[] = { + 0xB5, // country code + 0x00, 0x3B, // provider_code + 0x00, 0x00, 0x08, 0x00 // provider_oriented_code + }; + std::vector buf; + if (rpu.size() > sizeof(itut_t35_header) && memcmp(rpu.data(), itut_t35_header, sizeof(itut_t35_header)) == 0) { + buf = rpu; + } else { + buf = make_vector(itut_t35_header); + vector_cat(buf, rpu); + } + bytes = gen_av1_obu_metadata(AV1_METADATA_TYPE_ITUT_T35, buf); + return 0; +} + +int DOVIRpu::get_next_rpu(std::vector& bytes, const int64_t id, const RGY_CODEC codec) { + switch (codec) { + case RGY_CODEC_HEVC: return get_next_rpu_nal(bytes, id); + case RGY_CODEC_AV1: return get_next_rpu_obu(bytes, id); + default: return 1; + } +} + const DOVIProfile *getDOVIProfile(const int id) { static const std::array DOVI_PROFILES = { DOVIProfile{ 50, true, true, true, VideoVUIInfo(1, RGY_PRIM_UNSPECIFIED, RGY_MATRIX_UNSPECIFIED, RGY_TRANSFER_UNSPECIFIED, 5, RGY_COLORRANGE_FULL, RGY_CHROMALOC_UNSPECIFIED) }, diff --git a/NVEncCore/rgy_bitstream.h b/NVEncCore/rgy_bitstream.h index d747bbe7..77b09d65 100644 --- a/NVEncCore/rgy_bitstream.h +++ b/NVEncCore/rgy_bitstream.h @@ -274,6 +274,8 @@ class DOVIRpu { ~DOVIRpu(); int init(const TCHAR *rpu_file); int get_next_rpu_nal(std::vector& bytes, const int64_t id); + int get_next_rpu_obu(std::vector& bytes, const int64_t id); + int get_next_rpu(std::vector& bytes, const int64_t id, const RGY_CODEC codec); const tstring& get_filepath() const; protected: diff --git a/NVEncCore/rgy_output.cpp b/NVEncCore/rgy_output.cpp index 6de2c473..6760f54c 100644 --- a/NVEncCore/rgy_output.cpp +++ b/NVEncCore/rgy_output.cpp @@ -740,11 +740,11 @@ RGY_ERR RGYOutputRaw::WriteNextOneFrame(RGYBitstream *pBitstream) { } if (m_doviRpu) { std::vector dovi_nal; - if (m_doviRpu->get_next_rpu_nal(dovi_nal, bs_framedata.inputFrameId) != 0) { + if (m_doviRpu->get_next_rpu(dovi_nal, bs_framedata.inputFrameId, m_VideoOutputInfo.codec) != 0) { AddMessage(RGY_LOG_ERROR, _T("Failed to get dovi rpu for %lld.\n"), bs_framedata.inputFrameId); } if (dovi_nal.size() > 0) { - metadataList.push_back(std::make_unique(dovi_nal, false, true)); + metadataList.push_back(std::make_unique(dovi_nal, false, m_VideoOutputInfo.codec == RGY_CODEC_HEVC ? true : false)); } } else { auto [err_dovirpu, metadata_dovi_rpu] = getMetadata(RGY_FRAME_DATA_DOVIRPU, bs_framedata); diff --git a/NVEncCore/rgy_output_avcodec.cpp b/NVEncCore/rgy_output_avcodec.cpp index a7e6e073..6a021ffa 100644 --- a/NVEncCore/rgy_output_avcodec.cpp +++ b/NVEncCore/rgy_output_avcodec.cpp @@ -2759,11 +2759,11 @@ RGY_ERR RGYOutputAvcodec::WriteNextFrameInternalOneFrame(RGYBitstream *bitstream } if (m_Mux.video.doviRpu) { std::vector dovi_nal; - if (m_Mux.video.doviRpu->get_next_rpu_nal(dovi_nal, bs_framedata.inputFrameId) != 0) { + if (m_Mux.video.doviRpu->get_next_rpu(dovi_nal, bs_framedata.inputFrameId, m_VideoOutputInfo.codec) != 0) { AddMessage(RGY_LOG_ERROR, _T("Failed to get dovi rpu for %lld.\n"), bs_framedata.inputFrameId); } if (dovi_nal.size() > 0) { - metadataList.push_back(std::make_unique(dovi_nal, false, true)); + metadataList.push_back(std::make_unique(dovi_nal, false, m_VideoOutputInfo.codec == RGY_CODEC_HEVC ? true : false)); } } else { auto [err_dovirpu, metadata_dovi_rpu] = getMetadata(RGY_FRAME_DATA_DOVIRPU, bs_framedata);