diff --git a/NVEnc/NVEnc_readme.txt b/NVEnc/NVEnc_readme.txt index ce606b3c..2811751d 100644 --- a/NVEnc/NVEnc_readme.txt +++ b/NVEnc/NVEnc_readme.txt @@ -221,6 +221,7 @@ NVIDIA グラフィックドライバ 545.92 - インタレ解除を指定したが、インタレ設定がされていない場合、自動的に--interlace auto相当の動作にするように。 - エンコードを遅くする大量のメッセージを抑制。 - AQの情報をH.264以外でも表示するように。 +- --vpp-nnediでbob化する際、--vpp-rffなしでrffな動画を処理するとtimestamp周りの計算がおかしくなりエラー終了する問題を修正。 2023.11.08 (7.36) [NVEncC] diff --git a/NVEncCore/NVEncCore.cpp b/NVEncCore/NVEncCore.cpp index 878648d1..ed020672 100644 --- a/NVEncCore/NVEncCore.cpp +++ b/NVEncCore/NVEncCore.cpp @@ -2479,6 +2479,7 @@ RGY_ERR NVEncCore::InitFilters(const InEncodeVideoParam *inputParam) { param->frameIn = inputFrame; param->frameOut = inputFrame; param->baseFps = m_encFps; + param->timebase = m_outputTimebase; param->bOutOverwrite = false; NVEncCtxAutoLock(cxtlock(m_dev->vidCtxLock())); auto sts = filter->init(param, m_pNVLog); diff --git a/NVEncCore/NVEncFilterNnedi.cu b/NVEncCore/NVEncFilterNnedi.cu index 6fe14a11..977f3e75 100644 --- a/NVEncCore/NVEncFilterNnedi.cu +++ b/NVEncCore/NVEncFilterNnedi.cu @@ -1801,6 +1801,10 @@ RGY_ERR NVEncFilterNnedi::run_filter(const RGYFrameInfo *pInputFrame, RGYFrameIn || pNnediParam->nnedi.field == VPP_NNEDI_FIELD_BOB_AUTO) { if ((pInputFrame->picstruct & RGY_PICSTRUCT_INTERLACED) == 0) { copyFrameAsync(ppOutputFrames[0], pInputFrame, stream); + if (pNnediParam->nnedi.isbob()) { + copyFrameAsync(ppOutputFrames[1], pInputFrame, stream); + setBobTimestamp(pInputFrame, ppOutputFrames); + } return RGY_ERR_NONE; } else if ((pInputFrame->picstruct & RGY_PICSTRUCT_FRAME_TFF) == RGY_PICSTRUCT_FRAME_TFF) { targetField = NNEDI_GEN_FIELD_BOTTOM; @@ -1882,6 +1886,22 @@ RGY_ERR NVEncFilterNnedi::run_filter(const RGYFrameInfo *pInputFrame, RGYFrameIn return sts; } +void NVEncFilterNnedi::setBobTimestamp(const RGYFrameInfo *pInputFrame, RGYFrameInfo **ppOutputFrames) { + auto prm = std::dynamic_pointer_cast(m_pParam); + + auto frameDuration = pInputFrame->duration; + if (frameDuration == 0) { + frameDuration = (decltype(frameDuration))((prm->timebase.inv() / prm->baseFps * 2).qdouble() + 0.5); + } + ppOutputFrames[1]->picstruct = RGY_PICSTRUCT_FRAME; + ppOutputFrames[0]->timestamp = pInputFrame->timestamp; + ppOutputFrames[0]->duration = (frameDuration + 1) / 2; + ppOutputFrames[1]->timestamp = ppOutputFrames[0]->timestamp + ppOutputFrames[0]->duration; + ppOutputFrames[1]->duration = frameDuration - ppOutputFrames[0]->duration; + ppOutputFrames[0]->inputFrameId = pInputFrame->inputFrameId; + ppOutputFrames[1]->inputFrameId = pInputFrame->inputFrameId; +} + void NVEncFilterNnedi::close() { m_pFrameBuf.clear(); } diff --git a/NVEncCore/NVEncFilterNnedi.h b/NVEncCore/NVEncFilterNnedi.h index 9169f62f..3185ae33 100644 --- a/NVEncCore/NVEncFilterNnedi.h +++ b/NVEncCore/NVEncFilterNnedi.h @@ -42,8 +42,9 @@ class NVEncFilterParamNnedi : public NVEncFilterParam { VppNnedi nnedi; std::pair compute_capability; HMODULE hModule; + rgy_rational timebase; - NVEncFilterParamNnedi() : nnedi(), compute_capability(std::make_pair(0, 0)), hModule(NULL) {}; + NVEncFilterParamNnedi() : nnedi(), compute_capability(std::make_pair(0, 0)), hModule(NULL), timebase() {}; virtual ~NVEncFilterParamNnedi() {}; virtual tstring print() const override; }; @@ -64,6 +65,7 @@ class NVEncFilterNnedi : public NVEncFilter { virtual void close() override; virtual RGY_ERR checkParam(const std::shared_ptr pParam); virtual RGY_ERR initParams(const std::shared_ptr pNnediParam); + void setBobTimestamp(const RGYFrameInfo *pInputFrame, RGYFrameInfo **ppOutputFrames); template void setWeight0(TypeWeight *ptrDst, const float *ptrW, const std::shared_ptr pNnediParam); diff --git a/NVEncCore/NVEncFilterYadif.cu b/NVEncCore/NVEncFilterYadif.cu index 3acc5bba..89e85378 100644 --- a/NVEncCore/NVEncFilterYadif.cu +++ b/NVEncCore/NVEncFilterYadif.cu @@ -453,15 +453,18 @@ RGY_ERR NVEncFilterYadif::run_filter(const RGYFrameInfo *pInputFrame, RGYFrameIn ppOutputFrames[0]->picstruct = RGY_PICSTRUCT_FRAME; ppOutputFrames[0]->timestamp = pSourceFrame->timestamp; ppOutputFrames[0]->inputFrameId = pSourceFrame->inputFrameId; - copyFrameAsync(ppOutputFrames[0], pSourceFrame, stream); + sts = err_to_rgy(copyFrameAsync(ppOutputFrames[0], pSourceFrame, stream)); + if (sts != RGY_ERR_NONE) { + AddMessage(RGY_LOG_ERROR, _T("failed to copy frame: %s.\n"), get_err_mes(sts)); + return sts; + } if (prmYadif->yadif.mode & VPP_YADIF_MODE_BOB) { - ppOutputFrames[1]->picstruct = RGY_PICSTRUCT_FRAME; - ppOutputFrames[0]->timestamp = pSourceFrame->timestamp; - ppOutputFrames[0]->duration = (pSourceFrame->duration + 1) / 2; - ppOutputFrames[1]->timestamp = ppOutputFrames[0]->timestamp + ppOutputFrames[0]->duration; - ppOutputFrames[1]->duration = pSourceFrame->duration - ppOutputFrames[0]->duration; - ppOutputFrames[1]->inputFrameId = pSourceFrame->inputFrameId; - copyFrameAsync(ppOutputFrames[1], pSourceFrame, stream); + sts = err_to_rgy(copyFrameAsync(ppOutputFrames[1], pSourceFrame, stream)); + if (sts != RGY_ERR_NONE) { + AddMessage(RGY_LOG_ERROR, _T("failed to copy frame: %s.\n"), get_err_mes(sts)); + return sts; + } + setBobTimestamp(iframe, ppOutputFrames); } m_nFrame++; return RGY_ERR_NONE; @@ -489,14 +492,18 @@ RGY_ERR NVEncFilterYadif::run_filter(const RGYFrameInfo *pInputFrame, RGYFrameIn AddMessage(RGY_LOG_ERROR, _T("unsupported csp %s.\n"), RGY_CSP_NAMES[pSourceFrame->csp]); return RGY_ERR_UNSUPPORTED; } - func_list.at(pSourceFrame->csp)(ppOutputFrames[0], + sts = err_to_rgy(func_list.at(pSourceFrame->csp)(ppOutputFrames[0], &m_source.get(m_nFrame-1)->frame, &m_source.get(m_nFrame+0)->frame, &m_source.get(m_nFrame+1)->frame, targetField, pSourceFrame->picstruct, stream - ); + )); + if (sts != RGY_ERR_NONE) { + AddMessage(RGY_LOG_ERROR, _T("failed to copy frame: %s.\n"), get_err_mes(sts)); + return sts; + } ppOutputFrames[0]->picstruct = RGY_PICSTRUCT_FRAME; ppOutputFrames[0]->timestamp = pSourceFrame->timestamp; @@ -508,30 +515,19 @@ RGY_ERR NVEncFilterYadif::run_filter(const RGYFrameInfo *pInputFrame, RGYFrameIn AddMessage(RGY_LOG_ERROR, _T("unsupported csp %s.\n"), RGY_CSP_NAMES[pSourceFrame->csp]); return RGY_ERR_UNSUPPORTED; } - func_list.at(pSourceFrame->csp)(ppOutputFrames[1], + sts = err_to_rgy(func_list.at(pSourceFrame->csp)(ppOutputFrames[1], &m_source.get(m_nFrame-1)->frame, &m_source.get(m_nFrame+0)->frame, &m_source.get(m_nFrame+1)->frame, targetField, pSourceFrame->picstruct, stream - ); - auto frameDuration = pSourceFrame->duration; - if (frameDuration == 0) { - if (iframe <= 1) { - frameDuration = (decltype(frameDuration))((prmYadif->timebase / prmYadif->baseFps * 2).qdouble() + 0.5); - } else if (m_nFrame + 1 >= iframe) { - frameDuration = m_source.get(m_nFrame + 0)->frame.timestamp - m_source.get(m_nFrame - 1)->frame.timestamp; - } else { - frameDuration = m_source.get(m_nFrame + 1)->frame.timestamp - m_source.get(m_nFrame + 0)->frame.timestamp; - } + )); + if (sts != RGY_ERR_NONE) { + AddMessage(RGY_LOG_ERROR, _T("failed to copy frame: %s.\n"), get_err_mes(sts)); + return sts; } - ppOutputFrames[1]->picstruct = RGY_PICSTRUCT_FRAME; - ppOutputFrames[0]->timestamp = pSourceFrame->timestamp; - ppOutputFrames[0]->duration = (frameDuration + 1) / 2; - ppOutputFrames[1]->timestamp = ppOutputFrames[0]->timestamp + ppOutputFrames[0]->duration; - ppOutputFrames[1]->duration = frameDuration - ppOutputFrames[0]->duration; - ppOutputFrames[1]->inputFrameId = pSourceFrame->inputFrameId; + setBobTimestamp(iframe, ppOutputFrames); } m_nFrame++; } else { @@ -542,6 +538,27 @@ RGY_ERR NVEncFilterYadif::run_filter(const RGYFrameInfo *pInputFrame, RGYFrameIn return sts; } +void NVEncFilterYadif::setBobTimestamp(const int iframe, RGYFrameInfo **ppOutputFrames) { + auto prm = std::dynamic_pointer_cast(m_pParam); + + auto frameDuration = m_source.get(m_nFrame + 0)->frame.duration; + if (frameDuration == 0) { + if (iframe <= 1) { + frameDuration = (decltype(frameDuration))((prm->timebase.inv() / prm->baseFps * 2).qdouble() + 0.5); + } else if (m_nFrame + 1 >= iframe) { + frameDuration = m_source.get(m_nFrame + 0)->frame.timestamp - m_source.get(m_nFrame - 1)->frame.timestamp; + } else { + frameDuration = m_source.get(m_nFrame + 1)->frame.timestamp - m_source.get(m_nFrame + 0)->frame.timestamp; + } + } + ppOutputFrames[1]->picstruct = RGY_PICSTRUCT_FRAME; + ppOutputFrames[0]->timestamp = m_source.get(m_nFrame + 0)->frame.timestamp; + ppOutputFrames[0]->duration = (frameDuration + 1) / 2; + ppOutputFrames[1]->timestamp = ppOutputFrames[0]->timestamp + ppOutputFrames[0]->duration; + ppOutputFrames[1]->duration = frameDuration - ppOutputFrames[0]->duration; + ppOutputFrames[1]->inputFrameId = m_source.get(m_nFrame + 0)->frame.inputFrameId; +} + void NVEncFilterYadif::close() { m_nFrame = 0; m_pts = 0; diff --git a/NVEncCore/NVEncFilterYadif.h b/NVEncCore/NVEncFilterYadif.h index 8787341c..27d5d127 100644 --- a/NVEncCore/NVEncFilterYadif.h +++ b/NVEncCore/NVEncFilterYadif.h @@ -77,6 +77,7 @@ class NVEncFilterYadif : public NVEncFilter { virtual RGY_ERR run_filter(const RGYFrameInfo *pInputFrame, RGYFrameInfo **ppOutputFrames, int *pOutputFrameNum, cudaStream_t stream) override; virtual void close() override; RGY_ERR check_param(shared_ptr prmYadif); + void setBobTimestamp(const int iframe, RGYFrameInfo **ppOutputFrames); int m_nFrame; int64_t m_pts;