Search Unity

url for VideoPlayer in UWP

Discussion in 'Windows' started by klutzgames, Nov 6, 2017.

  1. klutzgames

    klutzgames

    Joined:
    Apr 6, 2015
    Posts:
    10
    I am using Unity 2017.2 to build an immersive Mixed Reality video player.
    To play videos that are not included in the assets, the VideoPlayer has the url, which can be set to a local file path.
    Unfortunately UWP does not allow the common file access. However, I can for example allow the Video Library in the UWP settings and can then access the files within my app like this:
    Code (CSharp):
    1.  
    2. var file = KnownFolders.VideosLibrary.GetFileAsync("video.mp4").GetAwaiter().GetResult();
    3.  
    I can read this file within my code without problems, so the file access itself works. However, to play it within the video player, I need to pass it a an url, for example like this:
    Code (CSharp):
    1.  
    2. var uri = new Uri(file.Path, UriKind.RelativeOrAbsolute);
    3. videoPlayer.url = uri.LocalPath;
    4.  
    Unfortunately this does not work. I tried many possible combination for the url, but I couldn't find anything that works.

    I found an article about this, which suggests to create a token, and pass the token as url:
    http://cubeslam.net/2017/04/05/unity3d-5-6-video-player-and-uwp/

    But this also did not work for me. The VideoPlayer just does not play it.

    Does anybody know how to do this correctly, or is it currently just not possible?

    The only work around I can still think of is creating inside the app a web server to stream the video to the VideoPlayer. But I hope there is an easier solution.

    Thanks a lot!
     
  2. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    Try uri.AbsoluteUri.
    Note, that there was a bug where on UWP you could only read files from directories like StreamingAssets, not from special folders that require permission in the manifest. This bug should be fixed in latest Unity releases.
     
  3. klutzgames

    klutzgames

    Joined:
    Apr 6, 2015
    Posts:
    10
    Thanks a lot for your reply!
    Unfortunately I still get a permission error:
    I use Unity Version 2017.2.0f3 Personal. Should I use the latest beta?
     
  4. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    It's better to store video to a different place, like Application.persistentDataPath.
    Reading files from those special directories is slow.
     
    carlaj likes this.
  5. klutzgames

    klutzgames

    Joined:
    Apr 6, 2015
    Posts:
    10
    But my application is a general VR Video Player therefore copying the video files is no option.So, streaming it from an build in web server is the only option after all?
     
    carlaj likes this.
  6. MKMobile

    MKMobile

    Joined:
    Jun 11, 2020
    Posts:
    1
    Is there any progress or alternative available to the above issue? Was it registered as a bug? I try to play videos with url in UWP environment and I face "cannot play url / cannot read file" error regardless if I provide uri.localpath or absoluteuri. This is almost for sure not an access issue because I am able to access files in the same folder where mp4 is located - I load pictures, using standard path "C:\folder\file.jpg" (some areas required broadFileSystemAccess right), without any problem.

    VideoPlayer works ok in Editor, but i fail to play any URL in UWP. Does it require some special rights? I tried "bacgroundplayback" but it doesn't change anything. I could also switch back to x64 , but then the application is not visible in start menu in MixedReality, so it seems that I HAVE TO use UWP to be able to deliver something that can be launched from WMR house :(
     
  7. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    There was never a bug report on this. You should be able to work around it by copying the video to persistentDataPath and setting the url to that location.
     
  8. holo-krzysztof

    holo-krzysztof

    Joined:
    Apr 5, 2017
    Posts:
    77
    This is still very much a bug in 2020 LTS. It's not possible to play files from the Videos library on a HoloLens which is very frustrating.

    The thing is, File.Exists returns true and if I tried opening it for read access it'd probably work fine, so I guess VideoPlayer internally uses an API that does not allow access to brokered files (CreateFile instead of CreateFileFromApp).
     
  9. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    Can you file a bug report?
     
    holo-krzysztof likes this.
  10. holo-krzysztof

    holo-krzysztof

    Joined:
    Apr 5, 2017
    Posts:
    77
    Done. It's number 1376489.

    By the way: I tried to work around this using the (badly documented) UWP import redirections mechanism (https://docs.microsoft.com/en-us/uw...estschema/element-uap7-importredirectiontable). Here's an example: https://www.tiraniddo.dev/2020/02/dll-import-redirection-in-windows-10_8.html

    The thing is, it doesn't seem to work for calls coming from UnityPlayer.dll. GameAssembly, baselib and even the CRT DLLs are redirected like I expect, but UnityPlayer (which makes the file system calls for VideoPlayer) is not, which is super weird.
    I thought it might be due to the fact that UnityPlayer is a WinRT component, but trying the same with a blank project did work fine, so idk.

    Unfortunately it wouldn't be a viable workaround for us because the redirection mechanism is broken on HoloLens 2 at the OS level (process crashes on startup).
     
    Last edited: Oct 28, 2021
  11. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    Unity uses CreateFile2, not CreateFileW. What API are you redirecting?
     
  12. holo-krzysztof

    holo-krzysztof

    Joined:
    Apr 5, 2017
    Posts:
    77
    I'm redirecting CreateFile2 and GetFileAttributesExW, but it does not work. Loader snaps doesn't say that redirects are applied to UnityPlayer.dll whereas they are e.g. for GameAssembly.dll.

    I tested the redirection mechanism in a blank project which worked fine. Is UnityPlayer.dll special in any way compared to a regular WinRT component or DLL?
     
  13. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    Sorry. I just looked at the code again and I realized that my initial conclusion that we use CreateFile2 is incorrect. We actually don't open the file ourselves right now, we ask Media Foundation to do it for us using this API: https://docs.microsoft.com/en-us/wi...te/nf-mfreadwrite-mfcreatesourcereaderfromurl

    It's very likely that whatever mechanism it uses to open the file doesn't play nice with WinRT DLLs. I'm not sure where to go from here: you could try figuring out what kind of file API it uses and try redirecting that but I'm not sure how well that would work.

    And thanks for the bug report. We will look into it.
     
  14. holo-krzysztof

    holo-krzysztof

    Joined:
    Apr 5, 2017
    Posts:
    77
    That looks interesting, thanks.

    Even if the redirection mechanism worked for calls originating from UnityPlayer.dll, it wouldn't help in this case. One of the documented limitations is that you can't redirect internal calls from OS DLLs, so the Media Foundation API would still do what it's doing.

    Getting around this would likely require in-memory patching and I don't feel comfortable in shipping this sort of hacks in production software.

    Anyway, thanks for your time and I hope the bug gets resolved at some point. :)
     
  15. holo-krzysztof

    holo-krzysztof

    Joined:
    Apr 5, 2017
    Posts:
    77
    MFCreateSourceReaderFromURL uses CreateFileW internally, I've just tested it in a blank UWP app.
     
  16. RobVS

    RobVS

    Joined:
    Sep 28, 2018
    Posts:
    1
    A possible workaround would be to use the StorageFile APIs, but you would just get a pointer to the RandomAccessStream and use MFCreateMFByteStreamOnStreamEx() to get an IMFByteStream and then use that to call MFCreateSourceReaderFromByteStream(). This should work around the issue.
     
    holo-krzysztof likes this.
  17. holo-krzysztof

    holo-krzysztof

    Joined:
    Apr 5, 2017
    Posts:
    77
    For context, Rob has been taking care of this issue on Microsoft's side. I have attached one of his e-mails to the bug report as it might help Unity in working around this issue should you decide to do so.
     
  18. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    Sorry it's taken a good minute, but I finally implemented a workaround using MFCreateMFByteStreamOnStreamEx() today. The fix will first be merged to 2022.2 and I then plan to backport it to Unity 2020.3 and up.
     
    holo-krzysztof likes this.
  19. holo-krzysztof

    holo-krzysztof

    Joined:
    Apr 5, 2017
    Posts:
    77
    I'm looking forward to this fix; I just tested again on a Windows version where this is supposedly fixed, but playback still doesn't work.
    The error is (still?) "WindowsMediaFoundation received empty file U:/Users/Visitor0/Videos/test.mp4" in an infinite loop, so maybe there's another API being used that doesn't play nice with AppContainers.
    I also tested a non-Unity app to call MFCreateSourceReaderFromURL and that worked out fine. The newest HoloLens emulator version already contains the Windows fix if you want to test locally: https://docs.microsoft.com/en-us/wi...p/advanced-concepts/hololens-emulator-archive
     
  20. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    Oh my, Microsoft fixed and released a patch faster than we did, I did not expect that :(. My fix is currently stuck in merge issues but I expect it to land this week.

    Can you try redirecting GetFileAttributesExW in UnityPlayer.dll to GetFileAttributesExFromAppW and see if that works around the issue?
     
  21. holo-krzysztof

    holo-krzysztof

    Joined:
    Apr 5, 2017
    Posts:
    77
    IIRC I never got redirections from UnityPlayer.dll to work, sadly :/
     
  22. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    Alright. I'm trying to get the fix in as soon as I can. I'll post when I know exactly where it will land.
     
    holo-krzysztof likes this.
  23. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    The fix landed to 2022.1.0b10, 2021.2.14f1 and 2020.3.31f1. It should be released next week.
     
    holo-krzysztof likes this.
  24. holo-krzysztof

    holo-krzysztof

    Joined:
    Apr 5, 2017
    Posts:
    77
    Very nice, I'm looking forward to that release :)
     
  25. xwonder

    xwonder

    Joined:
    Jun 18, 2018
    Posts:
    10
    It seems the issue persists in 2020.3.31f1, at least for Hololens 2.

    I can load and display pictures from Application.persistentDataPath (was able to do in older versions also), however setting an url of a videoPlayer to a .mp4 file in Application.persistentDataPath and hitting play still doesn't play the video on HL2 (does play it in editor).

    Are there any new settings that need to be set in order to make it work?
     
  26. holo-krzysztof

    holo-krzysztof

    Joined:
    Apr 5, 2017
    Posts:
    77
    I just tested with the repro project I used to report the bug, and playing back a file from the HoloLens Video library works fine. Here's the code for loading something from Videos:
    Code (CSharp):
    1. public class VideoPlayerSetup : MonoBehaviour
    2. {
    3.     // Start is called before the first frame update
    4.     void Start()
    5.     {
    6.         string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyVideos), "test.mp4");
    7.         var videoPlayer = GetComponent<VideoPlayer>();
    8.  
    9.         Uri u = new Uri(new Uri("file://"), path);
    10.         videoPlayer.url = u.AbsoluteUri;
    11.     }
    12. }
    The VideoPlayer component is set to Play on Awake, so as soon as the url is assigned, it starts the video.
     
  27. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    Make sure you enable the Videos folder capability in application manifest. It should just work otherwise.
     
  28. xwonder

    xwonder

    Joined:
    Jun 18, 2018
    Posts:
    10
    I've enabled VideosLibrary Capabilities and it did not fix the issue.

    Correct me if I'm wrong, but enabling VideosLibrary would allow me to play videos from my Videos folder and would not really affect playing videos from application persistent data path folder? Further more I believe the VideosLibrary Capabilities only give me read privileges, so I cannot use Videos folder as a work around since I cannot write files retrieved from the web to it.

    To clarify what my issue is: I download picture and video files from the web and save them to the application persistent data path. I can access and display/play pictures and videos in the Unity editor. I can display pictures on Hololens 2 but cannot play the video. Through the Windows Device Portal I checked that the video downloads successfully and is stored at the url path I provide to the videoPlayer. I've also tried the AbsolutePath approach with no success.
     
  29. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    Then your problem sounds entirely unrelated to what is discussed about. The problem holo-krzysztof had was that while it did work when playing from Application.persistentDataPath, it didn't work when playing out of Videos folder. So what happens when you try to play file out of Application.persistentDataPath?

    Your assumption is correct.