Skip to content

Commit

Permalink
alphaチャンネルのモードを指定するオプションを追加。( --alpha-channel-mode, #571 )
Browse files Browse the repository at this point in the history
  • Loading branch information
rigaya committed Aug 13, 2024
1 parent caed149 commit 4761d9a
Show file tree
Hide file tree
Showing 12 changed files with 62 additions and 13 deletions.
6 changes: 6 additions & 0 deletions NVEncC_Options.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
- [--cu-max \<int\> \[HEVC\]](#--cu-max-int-hevc)
- [--cu-min \<int\> \[HEVC\]](#--cu-min-int-hevc)
- [--alpha-bitrate-ratio \<int\> \[HEVC\]](#--alpha-bitrate-ratio-int-hevc)
- [--alpha-channel-mode \<string\> \[HEVC\]](#--alpha-channel-mode-string-hevc)
- [--tf-level \<int\> \[HEVC\]](#--tf-level-int-hevc)
- [--part-size-min \<int\> \[AV1\]](#--part-size-min-int-av1)
- [--part-size-max \<int\> \[AV1\]](#--part-size-max-int-av1)
Expand Down Expand Up @@ -755,6 +756,11 @@ Set bitrate ratio for alpha channel which can be used with ```--output-csp yuva4

When the value is set to "x", then approximately "1 / (x+1)" of the bitrate will be used for alpha channel. Therefore, smaller value will result more bitrate to be spent for alpha layer.

### --alpha-channel-mode &lt;string&gt; [HEVC]
Set alpha channel mode. (default: straight)
- straight
- premultiplied

### --tf-level &lt;int&gt; [HEVC]
Set HEVC temporal filtering, requires bframes >= 4. (Default: 0)
```
Expand Down
10 changes: 8 additions & 2 deletions NVEncC_Options.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
- [--cu-max \<int\> \[HEVC\]](#--cu-max-int-hevc)
- [--cu-min \<int\> \[HEVC\]](#--cu-min-int-hevc)
- [--alpha-bitrate-ratio \<int\> \[HEVC\]](#--alpha-bitrate-ratio-int-hevc)
- [--alpha-channel-mode \<string\> \[HEVC\]](#--alpha-channel-mode-string-hevc)
- [--tf-level \<int\> \[HEVC\]](#--tf-level-int-hevc)
- [--part-size-min \<int\> \[AV1\]](#--part-size-min-int-av1)
- [--part-size-max \<int\> \[AV1\]](#--part-size-max-int-av1)
Expand Down Expand Up @@ -758,9 +759,14 @@ HEVCの規格では64まで存在するが、現状NVENCでは32までしかサ
**画質が低下する恐れがあることがわかっているので、--cu-min / --cu-max の使用は非推奨。**

### --alpha-bitrate-ratio &lt;int&gt; [HEVC]
```--output-csp yuva420```でAlphaチャンネルエンコードを行う際に、Alphaチャンネルに割り当てるビットレートの割合を指定する。デフォルトは0で「自動」。
```--output-csp yuva420```でalphaチャンネルエンコードを行う際に、alphaチャンネルに割り当てるビットレートの割合を指定する。デフォルトは0で「自動」。

この値を"x"に設定すると、ビットレートの約 "1/(x+1)" がAlphaチャンネルに割り当てられる。つまり、値が小さいほど、Alphaチャンネルに多くのビットレートが使用される。
この値を"x"に設定すると、ビットレートの約 "1/(x+1)" がalphaチャンネルに割り当てられる。つまり、値が小さいほど、alphaチャンネルに多くのビットレートが使用される。

### --alpha-channel-mode &lt;string&gt; [HEVC]
```--output-csp yuva420```でalphaチャンネルエンコードを行う際のalphaチャンネルのモードを指定する。(デフォルト: straight)
- straight
- premultiplied

### --tf-level &lt;int&gt; [HEVC]
HEVC temporal filterの指定。Bフレーム数が4以上である必要がある。(デフォルト: 0)
Expand Down
19 changes: 18 additions & 1 deletion NVEncCore/NVEncCmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,10 @@ tstring encoder_help() {
_T(" warning: it is not recommended to use --cu-max or --cu-min,\n")
_T(" leaving it auto will enhance video quality.\n")
_T(" --alpha-bitrate-ratio <int> [HEVC] set ratio for alpha bitrate.\n")
_T(" smaller value will use more bitrate for alpha.\n"));
_T(" smaller value will use more bitrate for alpha.\n")
_T(" --alpha-channel-mode <string> [HEVC] set alpha channel mode.\n")
_T(" - straight (default)\n")
_T(" - premultiplied\n"));

str += strsprintf(_T("\n")
_T(" --part-size-min <int> [AV1] min size of luma coding block partition.\n")
Expand Down Expand Up @@ -1441,6 +1444,19 @@ int parse_one_option(const TCHAR *option_name, const TCHAR* strInput[], int& i,
}
return 0;
}
if (IS_OPTION("alpha-channel-mode")) {
i++;
int value = 0;
if (get_list_value(list_hevc_alpha_channel_mode, strInput[i], &value)) {
pParams->alphaChannelMode = value;
} else if (1 == _stscanf_s(strInput[i], _T("%d"), &value)) {
pParams->alphaChannelMode = value;
} else {
print_cmd_error_invalid_value(option_name, strInput[i]);
return 1;
}
return 0;
}
if (IS_OPTION("split-enc")) {
i++;
int value = 0;
Expand Down Expand Up @@ -1824,6 +1840,7 @@ tstring gen_cmd(const InEncodeVideoParam *pParams, const NV_ENC_CODEC_CONFIG cod
OPT_LST_HEVC(_T("--cu-max"), _T(""), maxCUSize, list_hevc_cu_size);
OPT_LST_HEVC(_T("--cu-min"), _T(""), minCUSize, list_hevc_cu_size);
OPT_NUM(_T("--alpha-bitrate-ratio"), alphaBitrateRatio);
OPT_LST(_T("--alpha-channel-mode"), alphaChannelMode, list_hevc_alpha_channel_mode);
}
if (pParams->codec_rgy == RGY_CODEC_H264 || save_disabled_prm) {
OPT_LST_H264(_T("--level"), _T(":h264"), level, list_avc_level);
Expand Down
3 changes: 2 additions & 1 deletion NVEncCore/NVEncCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,8 @@ NVENCSTATUS NVEncCore::InitOutput(InEncodeVideoParam *inputParams, NV_ENC_BUFFER
if (initWriters(m_pFileWriter, m_pFileWriterListAudio, m_pFileReader, m_AudioReaders,
&inputParams->common, &inputParams->input, &inputParams->ctrl, outputVideoInfo,
m_trimParam, m_outputTimebase, m_Chapters, m_hdrsei.get(), m_dovirpu.get(), m_encTimestamp.get(),
false, false, inputParams->alphaChannel, m_poolPkt.get(), m_poolFrame.get(), m_pStatus, m_pPerfMonitor, m_pNVLog) != RGY_ERR_NONE) {
false, false, inputParams->alphaChannel, inputParams->alphaChannelMode,
m_poolPkt.get(), m_poolFrame.get(), m_pStatus, m_pPerfMonitor, m_pNVLog) != RGY_ERR_NONE) {
PrintMes(RGY_LOG_ERROR, _T("failed to initialize file reader(s).\n"));
return NV_ENC_ERR_GENERIC;
}
Expand Down
1 change: 1 addition & 0 deletions NVEncCore/NVEncParam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ InEncodeVideoParam::InEncodeVideoParam() :
losslessIgnoreInputCsp(0),
alphaChannel(false),
alphaBitrateRatio(0),
alphaChannelMode(0),
nWeightP(0),
chromaQPOffset(0),
brefMode(NV_ENC_BFRAME_REF_MODE_AUTO),
Expand Down
7 changes: 7 additions & 0 deletions NVEncCore/NVEncParam.h
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,12 @@ const CX_DESC list_nvenc_caps_me_only[] = {
{ NULL, 0 }
};

const CX_DESC list_hevc_alpha_channel_mode[] = {
{ _T("straight"), 0 },
{ _T("premultiplied"), 1 },
{ NULL, 0 }
};

typedef struct NVEncCap {
int id; //feature ID
const TCHAR *name; //feature名
Expand Down Expand Up @@ -729,6 +735,7 @@ struct InEncodeVideoParam {
int losslessIgnoreInputCsp;
bool alphaChannel;
int alphaBitrateRatio;
int alphaChannelMode;
int nWeightP;
int chromaQPOffset;
int brefMode;
Expand Down
8 changes: 4 additions & 4 deletions NVEncCore/rgy_bitstream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ int get_hevc_sei_size(size_t& size, const uint8_t *ptr) {
return ptr - orig_ptr;
}

std::vector<uint8_t> gen_hevc_alpha_channel_info_sei() {
std::vector<uint8_t> gen_hevc_alpha_channel_info_sei(const int mode) {
// NVENCの作成するalpha_channel_info_seiはなんか変
// 下記資料に基づいて、適切なものを再生成する
// https://developer.apple.com/av-foundation/HEVC-Video-with-Alpha-Interoperability-Profile.pdf
Expand All @@ -89,10 +89,10 @@ std::vector<uint8_t> gen_hevc_alpha_channel_info_sei() {
add_u16(buf, u16);
buf.push_back(ALPHA_CHANNEL_INFO);
buf.push_back(4); // size
buf.push_back((mode & 0x07) << 4);
buf.push_back(0);
buf.push_back(0);
buf.push_back(0xff);
buf.push_back(1 << 7);
buf.push_back(0x7f);
buf.push_back(0x80); // 0x90 -> 0x80
to_nal(buf);

std::vector<uint8_t> nalbuf;
Expand Down
2 changes: 1 addition & 1 deletion NVEncCore/rgy_bitstream.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ size_t get_av1_uleb_size_bytes(uint64_t value);
std::vector<uint8_t> get_av1_uleb_size_data(uint64_t value);
std::vector<uint8_t> gen_av1_obu_metadata(const uint8_t metadata_type, const std::vector<uint8_t>& metadata);
int get_hevc_sei_size(size_t& size, const uint8_t *ptr);
std::vector<uint8_t> gen_hevc_alpha_channel_info_sei();
std::vector<uint8_t> gen_hevc_alpha_channel_info_sei(const int mode);

struct RGYHDRMetadataPrm {
int maxcll;
Expand Down
9 changes: 7 additions & 2 deletions NVEncCore/rgy_output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ RGYOutput::RGYOutput() :
m_sourceHWMem(false),
m_y4mHeaderWritten(false),
m_enableHEVCAlphaChannelInfoSEIFix(false),
m_HEVCAlphaChannelMode(0),
m_strWriterName(),
m_strOutputInfo(),
m_VideoOutputInfo(),
Expand Down Expand Up @@ -387,7 +388,7 @@ RGY_ERR RGYOutput::FixHEVCAlphaChannelInfoSEI(RGYBitstream *bitstream) {
const auto sei_data = unnal(ptr, nal.size - nal_header_size);
const auto sei_type = sei_data[0];
if (sei_type == ALPHA_CHANNEL_INFO) { // alpha_channel_information
const auto nalbuf = gen_hevc_alpha_channel_info_sei();
const auto nalbuf = gen_hevc_alpha_channel_info_sei(m_HEVCAlphaChannelMode);
bitstream->append(nalbuf.data(), nalbuf.size());
} else {
bitstream->append(nal.ptr, nal.size);
Expand Down Expand Up @@ -681,7 +682,8 @@ RGY_ERR RGYOutputRaw::Init(const TCHAR *strFileName, const VideoInfo *pVideoOutp
m_doviRpu = rawPrm->doviRpu;
m_timestamp = rawPrm->vidTimestamp;
m_debugDirectAV1Out = rawPrm->debugDirectAV1Out;
m_enableHEVCAlphaChannelInfoSEIFix = ENCODER_NVENC && rawPrm->codecId == RGY_CODEC_HEVC && rawPrm->HEVCAlphaChannel;
m_HEVCAlphaChannelMode = rawPrm->HEVCAlphaChannelMode;
m_enableHEVCAlphaChannelInfoSEIFix = rawPrm->codecId == RGY_CODEC_HEVC && rawPrm->HEVCAlphaChannel;
if (m_enableHEVCAlphaChannelInfoSEIFix) {
AddMessage(RGY_LOG_DEBUG, _T("enableHEVCAlphaChannelInfoSEIFix : on\n"));
}
Expand Down Expand Up @@ -1125,6 +1127,7 @@ RGY_ERR initWriters(
const bool videoDtsUnavailable,
const bool benchmark,
const bool HEVCAlphaChannel,
const int HEVCAlphaChannelMode,
RGYPoolAVPacket *poolPkt,
RGYPoolAVFrame *poolFrame,
shared_ptr<EncodeStatus> pStatus,
Expand Down Expand Up @@ -1197,6 +1200,7 @@ RGY_ERR initWriters(
writerPrm.lowlatency = ctrl->lowLatency;
writerPrm.debugDirectAV1Out = common->debugDirectAV1Out;
writerPrm.HEVCAlphaChannel = HEVCAlphaChannel;
writerPrm.HEVCAlphaChannelMode = HEVCAlphaChannelMode;
writerPrm.muxOpt = common->muxOpt;
writerPrm.poolPkt = poolPkt;
writerPrm.poolFrame = poolFrame;
Expand Down Expand Up @@ -1501,6 +1505,7 @@ RGY_ERR initWriters(
rawPrm.vidTimestamp = vidTimestamp;
rawPrm.debugDirectAV1Out = common->debugDirectAV1Out;
rawPrm.HEVCAlphaChannel = HEVCAlphaChannel;
rawPrm.HEVCAlphaChannelMode = HEVCAlphaChannelMode;
rawPrm.debugRawOut = common->debugRawOut;
rawPrm.outReplayFile = common->outReplayFile;
rawPrm.outReplayCodec = common->outReplayCodec;
Expand Down
3 changes: 3 additions & 0 deletions NVEncCore/rgy_output.h
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ class RGYOutput {
bool m_sourceHWMem;
bool m_y4mHeaderWritten;
bool m_enableHEVCAlphaChannelInfoSEIFix;
int m_HEVCAlphaChannelMode;
tstring m_strWriterName;
tstring m_strOutputInfo;
VideoInfo m_VideoOutputInfo;
Expand All @@ -314,6 +315,7 @@ struct RGYOutputRawPrm {
bool debugDirectAV1Out;
bool debugRawOut;
bool HEVCAlphaChannel;
int HEVCAlphaChannelMode;
tstring outReplayFile;
RGY_CODEC outReplayCodec;
int bufSizeMB;
Expand Down Expand Up @@ -366,6 +368,7 @@ RGY_ERR initWriters(
const bool videoDtsUnavailable,
const bool benchmark,
const bool HEVCAlphaChannel,
const int HEVCAlphaChannelMode,
RGYPoolAVPacket *poolPkt,
RGYPoolAVFrame *poolFrame,
shared_ptr<EncodeStatus> pStatus,
Expand Down
5 changes: 3 additions & 2 deletions NVEncCore/rgy_output_avcodec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,8 @@ RGY_ERR RGYOutputAvcodec::InitVideo(const VideoInfo *videoOutputInfo, const Avco
m_Mux.video.outputFps = av_make_q(videoOutputInfo->fpsN, videoOutputInfo->fpsD);
AddMessage(RGY_LOG_DEBUG, _T("output video stream fps: %d/%d\n"), m_Mux.video.outputFps.num, m_Mux.video.outputFps.den);

m_enableHEVCAlphaChannelInfoSEIFix = ENCODER_NVENC && videoOutputInfo->codec == RGY_CODEC_HEVC && prm->HEVCAlphaChannel;
m_HEVCAlphaChannelMode = prm->HEVCAlphaChannelMode;
m_enableHEVCAlphaChannelInfoSEIFix = videoOutputInfo->codec == RGY_CODEC_HEVC && prm->HEVCAlphaChannel;
if (m_enableHEVCAlphaChannelInfoSEIFix) {
AddMessage(RGY_LOG_DEBUG, _T("enableHEVCAlphaChannelInfoSEIFix : on\n"));
}
Expand Down Expand Up @@ -2406,7 +2407,7 @@ RGY_ERR RGYOutputAvcodec::AddHeaderToExtraDataHEVC(const RGYBitstream *bitstream
// alpha_channel_infoもextradataに追加しておく必要がある
if (sei_type == ALPHA_CHANNEL_INFO) {
if (m_enableHEVCAlphaChannelInfoSEIFix) { // NVENCのalpha_channel_info SEIの出力は変なので、適切なものを追加しておく
vector_cat(hevc_header, gen_hevc_alpha_channel_info_sei());
vector_cat(hevc_header, gen_hevc_alpha_channel_info_sei(m_HEVCAlphaChannelMode));
} else {
vector_cat(hevc_header, nal.ptr, nal.size);
}
Expand Down
2 changes: 2 additions & 0 deletions NVEncCore/rgy_output_avcodec.h
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ struct AvcodecWriterPrm {
bool disableMp4Opt; //mp4出力時のmuxの最適化を無効にする
bool debugDirectAV1Out; //AV1出力のデバッグ用
bool HEVCAlphaChannel; //HEVCのalphaチェンネルを使用するか
int HEVCAlphaChannelMode; //HEVCのalphaチェンネルのモード
RGYPoolAVPacket *poolPkt; //読み込み側からわたってきたパケットの返却先
RGYPoolAVFrame *poolFrame; //読み込み側からわたってきたパケットの返却先

Expand Down Expand Up @@ -443,6 +444,7 @@ struct AvcodecWriterPrm {
disableMp4Opt(false),
debugDirectAV1Out(false),
HEVCAlphaChannel(false),
HEVCAlphaChannelMode(0),
poolPkt(nullptr),
poolFrame(nullptr) {
}
Expand Down

0 comments on commit 4761d9a

Please sign in to comment.