Skip to content

Commit

Permalink
hwデコードの対応についてのチェックを全デバイスに対して行うように。
Browse files Browse the repository at this point in the history
  • Loading branch information
rigaya committed Feb 18, 2025
1 parent 54f0b54 commit 459d9d0
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 62 deletions.
3 changes: 3 additions & 0 deletions NVEnc/NVEnc_readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ NVIDIA グラフィックドライバ 551.23
今後の更新で設定ファイルの互換性がなくなるかもしれません。

【メモ】
2025.02.18 (8.00 beta2)
- GPUの自動選択処理をさらに改良。

2025.02.15 (8.00 beta1)
- NVENC SDK 13.0に対応。
使用には、ドライバ570.00以降が必要。
Expand Down
79 changes: 38 additions & 41 deletions NVEncCore/NVEncCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,17 @@ RGY_ERR NVEncCore::CheckGPUListByEncoder(std::vector<std::unique_ptr<NVGPUInfo>>
gpu = gpuList.erase(gpu);
continue;
}
// デコードのチェック
if (m_pFileReader->getInputCodec() != RGY_CODEC_UNKNOWN) {
if (RGYInputAvcodec *pReader = dynamic_cast<RGYInputAvcodec *>(m_pFileReader.get()); pReader) {
if (pReader->GetHWDecDeviceID().size() > 0 && !pReader->GetHWDecDeviceID().count((*gpu)->id())) {
message += strsprintf(_T("GPU #%d (%s) does not support required hw decoding.\n"), (*gpu)->id(), (*gpu)->name().c_str());
gpu = gpuList.erase(gpu);
continue;
}
}
}

if (inputParam->common.metric.enabled()) {
//デコードのほうもチェックしてあげないといけない
const auto& cuvid_csp = (*gpu)->cuvid_csp();
Expand Down Expand Up @@ -4020,31 +4031,6 @@ RGY_ERR NVEncCore::Init(InEncodeVideoParam *inputParam) {
devUsageLock = m_deviceUsage->lock(); // ロックは親プロセス側でとる
}

//リスト中のGPUのうち、まずは指定されたHWエンコードが可能なもののみを選択
if ((sts = CheckGPUListByEncoder(gpuList, inputParam)) != RGY_ERR_NONE) {
PrintMes(RGY_LOG_ERROR, _T("Unknown erro occurred during checking GPU.\n"));
return sts;
}
if (0 == gpuList.size()) {
PrintMes(RGY_LOG_ERROR, FOR_AUO
? _T("指定されたコーデック/プロファイルをエンコード可能なGPUがみつかりまえせんでした。\n")
: _T("No suitable GPU found for codec / profile specified.\n"));
return err_to_rgy(NV_ENC_ERR_NO_ENCODE_DEVICE);
}
PrintMes(RGY_LOG_DEBUG, _T("CheckGPUListByEncoder: Success.\n"));

//使用するGPUの優先順位を決定
if ((sts = GPUAutoSelect(gpuList, inputParam, devUsageLock.get())) != RGY_ERR_NONE) {
PrintMes(RGY_LOG_ERROR, FOR_AUO ? _T("GPUの自動選択に失敗しました。\n") : _T("Failed to select gpu.\n"));
return sts;
}
PrintMes(RGY_LOG_DEBUG, _T("GPUAutoSelect: Success.\n"));

if ((sts = CheckDynamicRCParams(inputParam->dynamicRC)) != RGY_ERR_NONE) {
PrintMes(RGY_LOG_DEBUG, _T("Error in dynamic rate control params.\n"));
return sts;
}

if ((sts = input_ret.get()) < RGY_ERR_NONE) return sts;
PrintMes(RGY_LOG_DEBUG, _T("InitInput: Success.\n"));

Expand Down Expand Up @@ -4093,23 +4079,34 @@ RGY_ERR NVEncCore::Init(InEncodeVideoParam *inputParam) {
}
m_rgbAsYUV444 = RGY_CSP_CHROMA_FORMAT[inputParam->outputCsp] == RGY_CHROMAFMT_RGB || RGY_CSP_CHROMA_FORMAT[inputParam->outputCsp] == RGY_CHROMAFMT_RGB_PACKED;

//リスト中のGPUのうち、まずは指定されたHWエンコードが可能なもののみを選択
if ((sts = CheckGPUListByEncoder(gpuList, inputParam)) != RGY_ERR_NONE) {
PrintMes(RGY_LOG_ERROR, _T("Unknown erro occurred during checking GPU.\n"));
return sts;
}
if (0 == gpuList.size()) {
PrintMes(RGY_LOG_ERROR, FOR_AUO
? _T("指定されたコーデック/プロファイルをエンコード可能なGPUがみつかりまえせんでした。\n")
: _T("No suitable GPU found for codec / profile specified.\n"));
return err_to_rgy(NV_ENC_ERR_NO_ENCODE_DEVICE);
}
PrintMes(RGY_LOG_DEBUG, _T("CheckGPUListByEncoder: Success.\n"));

//使用するGPUの優先順位を決定
if ((sts = GPUAutoSelect(gpuList, inputParam, devUsageLock.get())) != RGY_ERR_NONE) {
PrintMes(RGY_LOG_ERROR, FOR_AUO ? _T("GPUの自動選択に失敗しました。\n") : _T("Failed to select gpu.\n"));
return sts;
}
PrintMes(RGY_LOG_DEBUG, _T("GPUAutoSelect: Success.\n"));

if ((sts = CheckDynamicRCParams(inputParam->dynamicRC)) != RGY_ERR_NONE) {
PrintMes(RGY_LOG_DEBUG, _T("Error in dynamic rate control params.\n"));
return sts;
}

if (gpuList.size() > 1 && m_nDeviceId < 0) {
RGYInputAvcodec *pReader = dynamic_cast<RGYInputAvcodec *>(m_pFileReader.get());
if (pReader != nullptr) {
m_nDeviceId = pReader->GetHWDecDeviceID();
if (m_nDeviceId >= 0) {
const auto gpu = std::find_if(gpuList.begin(), gpuList.end(), [device_id = m_nDeviceId](const std::unique_ptr<NVGPUInfo> & gpuinfo) {
return gpuinfo->id() == device_id;
});
PrintMes(RGY_LOG_DEBUG, _T("device #%d (%s) selected by reader.\n"), (*gpu)->id(), (*gpu)->name().c_str());
} else {
PrintMes(RGY_LOG_DEBUG, _T("reader has not selected device.\n"));
}
}
if (m_nDeviceId < 0) {
m_nDeviceId = gpuList.front()->id();
PrintMes(RGY_LOG_DEBUG, _T("device #%d (%s) selected.\n"), gpuList.front()->id(), gpuList.front()->name().c_str());
}
m_nDeviceId = gpuList.front()->id();
PrintMes(RGY_LOG_DEBUG, _T("device #%d (%s) selected.\n"), gpuList.front()->id(), gpuList.front()->name().c_str());
}
if (m_deviceUsage) {
const int devID = gpuList.front()->id();
Expand Down
26 changes: 11 additions & 15 deletions NVEncCore/rgy_input_avcodec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ AVDemuxVideo::AVDemuxVideo() :
decRFFStatus(0),
pParserCtx(nullptr),
pCodecCtxParser(nullptr),
HWDecodeDeviceId(0),
HWDecodeDeviceId(),
hevcbsf(RGYHEVCBsf::INTERNAL),
bUseHEVCmp42AnnexB(false),
hevcNaluLengthSize(0),
Expand Down Expand Up @@ -459,7 +459,7 @@ RGY_ERR RGYInputAvcodec::initVideoParser() {
char_to_tstring(avcodec_get_name(m_Demux.video.stream->codecpar->codec_id)).c_str(),
m_Demux.video.pCodecCtxParser->time_base.num, m_Demux.video.pCodecCtxParser->time_base.den,
m_Demux.video.pCodecCtxParser->pkt_timebase.num, m_Demux.video.pCodecCtxParser->pkt_timebase.den);
} else if (m_Demux.video.HWDecodeDeviceId >= 0) {
} else if (m_Demux.video.HWDecodeDeviceId.size() >= 0) {
AddMessage(RGY_LOG_ERROR, _T("failed to init parser for %s.\n"), char_to_tstring(avcodec_get_name(m_Demux.video.stream->codecpar->codec_id)).c_str());
return RGY_ERR_NULL_PTR;
}
Expand Down Expand Up @@ -1913,7 +1913,7 @@ RGY_ERR RGYInputAvcodec::Init(const TCHAR *strFileName, VideoInfo *inputInfo, co
m_inputVideoInfo.type = RGY_INPUT_FMT_AVSW;
}
#endif
m_Demux.video.HWDecodeDeviceId = -1;
m_Demux.video.HWDecodeDeviceId.clear();
if (input_prm->tcfileIn.length() > 0) {
if (input_prm->seekSec > 0.0f) {
AddMessage(RGY_LOG_ERROR, _T("--seek not supported with --tcfile-in.\n"));
Expand All @@ -1939,11 +1939,7 @@ RGY_ERR RGYInputAvcodec::Init(const TCHAR *strFileName, VideoInfo *inputInfo, co
m_inputVideoInfo.codec = checkHWDecoderAvailable(
m_Demux.video.stream->codecpar->codec_id, (AVPixelFormat)m_Demux.video.stream->codecpar->format, &devCodecCsp.second);
if (m_inputVideoInfo.codec != RGY_CODEC_UNKNOWN) {
m_Demux.video.HWDecodeDeviceId = devCodecCsp.first;
break;
}
if (m_inputVideoInfo.type != RGY_INPUT_FMT_AVHW) {
break; //RGY_INPUT_FMT_AVANYのときは、HWデコードできなくても優先度の高いGPUを使用する
m_Demux.video.HWDecodeDeviceId.insert(devCodecCsp.first);
}
}
if (m_inputVideoInfo.codec == RGY_CODEC_UNKNOWN
Expand All @@ -1964,8 +1960,8 @@ RGY_ERR RGYInputAvcodec::Init(const TCHAR *strFileName, VideoInfo *inputInfo, co
if (m_inputVideoInfo.codec == RGY_CODEC_UNKNOWN) { //swデコードの場合
avswDecoder = input_prm->avswDecoder;
}
m_readerName = (m_Demux.video.HWDecodeDeviceId >= 0) ? _T("av" DECODER_NAME) : _T("avsw");
m_inputVideoInfo.type = (m_Demux.video.HWDecodeDeviceId >= 0) ? RGY_INPUT_FMT_AVHW : RGY_INPUT_FMT_AVSW;
m_readerName = (m_Demux.video.HWDecodeDeviceId.size() > 0) ? _T("av" DECODER_NAME) : _T("avsw");
m_inputVideoInfo.type = (m_Demux.video.HWDecodeDeviceId.size() > 0) ? RGY_INPUT_FMT_AVHW : RGY_INPUT_FMT_AVSW;
//念のため初期化
m_trimParam.list.clear();
m_trimParam.offset = 0;
Expand All @@ -1979,7 +1975,7 @@ RGY_ERR RGYInputAvcodec::Init(const TCHAR *strFileName, VideoInfo *inputInfo, co
return sts;
}
//HWデコードする場合には、ヘッダーが必要
} else if (m_Demux.video.HWDecodeDeviceId >= 0
} else if (m_Demux.video.HWDecodeDeviceId.size() > 0
&& (m_inputVideoInfo.codec != RGY_CODEC_VP8 && m_inputVideoInfo.codec != RGY_CODEC_VP9)
&& m_Demux.video.stream->codecpar->extradata == nullptr
&& m_Demux.video.stream->codecpar->extradata_size == 0) {
Expand Down Expand Up @@ -2028,7 +2024,7 @@ RGY_ERR RGYInputAvcodec::Init(const TCHAR *strFileName, VideoInfo *inputInfo, co
}
}
m_inputVideoInfo.codec = RGY_CODEC_UNKNOWN; //hwデコードをオフにする
m_Demux.video.HWDecodeDeviceId = -1;
m_Demux.video.HWDecodeDeviceId.clear();
}
//close bitstreamfilter
if (m_Demux.video.bsfcCtx) {
Expand Down Expand Up @@ -2218,7 +2214,7 @@ RGY_ERR RGYInputAvcodec::Init(const TCHAR *strFileName, VideoInfo *inputInfo, co
const auto aspectRatio = m_Demux.video.stream->codecpar->sample_aspect_ratio;
const bool bAspectRatioUnknown = aspectRatio.num * aspectRatio.den <= 0;

if (!(m_Demux.video.HWDecodeDeviceId >= 0)) {
if (!(m_Demux.video.HWDecodeDeviceId.size() > 0)) {
if (avswDecoder.length() != 0) {
// swデコーダの指定がある場合はまずはそれを使用する
if (nullptr == (m_Demux.video.codecDecode = avcodec_find_decoder_by_name(tchar_to_string(avswDecoder).c_str()))) {
Expand Down Expand Up @@ -2362,7 +2358,7 @@ RGY_ERR RGYInputAvcodec::Init(const TCHAR *strFileName, VideoInfo *inputInfo, co
m_inputVideoInfo.vui.colorrange = (CspColorRange)m_Demux.video.stream->codecpar->color_range;
m_inputVideoInfo.vui.descriptpresent = 1;

if (m_Demux.video.HWDecodeDeviceId >= 0) {
if (m_Demux.video.HWDecodeDeviceId.size() > 0) {
tstring mes = strsprintf(_T("av" DECODER_NAME ": %s, %dx%d, %d/%d fps"),
CodecToStr(m_inputVideoInfo.codec).c_str(),
m_inputVideoInfo.srcWidth, m_inputVideoInfo.srcHeight, m_inputVideoInfo.fpsN, m_inputVideoInfo.fpsD);
Expand Down Expand Up @@ -3422,7 +3418,7 @@ RGYDOVIProfile RGYInputAvcodec::getInputDOVIProfile() {
return getStreamDOVIProfile(m_Demux.video.stream);
}

int RGYInputAvcodec::GetHWDecDeviceID() {
const std::set<int>& RGYInputAvcodec::GetHWDecDeviceID() const {
return m_Demux.video.HWDecodeDeviceId;
}

Expand Down
7 changes: 4 additions & 3 deletions NVEncCore/rgy_input_avcodec.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "rgy_bitstream.h"
#include "convert_csp.h"
#include <deque>
#include <set>
#include <atomic>
#include <thread>
#include <cassert>
Expand Down Expand Up @@ -752,7 +753,7 @@ struct AVDemuxVideo {
AVCodecParserContext *pParserCtx; //動画ストリームのParser
AVCodecContext *pCodecCtxParser; //動画ストリームのParser用

int HWDecodeDeviceId; //HWデコードする場合に選択したデバイス
std::set<int> HWDecodeDeviceId; //HWデコードする場合に選択したデバイス

RGYHEVCBsf hevcbsf; //HEVCのbsfの選択
bool bUseHEVCmp42AnnexB;
Expand Down Expand Up @@ -915,8 +916,8 @@ class RGYInputAvcodec : public RGYInput
//動画の最初のフレームのptsを取得する
int64_t GetVideoFirstKeyPts();

//入力に使用する予定のdeviceIDを取得する
int GetHWDecDeviceID();
//入力に使用可能なdeviceIDを取得する
const std::set<int>& GetHWDecDeviceID() const;

//入力スレッドのハンドルを取得する
HANDLE getThreadHandleInput();
Expand Down
6 changes: 3 additions & 3 deletions NVEncCore/rgy_version.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@
#ifndef __RGY_CONFIG_H__
#define __RGY_CONFIG_H__

#define VER_FILEVERSION 0,8,0,1
#define VER_STR_FILEVERSION "8.00b1"
#define VER_STR_FILEVERSION_TCHAR _T("8.00b1")
#define VER_FILEVERSION 0,8,0,2
#define VER_STR_FILEVERSION "8.00b2"
#define VER_STR_FILEVERSION_TCHAR _T("8.00b2")

#ifdef _M_IX86
#define BUILD_ARCH_STR _T("x86")
Expand Down
4 changes: 4 additions & 0 deletions ReleaseNotes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# NVEnc Release Notes

## 8.00beta2

- Improve auto gpu selection for multi (NVIDIA) GPU environments.

## 8.00beta1

- Add support for NVENC SDK 13.0.
Expand Down

0 comments on commit 459d9d0

Please sign in to comment.