Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can you make a Windows tutorial? #6

Open
forestcolat opened this issue Jul 15, 2020 · 6 comments
Open

Can you make a Windows tutorial? #6

forestcolat opened this issue Jul 15, 2020 · 6 comments

Comments

@forestcolat
Copy link

I've trying for around 3 weeks, but "transfer" the tutorial from Xcode to Visual studio is a little more complex than a imagined. Is this even posible? or Am I doing something that is just avaluable for Mac?

@madelinegannon
Copy link
Owner

Hi @forestcolat — I commented in #5 which I think will get you unstuck. Respond with any issues in that thread.

I'll leave this issue open in case anyone from the community wants to post a step-by-step windows tutorial (I'm developing on linux and mac at the moment).

@ChapC
Copy link

ChapC commented Oct 16, 2020

Hey @forestcolat, not sure if you're still working on this, but for anyone else who's interested I got mediapipe working on Windows 10 after a couple days of messing around. Here's what I did:

1. Follow steps 1-8 of the official Windows installation guide
Not sure if it's that important, but it took me a while to track down the full version numbers required for step 6. I'm not very familiar with the VS toolchain so if there's an easier way to get this info please let me know.

You can find BAZEL_VC_FULL_VERSION by opening the VS Developer Command Prompt and running cl with no arguments (my version was 19.27.29111).
BAZEL_WINSDK_FULL_VERSION can be located by opening the Visual Studio installer, modifying your installation (for me Visual Studio Community 2019 -> More -> Modify) and looking for the version number of Windows 10 SDK in the "Installation Details" section.
image
Mine was version 10.0.18362.0.

2. Patch or rollback
As mentioned in this issue, the latest version of mediapipe won't build properly on Windows. You have two options: patch a few of the framework files or rollback to version 0.7.5 (run git checkout v0.7.5 in the mediapipe folder).
I opted to patch, applying these changes from the above issue:

mediapipe/framework/deps/file_helpers.cc - line 19

17: #ifdef _WIN32
18: #include <Windows.h>
19: #include <direct.h>  //<--- Add this
20: #else
21: #include <dirent.h>
22: #endif  // _WIN32

mediapipe/framework/legacy_calculator_support.h - lines 69, 83

64: #endif  // !__APPLE__
65:     static thread_local C* current_;  // NOLINT
66:   };
67: };
68: 
69: #if !defined(_MSC_VER)    //<--- Add this
70: // We only declare this variable for two specializations of the template because
~~blah~blah~blah~~
81: thread_local CalculatorContract*
82:     LegacyCalculatorSupport::Scoped<CalculatorContract>::current_;
83: #endif   //<--- Add this
84: }  // namespace mediapipe
85: 
86: #endif  // MEDIAPIPE_FRAMEWORK_LEGACY_CALCULATOR_SUPPORT_H_

mediapipe/framework/packet.h - lines 442-444, 451

438: // Registers a message type. T must be a non-cv-qualified concrete proto type.
439: template <typename T>
440: struct MessageRegistrationImpl {
441:   static NoDestructor<mediapipe::RegistrationToken> registration;
442:   static std::unique_ptr<Holder<T>> CreateMessageHolder() {    //<--- Add these...
443:       return absl::make_unique<Holder<T>>(new T);    //<--- ...three lines...
444:   }   //<--- ...in here
445: };
446: 
447: // Static members of template classes can be defined in the header.
448: template <typename T>
449: NoDestructor<mediapipe::RegistrationToken>
450:     MessageRegistrationImpl<T>::registration(MessageHolderRegistry::Register(
451:         T{}.GetTypeName(), MessageRegistrationImpl<T>::CreateMessageHolder));   //<--- Modify line to this
452: 
453: // For non-Message payloads, this does nothing.
454: template <typename T, typename Enable = void>
455: struct HolderSupport {
456:   static void EnsureStaticInit() {}
457: };

3. Run the Hello World example per step 9
Ensure you add the --action_env PYTHON_BIN_PATH="C://path//to//python.exe" argument to the build command like the guide says. My Python install is in the default location at %localappdata%/Programs/Python, so for me that argument looks like --action_env PYTHON_BIN_PATH="C:\\Users\\chap\\AppData\\Local\\Programs\\Python\\Python38-32\\python.exe".

If the build completes successfully and you see Hello World! printed to the console, you should be ready to move on to...

4. Windows-ifying Madeline's class
We're almost there! The mediapipe environment is all set up, now we just need to make a few changes to the PassThrough calculator. At the moment it's using a few unix-only headers for socket communication, like sys/socket.h. On Windows, sockets are available to us via the Windows Sockets 2 (winsock) library. Luckily the interface is almost identical.

First, remove the unix headers from the top of the file and add the winsock headers. Your second set of includes should look like this

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
//Winsock Library
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")

Next, the setup_udp method needs a few changes.
Add in this call to WSAStartup to initialize winsock at the top of setup_udp

// Initialize winsock
WSADATA socketsImplData;
if (int result = WSAStartup(MAKEWORD(2, 2), &socketsImplData) != 0) {
    fprintf(stderr, "Failed to start winsock - Startup error code %d\n", result);
    exit(EXIT_FAILURE);
}

and change the socket creation call to specify that we want a UDP socket (IPPROTO_UDP) and to give us an error code if things go wrong

// Creating socket (it's still basically a file descriptor)
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != 0 ) {
    fprintf(stderr, "socket creation failed - error code %d\n", WSAGetLastError());
    exit(EXIT_FAILURE);
}

Last thing to change in the setup_udp method is to change the socket's send address from INADDR_ANY to 127.0.0.1. Windows supports INADDR_ANY too, but doesn't like it when you use it here for some reason. 🤷

  // Filling server information
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(PORT);
  servaddr.sin_addr.s_addr = inet_addr("127.0.0.1")

I'm not 100% sure on what you should put here if you want to send data to another device. I would have thought INADDR_ANY, but that gives me error 10049 - Cannot assign requested address. Any help appreciated.

Finally, to properly shut down the socket we'll want to change the calculator's Close method. Replace close with the Windows equivalent closesocket and add WSACleanup afterwards.

::mediapipe::Status Close(CalculatorContext* cc) {
    if (!cc->GraphStatus().ok()) {
      return ::mediapipe::OkStatus();
    }
    closesocket(sock);
    WSACleanup();
    return ::mediapipe::OkStatus();
}

Here's a gist with all those changes added in.

Aaaaaaand we're done! From here you can follow all the steps in Madeline's tutorial and hopefully it'll work on your Windows machine. Let me know if anything blows up.

I should mention that I actually ended up creating a slightly different calculator than MyPassThroughCalculator, and am just quickly applying what I learnt there to type up this example. I haven't fully tested it, so if there's anything I missed give me a yell.
The calculator I created is called JSONOverUDPOutput. Differences are it's for the upper-body pose example, uses JSON instead of Protobuf (because I'm lazy) and doesn't pass inputs through (so can confirm #2).

Happy to help anyone else. Thanks heaps @madelinegannon for the awesome tutorial! Wouldn't have gotten anywhere without it 😃

@madelinegannon
Copy link
Owner

This is so great! Thanks for sharing @ChapC

@greywartinger
Copy link

Hi @ChapC , I really appreciate you taking the time to walk people through your process. I am quite new to this type of install and was curious if you might help point me in the right direction with some of the steps.
I think I am successfully up to step 6 on the windows install guide, but am not sure if I am setting the Bazel variables correctly. after I hit enter with the correct version numbers, nothing seems to happen. Should I be expecting anything?
Also, I am not sure of how to enter the MediaPipe repository, I don't think I can actually type out the command properly in the command prompt. Perhaps I'm using the wrong command prompt? Right now I'm just using the standard Windows one.

Thank you for your help with this!

@ChapC
Copy link

ChapC commented Nov 4, 2020

Glad to help!
Setting environment variables in the console doesn't give you any feedback unless there was an error. So if you're not seeing anything after you hit enter, that means they were set successfully. Do keep in mind that set only sets environment variables for the current console window, so once you close it they will be removed.

I'm not sure exactly what you mean by 'entering' the MediaPipe repository. In step 7, running the git clone https://github.com/google/mediapipe.git command should download the repository to whichever folder you're currently in. There's nothing special about repositories once they're on your computer, they just look like normal folders. You can move the command prompt into the folder just like you would any other by using the cd command.

I used the normal command prompt too, so it should work okay. Let me know how you go with it.

@greywartinger
Copy link

Thank you! This was already a huge help, I am working through the next steps now and will keep you posted.

Also, thank you to @madelinegannon!! What a tremendous effort to get this information out there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants