diff --git a/NVEnc/NVEnc_readme.txt b/NVEnc/NVEnc_readme.txt index 6f3dea3a..89c0a288 100644 --- a/NVEnc/NVEnc_readme.txt +++ b/NVEnc/NVEnc_readme.txt @@ -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以降が必要。 diff --git a/NVEncCore/NVEncCore.cpp b/NVEncCore/NVEncCore.cpp index 211c1d53..f2b3f809 100644 --- a/NVEncCore/NVEncCore.cpp +++ b/NVEncCore/NVEncCore.cpp @@ -894,6 +894,17 @@ RGY_ERR NVEncCore::CheckGPUListByEncoder(std::vector> gpu = gpuList.erase(gpu); continue; } + // デコードのチェック + if (m_pFileReader->getInputCodec() != RGY_CODEC_UNKNOWN) { + if (RGYInputAvcodec *pReader = dynamic_cast(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(); @@ -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")); @@ -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(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 & 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(); diff --git a/NVEncCore/rgy_input_avcodec.cpp b/NVEncCore/rgy_input_avcodec.cpp index c39ce9ba..56256b6e 100644 --- a/NVEncCore/rgy_input_avcodec.cpp +++ b/NVEncCore/rgy_input_avcodec.cpp @@ -131,7 +131,7 @@ AVDemuxVideo::AVDemuxVideo() : decRFFStatus(0), pParserCtx(nullptr), pCodecCtxParser(nullptr), - HWDecodeDeviceId(0), + HWDecodeDeviceId(), hevcbsf(RGYHEVCBsf::INTERNAL), bUseHEVCmp42AnnexB(false), hevcNaluLengthSize(0), @@ -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; } @@ -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")); @@ -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 @@ -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; @@ -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) { @@ -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) { @@ -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()))) { @@ -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); @@ -3422,7 +3418,7 @@ RGYDOVIProfile RGYInputAvcodec::getInputDOVIProfile() { return getStreamDOVIProfile(m_Demux.video.stream); } -int RGYInputAvcodec::GetHWDecDeviceID() { +const std::set& RGYInputAvcodec::GetHWDecDeviceID() const { return m_Demux.video.HWDecodeDeviceId; } diff --git a/NVEncCore/rgy_input_avcodec.h b/NVEncCore/rgy_input_avcodec.h index dd219f32..124dda46 100644 --- a/NVEncCore/rgy_input_avcodec.h +++ b/NVEncCore/rgy_input_avcodec.h @@ -39,6 +39,7 @@ #include "rgy_bitstream.h" #include "convert_csp.h" #include +#include #include #include #include @@ -752,7 +753,7 @@ struct AVDemuxVideo { AVCodecParserContext *pParserCtx; //動画ストリームのParser AVCodecContext *pCodecCtxParser; //動画ストリームのParser用 - int HWDecodeDeviceId; //HWデコードする場合に選択したデバイス + std::set HWDecodeDeviceId; //HWデコードする場合に選択したデバイス RGYHEVCBsf hevcbsf; //HEVCのbsfの選択 bool bUseHEVCmp42AnnexB; @@ -915,8 +916,8 @@ class RGYInputAvcodec : public RGYInput //動画の最初のフレームのptsを取得する int64_t GetVideoFirstKeyPts(); - //入力に使用する予定のdeviceIDを取得する - int GetHWDecDeviceID(); + //入力に使用可能なdeviceIDを取得する + const std::set& GetHWDecDeviceID() const; //入力スレッドのハンドルを取得する HANDLE getThreadHandleInput(); diff --git a/NVEncCore/rgy_version.h b/NVEncCore/rgy_version.h index 53c61a17..93f2a93a 100644 --- a/NVEncCore/rgy_version.h +++ b/NVEncCore/rgy_version.h @@ -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") diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 0f790e9c..e817a6b5 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -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.