Wpf and Spout

Home Forums Spout Developer Wpf and Spout

Viewing 15 posts - 1 through 15 (of 22 total)
  • Author
    Posts
  • #1286
    david
    Participant

    Hi guys,

    I’m working on this project and would like to implement Spout into my application. Now this is a wpf c# application and I was searching around to find an answer on how to implement it. Is this possible at the moment? Its a two-part application (user interface and graphic engine in cinder) and the part that worries is the receiver.

    If there is anything you could point me to, it would be amazing! An example or a suggestion on how to do it. Thank you!

    #1287
    leadedge
    Keymaster

    I would first look at the Cinder examples that are included in the Spout installation. A receiver example is included.

    Then look at Bruce Lane’s Spout repository :

    https://github.com/brucelane/Cinder-Spout

    #1294
    david
    Participant

    Thank you.

    Here is an update. I am sending textures from the cinder engine and the next step is to catch these textures in C# and display them on a certain canvas or a bitmap. Any guidelines? The engine will send a pointer to the receiver (via pipes) so that this receiver can pick a texture from the lower levels and read it to its buffer. The problem is how to get the content to that .net environment.

    #1295
    leadedge
    Keymaster

    It sounds to me that you need to dig fairly deep into the Spout SDK.

    But before that, I think it is worth looking at the Unity plugin developed by Ben Kuper that uses native code in C++ interfaced to a C# project. This has recently been taken on by Stefan Schlupek for ongoing development.

    https://github.com/sloopidoopi/Spout4Unity

    In essence behind all of this is a simple structure in shared memory for each sender. This contains information on the width, height, format and sharehandle of the sender’s shared DirectX texture. If your application is based on DirectX, you can access this directly through the lower levels of the Spout SDK and that is how the Unity plugin works. But if you can use an interface with C++ with an OpenGL context available it makes life much easier.

    My first thought is that if you already have a texture pointer, is it DirectX or OpenGL? If it is DirectX you probably don’t have to use pipes because the DirectX texture pointer (sharehandle for DX9) is already in shared memory and controlled access is possible using the “SpoutSenderNames” class which is independent of OpenGL.

    I am probably off course because I am not familiar with wpf. But my first thought would be what to deal with, either DirectX or OpenGL.

    #1296
    david
    Participant

    Great, thank you once more!

    #1297
    leadedge
    Keymaster

    Further to this, I was not thinking clearly enough before. If you have used the Spout SDK with Cinder and can successfully receive your texture using the Spout demo receiver, you are mostly there. Then you will have your sender’s texture information structure in shared memory already and a shared DirectX texture ready to access.

    #1343
    david
    Participant

    This. MemoryMappedFile can find the stream, but I got lost in getting the data back in other application. The default sender is working with a texture (2048 x 2048) and streams out on a window 640 x 512. The Format format is RGBA. How do I access the texture from here (or just byte-per-byte) data? What informations are stored in standard spout stream?

    #1348
    leadedge
    Keymaster

    So I assume you can access the sender’s memory mapped file. You can also do this with C++ using the SpoutSenderNames class. If you look at “SpoutSharedMemory.cpp” you will see how access to the shared memory maps is managed.

    In “SpoutSenderNames.h” look at the “SharedTextureInfo” structure. This is exactly the same as what is in shared memory.

    So if you have created a sender with Cinder and it is working OK, you can access the sender information in C++ using “spoutSenderNames::GetSenderInfo”.

    I am not sure how you will do this in your WPF application if it does not use C++, but you have two things to manage. One is the sender “named mutex” which is named using the sender name appended by “_mutex”. This controls access to the memory map and avoids concurrent access. But it is possible to ignore this for testing and just access the memory map and see what you get.

    If you can open the shared memory, you will be able to retrieve the information in the format of the “SharedTextureInfo” structure. What you are interested in is the texture pointer.

    If you are using DirectX in the WPF application you will need to create a DirectX texture using this pointer, (or share handle for DirectX 9). And that is the result you need straight away. You will then have a local DirectX texture you can use. The access is instant as soon as you create the local texture from the share handle. There is no byte-by-byte transfer needed.

    One problem might be texture format compatibility between DirectX 11 and DirectX 9. I would suggest setting the Cinder sender as DirectX9 with “SetDX9(true)” and using a DirectX 9 texture in your application.

    This is fairly low level and I hope you can follow it. If not, just get back here and I will try to better understand your application.

    #1349
    david
    Participant

    Thats right. Already got the SharedInfo data from the shared memory so the pointer and the stream resolutions are safe, as well as the description and format. Now I’ll need to figure out how to get the data to that local texture and get the first bytes of data.

    Making a sender and receiver in cinder was pretty straight forward. You did an excellent job!

    #1350
    leadedge
    Keymaster

    Is this any use :

    https://msdn.microsoft.com/en-us/library/cc656716%28v=vs.110%29.aspx

    What you will need to do is create a DirectX 9EX device and then a texture using the sharehandle and dimensions you retrieve from shared memory. The texture you create will have the data in it straight away, no need to transfer anything. If you look at “spoutDirectX.cpp” you might get some code you can use. Once you have that texture, you should be able to do something with it. If you want pixel data in CPU memory I can point to some code that does that.

    I am glad that the Cinder project worked well for you. I have tried to reduce the Spout OpenGL functions to the minimum.

    #1351
    david
    Participant

    Got the example running. So the content (the triangle) is spinning in d3dimage.
    Now here is another thing. This is the crucial part.

    IntPtr pSurface = IntPtr.Zero;
    HRESULT.Check(GetBackBufferNoRef(out pSurface)); // pSurface is NULL or a valid handle

    The unmanaged code does return a IDirect3DSurface9 handle that is rendered in the background. Spout, on the other hand, does a different thing. How can I do a similar thing with spout? I have the shared memory data, what calls do I have to make to get the content I need in a similar fashion? I was thinking of making a new dll (like the one from the example) for spout, but am pretty sure the guidelines you gave me so far lead to a more clean solution.

    #1354
    leadedge
    Keymaster

    Instead of a surface you need a shared texture. I had a look at the project and it does not have any texture creation, so you have to add that. This can get complicated quickly without some sample code, so have a look at this project which is the beginning of a DirectX example.

    https://www.dropbox.com/sh/bpsbllvlte66c17/AACZggdZEsXyRpVnY7YCAA1ma?dl=0

    This is both a receiver and a sender combined and uses Spout class functions, so it does not access shared memory directly. These files are not included with the example project folder and so it will not build as-is. But you can set up folders so that the Spout SDK files are in a “SpoutSDK” folder a level above the project folder and then it should find them. Sorry this is not yet finished but it might give you an idea of how to proceed.

    From what I can see, the “D3DContent” dll could be worked on to use the higher level Spout functions so that direct memory map access is not necessary.

    #1355
    david
    Participant

    Thank you.

    Will post an update when I get things working.

    #1683
    david
    Participant

    Hi again. Got the things working and I’m here with another proposal. This time I would like to test out the MemoryShare option. Downloaded the latest sdk and running the MemoryShare examples. Now my question is: what is the sample’s sender name / under what name can the shared data be found under MemoryMappedFile (for example under C#). I scanned the source but couldn’t find the data the samples are sharing between each other.

    Thank you!

    #1684
    leadedge
    Keymaster

    If you have things working, this is well done and a significant thing. Anyway maybe I can give some pointers.

    The memoryshare class is actually a relic of the first attempts to share image data between applications. There is only one sender/receiver pair and no sender name is involved. There is no individual memory map for the sender with information about size, texture etc. Instead a large memory map the size of the desktop is established with a fixed name and the sender and receiver communicate using this.

    To get an idea, in SpoutSDK.cpp you might look at :
    Spout::InitMemoryShare
    and :
    Spout::SendImage – skip down to the part where it says “else if(bMemoryShareInitOK)”

    Follow the calls through to the “SpoutMemoryShare” class.

    Since it has already been embedded in the Spout SDK, it should all work out if you call “SetMemoryShareMode(true)”. I am not sure, but I think this can be done even without an OpenGL context. If that is a problem the “SpoutMemoryShare” class should be useable on it’s own.

    Some time I am keen to see the result of your work.

Viewing 15 posts - 1 through 15 (of 22 total)
  • You must be logged in to reply to this topic.