0

How can I flipped the SharpDX.Databox without converting it to bitmap? I'm making a screen recording using SharpDX and Media foundation. Below is the code on how I get the Databox.

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

But when I passed the mapSource in mediafoundation.net I produced a vertical video.

        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

kripto
  • 69
  • 1
  • 10

1 Answers1

1

In your code there is a mistake in code with MFCopyImage. According MFCopyImage function you must set _In_ LONG lDestStride, _In_ const BYTE *pSrc, _In_ LONG lSrcStride, - lDestStride and lSrcStride - is width of memory for storing one line of pixels - your computing videoWidth * BYTES_PER_PIXEL is not correct, because for Windows RGB format stride can be widther than videoWidth * BYTES_PER_PIXEL. You must compute destination stride by function MFGetStrideForBitmapInfoHeader, source stride you can get from you image source code - I do not know you code, but for my project I used

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,
  • RowPitch.

Regards.

P.S. Destination stride mStride can be negative - it means that it needs write from last line to the first. It can done by the next changing of destination pointer - aPtrData += (mHeight - 1)*mStride;

Evgeny Pereguda
  • 553
  • 1
  • 4
  • 9
  • I'm using c# I guess you are c++ programmer. But I will try your solution. and Let you know the result Thanks. – kripto May 18 '17 at 02:25
  • You use `MFExtern` - it is just wrapper for mapping of C function of MediaFoundation on C# code. Try find `MFExtern.MFGetStrideForBitmapInfoHeader`. – Evgeny Pereguda May 18 '17 at 02:30
  • Sorry but I can't still make my output right. I'm not so expert in using Media foundation. The image source is already inverted by the way there is an attachment on my post I just forgot to rename the link. You can see it at the bottom. I can actually make that right using – kripto May 18 '17 at 05:27
  • Hi, what format of video you use? How you compute `frameSizeBytes`? It is recommended use [MFCalculateImageSize](https://msdn.microsoft.com/en-us/library/windows/desktop/bb970318(v=vs.85).aspx) for such purpose. I see your image and it has two distortions: 1. image has 'slope' - width of each line of image less then it needs for the correct drawing, as a result for drawing one line it takes some pixels from the next - it is a result of the wrong stride. 2. image has vertical flipping - it is result of different formats - Direct3D use moder format for storing image - – Evgeny Pereguda May 18 '17 at 07:09
  • begin line of pixels is stored at the begin of memory segment, but in system memory for compatibleness with old software it uses old image format - begin line of pixels can be placed at the end of memory segment and it needs read such memory from the end to the begin. For recognizing of such situation it needs check `Stride` value. You must compute it from `MFExtern.MFGetStrideForBitmapInfoHeader` and check - if it is negative then you must copy from Direct3D memory in revers form from end to start by changing pointer on `aPtrData += (mHeight - 1)* abs(mStride)` – Evgeny Pereguda May 18 '17 at 07:14
  • framesizebytes = BYTES_PER_PIXEL * videoWidth * videoHeight; BYTESPERPIXEL is 4 when I debug. I'm not familiar with copy memory and rewrite the memory from end to start. So you mean I have to loop on this? – kripto May 18 '17 at 07:38