SHA256
Optimize Frame Readback and Encoding Pipeline
This commit is contained in:
3 files changed
+58
-111
No files matched your search
@@ -974,29 +974,22 @@ namespace ADOFAIRenderer.Util.FFmpeg
|
||||
/// Encodes a frame from IntPtr (native pointer).
|
||||
/// Can be used from external native plugins or custom capture sources.
|
||||
/// </summary>
|
||||
public void SendDataFromNativeBuffer(IntPtr pointer, int length)
|
||||
public void SendDataFromNativeBuffer(IntPtr pointer, int length, bool isColorConverted)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_disposed || !_isInitialized) return;
|
||||
var preConvertedSize = _settings.Width * _settings.Height * 3 / 2;
|
||||
|
||||
if (!_loggedConversionMode)
|
||||
{
|
||||
_loggedConversionMode = true;
|
||||
Melon<RenderMod>.Logger.Msg(length == preConvertedSize
|
||||
? "[Encoder] High-speed GPU color conversion enabled (NV12/YUV420P Direct Write, bypassing sws_scale)"
|
||||
Melon<RenderMod>.Logger.Msg(isColorConverted
|
||||
? "[Encoder] GPU color conversion enabled (NV12/YUV420P Direct Write, bypassing sws_scale)"
|
||||
: "[Encoder] CPU color conversion fallback enabled (RGBA Input, using sws_scale)");
|
||||
}
|
||||
|
||||
if (length == preConvertedSize)
|
||||
{
|
||||
WritePreConvertedFrame((byte*)pointer.ToPointer());
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteFrameFromBuffer((byte*)pointer.ToPointer());
|
||||
}
|
||||
if (isColorConverted) WritePreConvertedFrame((byte*)pointer.ToPointer());
|
||||
else WriteFrameFromBuffer((byte*)pointer.ToPointer());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1004,31 +997,23 @@ namespace ADOFAIRenderer.Util.FFmpeg
|
||||
/// Encodes a frame from a managed byte[].
|
||||
/// Pins the array using fixed keyword to prevent GC from moving it before passing the pointer.
|
||||
/// </summary>
|
||||
public void SendDataFromBuffer(byte[] buffer, int length)
|
||||
public void SendDataFromBuffer(byte[] buffer, int length, bool isColorConverted)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_disposed || !_isInitialized) return;
|
||||
fixed (byte* pBuffer = buffer)
|
||||
{
|
||||
var preConvertedSize = _settings.Width * _settings.Height * 3 / 2;
|
||||
|
||||
if (!_loggedConversionMode)
|
||||
{
|
||||
_loggedConversionMode = true;
|
||||
Melon<RenderMod>.Logger.Msg(length == preConvertedSize
|
||||
Melon<RenderMod>.Logger.Msg(isColorConverted
|
||||
? "[Encoder] High-speed GPU color conversion enabled (NV12/YUV420P Direct Write, bypassing sws_scale)"
|
||||
: "[Encoder] CPU color conversion fallback enabled (RGBA Input, using sws_scale)");
|
||||
}
|
||||
|
||||
if (length == preConvertedSize)
|
||||
{
|
||||
WritePreConvertedFrame(pBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteFrameFromBuffer(pBuffer);
|
||||
}
|
||||
if (isColorConverted) WritePreConvertedFrame(pBuffer);
|
||||
else WriteFrameFromBuffer(pBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1145,33 +1130,7 @@ namespace ADOFAIRenderer.Util.FFmpeg
|
||||
throw new NotSupportedException($"This pixel format ({_dstPixFmt}) does not support direct copying of pre-converted buffers.");
|
||||
}
|
||||
|
||||
// QSV acceleration handling or encoder send
|
||||
if (_isQsvEncoder)
|
||||
{
|
||||
ffmpeg.av_frame_unref(_pHwFrame);
|
||||
try
|
||||
{
|
||||
var ret = ffmpeg.av_hwframe_get_buffer(_pCodecContext->hw_frames_ctx, _pHwFrame, 0);
|
||||
if (ret < 0)
|
||||
throw new Exception($"Failed to allocate QSV hardware frame buffer — {GetFFmpegErrorString(ret)} (Code: {ret})");
|
||||
|
||||
ret = ffmpeg.av_hwframe_transfer_data(_pHwFrame, _pDstFrame, 0);
|
||||
if (ret < 0)
|
||||
throw new Exception($"Failed to upload QSV frame — {GetFFmpegErrorString(ret)} (Code: {ret})");
|
||||
|
||||
_pHwFrame->pts = _frameIndex++;
|
||||
SendFrameAndWritePackets(_pHwFrame);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ffmpeg.av_frame_unref(_pHwFrame);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_pDstFrame->pts = _frameIndex++;
|
||||
SendFrameAndWritePackets(_pDstFrame);
|
||||
}
|
||||
SubmitDstFrame();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1209,6 +1168,11 @@ namespace ADOFAIRenderer.Util.FFmpeg
|
||||
_pDstFrame->data, _pDstFrame->linesize
|
||||
);
|
||||
|
||||
SubmitDstFrame();
|
||||
}
|
||||
|
||||
private void SubmitDstFrame()
|
||||
{
|
||||
if (_isQsvEncoder)
|
||||
{
|
||||
// ── QSV hw_frames_ctx mode: System memory → GPU surface upload ──
|
||||
|
||||
Reference in new issue
Block a user