Skip to content

Commit

Permalink
--dolby-vision-rpu使用時にレターボックス部分をcropをした場合にそれを反映させるオプションを追加。 ( #222, -…
Browse files Browse the repository at this point in the history
…-dolby-vision-rpu-prm crop )
  • Loading branch information
rigaya committed Nov 19, 2024
1 parent 4684fcd commit d651d8c
Show file tree
Hide file tree
Showing 14 changed files with 154 additions and 34 deletions.
5 changes: 5 additions & 0 deletions QSVEnc/QSVEnc_readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,11 @@ API v1.1 … Intel Media SDK v2.0


【どうでもいいメモ】
2024.11.xx (7.74)
- --dolby-vision-profileで対象外のプロファイルも読み込めていた問題を修正。
- --dolby-vision-rpu使用時にレターボックス部分をcropをした場合にそれを反映させるオプションを追加。 ( --dolby-vision-rpu-prm crop )
- --dolby-visionに関するモード制限を解除。

2024.11.12 (7.73)
- --dolby-vision-rpu copyを使用して長時間のエンコードを行うと、エンコード速度が著しく低下していくのを改善し、速度を維持し続けられるように。
- AV1出力時に--dhdr10-infoを使用した時の出力を改善。
Expand Down
16 changes: 16 additions & 0 deletions QSVEncC_Options.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@
- [--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)
- [--dolby-vision-rpu-prm \<param1\>=\<value1\>\[,\<param2\>=\<value2\>\]...](#--dolby-vision-rpu-prm-param1value1param2value2)
- [--aud](#--aud)
- [--pic-struct](#--pic-struct)
- [--buf-period](#--buf-period)
Expand Down Expand Up @@ -952,6 +953,21 @@ Interleave Dolby Vision RPU metadata copied from HEVC input file. Recommended to
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-rpu-prm &lt;param1&gt;=&lt;value1&gt;[,&lt;param2&gt;=&lt;value2&gt;]...

Set parameters for ```--dolby-vision-rpu```.

- **parameters**

- crop=&lt;bool&gt;

Set active area offsets to 0 (no letterbox bars).

- Examples
```
Example: --dolby-vision-rpu-prm crop=true
```

### --aud
Insert Access Unit Delimiter NAL.

Expand Down
16 changes: 16 additions & 0 deletions QSVEncC_Options.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@
- [--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)
- [--dolby-vision-rpu-prm \<param1\>=\<value1\>\[,\<param2\>=\<value2\>\]...](#--dolby-vision-rpu-prm-param1value1param2value2)
- [--aud](#--aud)
- [--pic-struct](#--pic-struct)
- [--buf-period](#--buf-period)
Expand Down Expand Up @@ -976,6 +977,21 @@ HEVCの入力ファイルから読み取ったdolby visionのmetadataを出力
avhw読み込みでは、フレームの並び替えにタイムスタンプを使用するため、タイムスタンプの取得できないraw ESのような入力ファイルでは使用できません。
こうした場合には、avsw読み込みを使用してください。

### --dolby-vision-rpu-prm &lt;param1&gt;=&lt;value1&gt;[,&lt;param2&gt;=&lt;value2&gt;]...

```--dolby-vision-rpu```用のパラメータを指定する。

- **パラメータ**

- crop=&lt;bool&gt;

RPUのactive area offsetsを0に設定する (レターボックスなしの意味)。

- 使用例
```
例: --dolby-vision-rpu-prm crop=true
```


### --aud
Access Unit Delimiter NALを挿入する。
Expand Down
51 changes: 50 additions & 1 deletion QSVPipeline/rgy_cmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6155,6 +6155,40 @@ int parse_one_common_option(const TCHAR *option_name, const TCHAR *strInput[], i
}
return 0;
}
if (IS_OPTION("dolby-vision-rpu-prm")) {
i++;
const auto paramList = std::vector<std::string>{ "crop" };
for (const auto &param : split(strInput[i], _T(","))) {
auto pos = param.find_first_of(_T("="));
if (pos != std::string::npos) {
auto param_arg = tolowercase(param.substr(0, pos));
auto param_val = param.substr(pos + 1);
if (param_arg == _T("crop")) {
bool b = false;
if (!cmd_string_to_bool(&b, param_val)) {
common->doviRpuActiveAreaOffsets.reset((b) ? new RGYDOVIRpuActiveAreaOffsets() : nullptr);
if (b) {

}
} else {
print_cmd_error_invalid_value(tstring(option_name) + _T(" ") + param_arg + _T("="), param_val);
return 1;
}
continue;
}
print_cmd_error_unknown_opt_param(option_name, param_arg, paramList);
return 1;
} else {
if (param == _T("crop")) {
common->doviRpuActiveAreaOffsets.reset(new RGYDOVIRpuActiveAreaOffsets());
continue;
}
print_cmd_error_unknown_opt_param(option_name, param, paramList);
return 1;
}
}
return 0;
}
#endif //#if ENABLE_DOVI_METADATA_OPTIONS
if (IS_OPTION("timecode")) {
common->timecode = true;
Expand Down Expand Up @@ -8200,6 +8234,16 @@ tstring gen_cmd(const RGYParamCommon *param, const RGYParamCommon *defaultPrm, b
} else {
OPT_STR_PATH(_T("--dolby-vision-rpu"), doviRpuFile);
}

if (param->doviRpuActiveAreaOffsets != defaultPrm->doviRpuActiveAreaOffsets) {
tmp.str(tstring());
if (param->doviRpuActiveAreaOffsets) {
tmp << ",crop=on";
}
if (!tmp.str().empty()) {
cmd << _T(" --dolby-vision-rpu-prm ") << tmp.str().substr(1);
}
}
if (param->timecode || param->timecodeFile.length() > 0) {
cmd << (param->timecode ? _T("--timecode ") : _T("--no-timecode "));
if (param->timecodeFile.length() > 0) {
Expand Down Expand Up @@ -8451,7 +8495,12 @@ tstring gen_cmd_help_common() {
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 copy Copy dolby vision metadata from input file.\n"));
_T(" --dolby-vision-rpu copy Copy dolby vision metadata from input file.\n")
_T(" --dolby-vision-rpu-prm <param1>=<value>[,<param2>=<value>][...]\n")
_T(" parameters for --dolby-vision-rpu.\n")
_T(" params\n")
_T(" crop=<bool> Set active area offsets to 0 (no letterbox bars).\n")
);
#endif //#if ENABLE_DOVI_METADATA_OPTIONS
str += strsprintf(
_T(" --input-analyze <int> set time (sec) which reader analyze input file.\n")
Expand Down
5 changes: 5 additions & 0 deletions QSVPipeline/rgy_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,11 @@ const CX_DESC list_dovi_profile_parse[] = {
{ NULL, 0 }
};

struct RGYDOVIRpuActiveAreaOffsets {
uint16_t left, top, right, bottom;

RGYDOVIRpuActiveAreaOffsets() : left(0), top(0), right(0), bottom(0) {};
};

// 1st luma line > |X X ... |3 4 X ... X が輝度ピクセル位置
// | |1 2 1-6 are possible chroma positions
Expand Down
57 changes: 32 additions & 25 deletions QSVPipeline/rgy_frame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,37 +190,44 @@ RGYFrameDataDOVIRpu::~RGYFrameDataDOVIRpu() { }
RGY_ERR RGYFrameDataDOVIRpu::convert(const RGYFrameDataMetadataConvertParam *metadataprm) {
#if ENABLE_LIBDOVI
auto prm = dynamic_cast<const RGYFrameDataDOVIRpuConvertParam*>(metadataprm);
if (!prm || !prm->enable) {
return RGY_ERR_NONE;
}
if (prm->doviProfileDst != RGY_DOVI_PROFILE_81 && prm->doviProfileDst != RGY_DOVI_PROFILE_COPY) {
if (!prm) {
return RGY_ERR_NONE;
}
if (m_data.size() == 0) {
return RGY_ERR_NONE;
}
std::unique_ptr<DoviRpuOpaque, decltype(&dovi_rpu_free)> rpu(dovi_parse_rpu(m_data.data(), m_data.size()), dovi_rpu_free);
if (!rpu) {
return RGY_ERR_INVALID_BINARY;
}
std::unique_ptr<const DoviRpuDataHeader, decltype(&dovi_rpu_free_header)> header(dovi_rpu_get_header(rpu.get()), dovi_rpu_free_header);
if (!header) {
return RGY_ERR_UNKNOWN;
}
const auto dovi_profile = header->guessed_profile;
if (dovi_profile != 7) {
return RGY_ERR_NONE;
}
const int ret = dovi_convert_rpu_with_mode(rpu.get(), 2);
if (ret != 0) {
return RGY_ERR_INVALID_OPERATION;
}
std::unique_ptr<const DoviData, decltype(&dovi_data_free)> rpu_data(dovi_write_rpu(rpu.get()), dovi_data_free);
if (!rpu_data) {
return RGY_ERR_NULL_PTR;
if (prm->convertProfile || prm->activeAreaOffsets || prm->removeMapping) {
std::unique_ptr<DoviRpuOpaque, decltype(&dovi_rpu_free)> rpu(dovi_parse_rpu(m_data.data(), m_data.size()), dovi_rpu_free);
if (!rpu) {
return RGY_ERR_INVALID_BINARY;
}
std::unique_ptr<const DoviRpuDataHeader, decltype(&dovi_rpu_free_header)> header(dovi_rpu_get_header(rpu.get()), dovi_rpu_free_header);
if (!header) {
return RGY_ERR_UNKNOWN;
}
const auto dovi_profile = header->guessed_profile;
if (prm->convertProfile
&& dovi_profile == 7
&& (prm->doviProfileDst == RGY_DOVI_PROFILE_81 || prm->doviProfileDst == RGY_DOVI_PROFILE_COPY)) {
const int ret = dovi_convert_rpu_with_mode(rpu.get(), 2);
if (ret != 0) {
return RGY_ERR_INVALID_OPERATION;
}
}
if (prm->activeAreaOffsets) {
dovi_rpu_set_active_area_offsets(rpu.get(),
prm->activeAreaOffsets->left, prm->activeAreaOffsets->right, prm->activeAreaOffsets->top, prm->activeAreaOffsets->bottom);
}
if (prm->removeMapping) {
dovi_rpu_remove_mapping(rpu.get());
}
std::unique_ptr<const DoviData, decltype(&dovi_data_free)> rpu_data(dovi_write_rpu(rpu.get()), dovi_data_free);
if (!rpu_data) {
return RGY_ERR_NULL_PTR;
}
m_data.resize(rpu_data->len);
memcpy(m_data.data(), rpu_data->data, rpu_data->len);
}
m_data.resize(rpu_data->len);
memcpy(m_data.data(), rpu_data->data, rpu_data->len);
#endif // ENABLE_LIBDOVI
return RGY_ERR_NONE;
}
Expand Down
15 changes: 12 additions & 3 deletions QSVPipeline/rgy_frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,11 @@ class RGYFrameDataQP : public RGYFrameData {

class RGYFrameDataMetadataConvertParam {
public:
bool enable;
bool convertProfile;
bool removeMapping;
std::unique_ptr<RGYDOVIRpuActiveAreaOffsets> activeAreaOffsets;

RGYFrameDataMetadataConvertParam() : enable(false) {}
RGYFrameDataMetadataConvertParam() : convertProfile(false), removeMapping(false), activeAreaOffsets() {};
virtual ~RGYFrameDataMetadataConvertParam() {};
};

Expand Down Expand Up @@ -125,7 +127,14 @@ class RGYFrameDataDOVIRpuConvertParam : public RGYFrameDataMetadataConvertParam
RGYDOVIProfile doviProfileDst;

RGYFrameDataDOVIRpuConvertParam() : RGYFrameDataMetadataConvertParam(), doviProfileDst(RGY_DOVI_PROFILE_UNSET) {}
RGYFrameDataDOVIRpuConvertParam(RGYDOVIProfile profile) : RGYFrameDataMetadataConvertParam(), doviProfileDst(profile) { enable = true; }
RGYFrameDataDOVIRpuConvertParam(RGYDOVIProfile profile, const RGYDOVIRpuActiveAreaOffsets *activeAreaOffsets_) :
RGYFrameDataMetadataConvertParam(), doviProfileDst(profile) {
convertProfile = true;
removeMapping = false;
if (activeAreaOffsets_) {
activeAreaOffsets = std::make_unique<RGYDOVIRpuActiveAreaOffsets>(*activeAreaOffsets_);
}
}
virtual ~RGYFrameDataDOVIRpuConvertParam() {};
};

Expand Down
6 changes: 5 additions & 1 deletion QSVPipeline/rgy_output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,7 @@ RGYOutputRaw::RGYOutputRaw() :
m_doviProfileDst(RGY_DOVI_PROFILE_UNSET),
m_doviRpu(nullptr),
m_doviRpuMetadataCopy(false),
m_doviRpuActiveAreaOffsets(nullptr),
m_timestamp(nullptr),
m_prevInputFrameId(-1),
m_prevEncodeFrameId(-1),
Expand Down Expand Up @@ -715,6 +716,7 @@ RGY_ERR RGYOutputRaw::Init(const TCHAR *strFileName, const VideoInfo *pVideoOutp
m_doviProfileDst = rawPrm->doviProfile;
m_doviRpu = rawPrm->doviRpu;
m_doviRpuMetadataCopy = rawPrm->doviRpuMetadataCopy;
m_doviRpuActiveAreaOffsets = (rawPrm->doviRpuActiveAreaOffsets) ? std::make_unique<RGYDOVIRpuActiveAreaOffsets>(*rawPrm->doviRpuActiveAreaOffsets) : nullptr;
m_timestamp = rawPrm->vidTimestamp;
m_debugDirectAV1Out = rawPrm->debugDirectAV1Out;
m_HEVCAlphaChannelMode = rawPrm->HEVCAlphaChannelMode;
Expand Down Expand Up @@ -837,7 +839,7 @@ RGY_ERR RGYOutputRaw::WriteNextOneFrame(RGYBitstream *pBitstream) {
metadataList.push_back(std::make_unique<RGYOutputInsertMetadata>(dovi_nal, false, m_VideoOutputInfo.codec == RGY_CODEC_HEVC ? true : false));
}
} else if (m_doviRpuMetadataCopy) {
auto doviRpuConvPrm = (m_doviProfileDst == RGY_DOVI_PROFILE_COPY) ? std::make_unique<RGYFrameDataDOVIRpuConvertParam>(m_doviProfileDst) : nullptr;
auto doviRpuConvPrm = (m_doviProfileDst == RGY_DOVI_PROFILE_COPY) ? std::make_unique<RGYFrameDataDOVIRpuConvertParam>(m_doviProfileDst, m_doviRpuActiveAreaOffsets.get()) : nullptr;
auto [err_dovirpu, metadata_dovi_rpu] = getMetadata<RGYFrameDataDOVIRpu>(RGY_FRAME_DATA_DOVIRPU, bs_framedata, doviRpuConvPrm.get());
if (err_dovirpu != RGY_ERR_NONE) {
return err_dovirpu;
Expand Down Expand Up @@ -1228,6 +1230,7 @@ RGY_ERR initWriters(
writerPrm.doviRpu = doviRpu;
writerPrm.doviRpuMetadataCopy = common->doviRpuMetadataCopy;
writerPrm.doviProfile = common->doviProfile;
writerPrm.doviRpuActiveAreaOffsets = common->doviRpuActiveAreaOffsets.get();
writerPrm.vidTimestamp = vidTimestamp;
writerPrm.videoCodecTag = common->videoCodecTag;
writerPrm.videoMetadata = common->videoMetadata;
Expand Down Expand Up @@ -1542,6 +1545,7 @@ RGY_ERR initWriters(
rawPrm.doviProfile = common->doviProfile;
rawPrm.doviRpu = doviRpu;
rawPrm.doviRpuMetadataCopy = common->doviRpuMetadataCopy;
rawPrm.doviRpuActiveAreaOffsets = common->doviRpuActiveAreaOffsets.get();
rawPrm.vidTimestamp = vidTimestamp;
rawPrm.debugDirectAV1Out = common->debugDirectAV1Out;
rawPrm.HEVCAlphaChannel = HEVCAlphaChannel;
Expand Down
2 changes: 2 additions & 0 deletions QSVPipeline/rgy_output.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ struct RGYOutputRawPrm {
RGYDOVIProfile doviProfile;
DOVIRpu *doviRpu;
bool doviRpuMetadataCopy; //doviのmetadataのコピー
const RGYDOVIRpuActiveAreaOffsets *doviRpuActiveAreaOffsets;
RGYTimestamp *vidTimestamp;
};

Expand All @@ -346,6 +347,7 @@ class RGYOutputRaw : public RGYOutput {
RGYDOVIProfile m_doviProfileDst;
DOVIRpu *m_doviRpu;
bool m_doviRpuMetadataCopy;
std::unique_ptr<RGYDOVIRpuActiveAreaOffsets> m_doviRpuActiveAreaOffsets;
RGYTimestamp *m_timestamp;
int64_t m_prevInputFrameId;
int64_t m_prevEncodeFrameId;
Expand Down
4 changes: 3 additions & 1 deletion QSVPipeline/rgy_output_avcodec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ AVMuxVideo::AVMuxVideo() :
doviProfileDst(RGY_DOVI_PROFILE_UNSET),
doviRpu(nullptr),
doviRpuMetadataCopy(false),
doviRpuActiveAreaOffsets(nullptr),
bsfc(nullptr),
bsfcBuffer(nullptr),
bsfcBufferLength(0),
Expand Down Expand Up @@ -897,6 +898,7 @@ RGY_ERR RGYOutputAvcodec::InitVideo(const VideoInfo *videoOutputInfo, const Avco
m_Mux.video.bsfcBufferLength = 0;
m_Mux.video.hdr10plusMetadataCopy = prm->hdr10plusMetadataCopy;
m_Mux.video.doviRpuMetadataCopy = prm->doviRpuMetadataCopy;
m_Mux.video.doviRpuActiveAreaOffsets = (prm->doviRpuActiveAreaOffsets) ? std::make_unique<RGYDOVIRpuActiveAreaOffsets>(*prm->doviRpuActiveAreaOffsets) : nullptr;

auto retm = SetMetadata(&m_Mux.video.streamOut->metadata, (prm->videoInputStream) ? prm->videoInputStream->metadata : nullptr, prm->videoMetadata, RGY_METADATA_DEFAULT_COPY_LANG_ONLY, _T("Video"));
if (retm != RGY_ERR_NONE) {
Expand Down Expand Up @@ -2826,7 +2828,7 @@ RGY_ERR RGYOutputAvcodec::WriteNextFrameInternalOneFrame(RGYBitstream *bitstream
metadataList.push_back(std::make_unique<RGYOutputInsertMetadata>(dovi_nal, false, m_VideoOutputInfo.codec == RGY_CODEC_HEVC ? true : false));
}
} else if (m_Mux.video.doviRpuMetadataCopy) {
auto doviRpuConvPrm = (m_Mux.video.doviProfileSrc != m_Mux.video.doviProfileDst) ? std::make_unique<RGYFrameDataDOVIRpuConvertParam>(m_Mux.video.doviProfileDst) : nullptr;
auto doviRpuConvPrm = (m_Mux.video.doviProfileSrc != m_Mux.video.doviProfileDst) ? std::make_unique<RGYFrameDataDOVIRpuConvertParam>(m_Mux.video.doviProfileDst, m_Mux.video.doviRpuActiveAreaOffsets.get()) : nullptr;
auto [err_dovirpu, metadata_dovi_rpu] = getMetadata<RGYFrameDataDOVIRpu>(RGY_FRAME_DATA_DOVIRPU, bs_framedata, doviRpuConvPrm.get());
if (err_dovirpu != RGY_ERR_NONE) {
return err_dovirpu;
Expand Down
3 changes: 3 additions & 0 deletions QSVPipeline/rgy_output_avcodec.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ struct AVMuxVideo {
RGYDOVIProfile doviProfileDst; //dovi profile output
DOVIRpu *doviRpu; //dovi rpu 追加用
bool doviRpuMetadataCopy; //dovi rpuをコピー
std::unique_ptr<RGYDOVIRpuActiveAreaOffsets> doviRpuActiveAreaOffsets; //doviのactive_area_offsets
AVBSFContext *bsfc; //必要なら使用するbitstreamfilter
uint8_t *bsfcBuffer; //bitstreamfilter用のバッファ
size_t bsfcBufferLength; //bitstreamfilter用のバッファの長さ
Expand Down Expand Up @@ -401,6 +402,7 @@ struct AvcodecWriterPrm {
DOVIRpu *doviRpu; //DOVIRpu
bool doviRpuMetadataCopy; //doviのmetadataのコピー
RGYDOVIProfile doviProfile; //doviのprofile
const RGYDOVIRpuActiveAreaOffsets *doviRpuActiveAreaOffsets; //doviのactive_area_offsets
RGYTimestamp *vidTimestamp; //動画のtimestampの情報
std::string videoCodecTag; //動画タグ
std::vector<tstring> videoMetadata; //動画のmetadata
Expand Down Expand Up @@ -443,6 +445,7 @@ struct AvcodecWriterPrm {
doviRpu(nullptr),
doviRpuMetadataCopy(false),
doviProfile(RGY_DOVI_PROFILE_UNSET),
doviRpuActiveAreaOffsets(nullptr),
vidTimestamp(nullptr),
videoCodecTag(),
videoMetadata(),
Expand Down
1 change: 1 addition & 0 deletions QSVPipeline/rgy_prm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2270,6 +2270,7 @@ RGYParamCommon::RGYParamCommon() :
doviRpuMetadataCopy(false),
doviRpuFile(),
doviProfile(RGY_DOVI_PROFILE_UNSET),
doviRpuActiveAreaOffsets(),
videoCodecTag(),
videoMetadata(),
formatMetadata(),
Expand Down
1 change: 1 addition & 0 deletions QSVPipeline/rgy_prm.h
Original file line number Diff line number Diff line change
Expand Up @@ -2417,6 +2417,7 @@ struct RGYParamCommon {
bool doviRpuMetadataCopy;
tstring doviRpuFile;
RGYDOVIProfile doviProfile;
std::unique_ptr<RGYDOVIRpuActiveAreaOffsets> doviRpuActiveAreaOffsets;
std::string videoCodecTag;
std::vector<tstring> videoMetadata;
std::vector<tstring> formatMetadata;
Expand Down
6 changes: 3 additions & 3 deletions QSVPipeline/rgy_version.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@

#include "rgy_rev.h"

#define VER_FILEVERSION 0,7,73,0
#define VER_STR_FILEVERSION "7.73"
#define VER_STR_FILEVERSION_TCHAR _T("7.73")
#define VER_FILEVERSION 0,7,74,0
#define VER_STR_FILEVERSION "7.74"
#define VER_STR_FILEVERSION_TCHAR _T("7.74")

#ifdef _M_IX86
#define BUILD_ARCH_STR _T("x86")
Expand Down

0 comments on commit d651d8c

Please sign in to comment.