【问题标题】:SharpDX MapSubresource is vertically flipped C#SharpDX MapSubresource 垂直翻转 C#
【发布时间】:2017-05-18 01:58:48
【问题描述】:

如何在不将其转换为位图的情况下翻转 SharpDX.Databox? 我正在使用 SharpDX 和 Media Foundation 进行屏幕录制。下面是我如何获取 Databox 的代码。

mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0,SharpDX.Direct3D11.MapMode.Read, SharpDX.Direct3D11.MapFlags.None);

但是当我通过 mediafoundation.net 中的 mapSource 时,我制作了一个垂直视频。

        IMFSample sample = null;
        IMFMediaBuffer buffer = null;

        IntPtr data = new IntPtr();
        int bufferMaxLength;
        int bufferCurrentLength;

        int hr = (int)MFExtern.MFCreateMemoryBuffer(frameSizeBytes, out buffer);

        if (Succeeded(hr)) hr = (int)buffer.Lock(out data, out bufferMaxLength, out bufferCurrentLength);
        if (Succeeded(hr))
        {

            hr = (int)MFExtern.MFCopyImage(data, videoWidth * BYTES_PER_PIXEL, mapSource.DataPointer, videoWidth * BYTES_PER_PIXEL, videoWidth * BYTES_PER_PIXEL, videoHeight);
        }
        if (Succeeded(hr)) hr = (int)buffer.Unlock();
        if (Succeeded(hr)) hr = (int)buffer.SetCurrentLength(frameSizeBytes);
        if (Succeeded(hr)) hr = (int)MFExtern.MFCreateSample(out sample);
        if (Succeeded(hr)) hr = (int)sample.AddBuffer(buffer);
        if (Succeeded(hr)) hr = (int)sample.SetSampleTime(frame.prevRecordingDuration.Ticks);//(TICKS_PER_SECOND * frames / VIDEO_FPS);
        if (Succeeded(hr)) hr = (int)sample.SetSampleDuration((frame.recordDuration-frame.prevRecordingDuration).Ticks);
        if (Succeeded(hr)) hr = (int)sinkWriter.WriteSample(streamIndex, sample);
        if (Succeeded(hr)) frames++;

        COMBase.SafeRelease(sample);
        COMBase.SafeRelease(buffer);

enter image description here

【问题讨论】:

    标签: directx ms-media-foundation sharpdx dxgi


    【解决方案1】:

    在您的代码中,MFCopyImage 的代码存在错误。根据MFCopyImage function,您必须设置 _In_ LONG lDestStride, _In_ const BYTE *pSrc, _In_ LONG lSrcStride, - lDestStride 和 lSrcStride - 是用于存储一行像素的内存宽度 - 您的计算 videoWidth * BYTES_PER_PIXEL 不正确,因为对于 Windows RGB 格式的 stride 可能比videoWidth * BYTES_PER_PIXEL 更宽。您必须通过函数MFGetStrideForBitmapInfoHeader 计算目标步幅,您可以从图像源代码中获得源步幅 - 我不知道您的代码,但对于我的项目,我使用了

    D3D11_MAPPED_SUBRESOURCE resource;
                    UINT subresource = D3D11CalcSubresource(0, 0, 0);
                    ctx->Map(mDestImage, subresource, D3D11_MAP_READ_WRITE, 0, &resource);
                    LOG_INVOKE_MF_FUNCTION(MFCopyImage,
                        aPtrData,
                        mStride,
                        (BYTE*)resource.pData,
                        resource.RowPitch,
    
    • 行间距。

    问候。

    附:目标步幅mStride 可以为负数 - 这意味着它需要从最后一行写入到第一行。可以通过下一次更改目标指针来完成 - aPtrData += (mHeight - 1)*mStride;

    【讨论】:

    • 我正在使用 c# 我猜你是 c++ 程序员。但我会尝试你的解决方案。让你知道结果谢谢。
    • 您使用MFExtern - 它只是将 MediaFoundation 的 C 函数映射到 C# 代码的包装器。尝试查找MFExtern.MFGetStrideForBitmapInfoHeader
    • 抱歉,我仍然无法正确输出。我在使用媒体基础方面不是那么专家。图片来源已经被我的帖子中的附件反转了,我只是忘记重命名链接。你可以在底部看到它。我实际上可以使用来做到这一点
    • 您好,您使用什么格式的视频?你如何计算frameSizeBytes?建议为此使用MFCalculateImageSize。我看到你的图像,它有两个失真: 1. 图像有“斜率” - 每行图像的宽度小于正确绘图所需的宽度,因此绘制一条线需要从下一条线获取一些像素 - 它是步幅错误的结果。 2. 图像有垂直翻转 - 这是不同格式的结果 - Direct3D 使用现代格式存储图像 -
    • 开始行像素存储在内存段的开头,但在系统内存中为了与旧软件兼容,它使用旧图像格式 - 开始行像素可以放在内存段的末尾,并且它需要从头到尾读取这样的内存。为了识别这种情况,需要检查Stride 值。您必须从 MFExtern.MFGetStrideForBitmapInfoHeader 计算它并检查 - 如果它是负数,那么您必须通过更改 aPtrData += (mHeight - 1)* abs(mStride) 上的指针从头到尾以反向形式从 Direct3D 内存复制
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-25
    • 2015-05-17
    • 1970-01-01
    • 2011-07-05
    • 1970-01-01
    • 2016-10-15
    相关资源
    最近更新 更多