diff --git a/TIASshot.Tests/ColorCorrectorTests.cs b/TIASshot.Tests/ColorCorrectorTests.cs index 8642ef9..c57822e 100644 --- a/TIASshot.Tests/ColorCorrectorTests.cs +++ b/TIASshot.Tests/ColorCorrectorTests.cs @@ -542,6 +542,56 @@ } /// + /// ExtendMat の戻り値のバッファを共有する保持用ヘッダを作り,そのバッファの + /// ネイティブ参照カウント(cv::UMatData::refcount)を読めるようにするテスト用サブクラス. + /// 挙動は変えない.オフセットは x64 / OpenCV 4.x の cv::Mat・cv::UMatData のレイアウト + /// (cv::Mat::u = +56,UMatData::refcount = +20)に依存するため,捕捉直後の値で前提を検証する. + /// + private class ExtendMatRefCountCorrector : ColorCorrector { + public Mat Holder; + public System.IntPtr UMatData; + public int RefCountAtCapture; + + public ExtendMatRefCountCorrector() : base(null, null, new int[] { 4 }) { } + + internal override Mat ExtendMat(Mat src, int channels) { + var result = base.ExtendMat(src, channels); + Holder = new Mat(result, new Rect(0, 0, result.Cols, result.Rows)); + UMatData = System.Runtime.InteropServices.Marshal.ReadIntPtr(result.CvPtr, 56); + RefCountAtCapture = ReadRefCount(); + return result; + } + + public int ReadRefCount() { + return System.Runtime.InteropServices.Marshal.ReadInt32(UMatData, 20); + } + } + + /// + /// ConvertImage: 行列積の一時 MatExpr を解放し,中間拡張 Mat のネイティブバッファへの参照を + /// 呼び出し完了時に残さないこと(MatExpr を GC ファイナライザ任せにすると,拡張 Mat の + /// 大きなバッファが GC まで解放されずピークメモリが膨らむ) + /// + [Test] + public void ConvertImage_通常入力_行列積のMatExprが拡張Matのバッファ参照を残さない() { + // Arrange + using (var src = new Mat(2, 2, MatType.CV_8UC3, new Scalar(50, 100, 150))) + using (var conv = CreateIdentityLikeConvMat()) { + var corrector = new ExtendMatRefCountCorrector(); + + // Act + using (var dst = corrector.ConvertImage(src, conv)) + using (corrector.Holder) { + // Assert + Assert.That(corrector.RefCountAtCapture, Is.EqualTo(2), + "捕捉直後は拡張 Mat と保持用ヘッダの 2 参照(オフセット前提の確認)"); + Assert.That(corrector.ReadRefCount(), Is.EqualTo(1), + "ConvertImage 完了後は保持用ヘッダの参照のみが残る(MatExpr が参照を保持しない)"); + } + } + } + + /// /// CalcConvertMatrix: ExtendMat のパススルー入力(3 列相当でない Mat は src をそのまま返す)でも /// 入力 src を解放しないこと(無条件 Dispose による入力破壊の回帰防止) ///