kyrylomyr
kyrylomyr

Reputation: 12632

WPF MediaElement - play file with custom extension

I have video files with the custom extension. They are correctly encoded MP4-files. When I try to play such file using the MediaElement, nothing happened:

<MediaElement x:Name="UxVideo" Source="D:\111.xyz" />

However, it works fine when I rename the file extension:

<MediaElement x:Name="UxVideo" Source="D:\111.mp4" />

It seems like MediaElement uses the file extension to figure out the video format. Are there any workarounds to make MediaElement play files with custom extensions? Maybe any other controls to achieve what I need?

It's not suitable for me to rename file at runtime, because other applications may use it. And I can't make a copy of file, because it may have a large size.

UPDATE

I have associated my file extension with the Windows Media Player, and MediaElement started to work correctly o_O

OK, but it's my machine. What to do with the client's PC?

Upvotes: 0

Views: 2551

Answers (4)

goobering
goobering

Reputation: 1553

It appears to be possible to spoof the MediaElement using a symbolic link. This wouldn't incur substantial storage overheads, but any links created should probably be deleted after use to keep everything tidy.

From https://msdn.microsoft.com/en-us/library/windows/desktop/aa365680%28v=vs.85%29.aspx :

A symbolic link is a file-system object that points to another file system object. The object being pointed to is called the target.

Symbolic links are transparent to users; the links appear as normal files or directories, and can be acted upon by the user or application in exactly the same manner.

An example of how to create a symbolic link is given here: https://stackoverflow.com/a/11156870/1095741 . I've amended symbolicLink and fileName to match your question:

namespace ConsoleApplication
{
    class Program
    {
        [DllImport("kernel32.dll")]
        static extern bool CreateSymbolicLink(
        string lpSymlinkFileName, string lpTargetFileName, SymbolicLink dwFlags);

        enum SymbolicLink
        {
            File = 0,
            Directory = 1
        }

        static void Main(string[] args)
        {
            string symbolicLink = @"D:\111.mp4";
            string fileName = @"D:\111.xyz";

            using (var writer = File.CreateText(fileName))
            {
                writer.WriteLine("Hello World");
            }

            CreateSymbolicLink(symbolicLink, fileName, SymbolicLink.File);
        }
    }
}

Upvotes: 2

kyrylomyr
kyrylomyr

Reputation: 12632

The workaround that I've found is to register the custom file extension for the Windows Media Player before trying to play the video file. So, we need to execute the following code on application start:

private void RegisterFileExtension(string fileName)
{
    var ext = Path.GetExtension(fileName);
    var key = Registry.CurrentUser.CreateSubKey(
        $@"Software\Microsoft\MediaPlayer\Player\Extensions\{ext}"); // C# 6.0
    key.SetValue("Permissions", 1);
    key.SetValue("Runtime", 1);
}

This code creates the required keys in the Registry, the same what you get when manually open file with the Windows Media Player.

Then, the MediaElement plays video fine:

<MediaElement Source="D:\111.xyz" />

Upvotes: 0

goobering
goobering

Reputation: 1553

Looks like MediaElement.SetSource() has an option for specifying a MIME type in addition to a source. Code lifted verbatim from https://msdn.microsoft.com/en-us/library/windows/apps/br244338.aspx .

async private void SetLocalMedia()
{
    var openPicker = new Windows.Storage.Pickers.FileOpenPicker();

    openPicker.FileTypeFilter.Add(".wmv");
    openPicker.FileTypeFilter.Add(".mp4");
    openPicker.FileTypeFilter.Add(".wma");
    openPicker.FileTypeFilter.Add(".mp3");

    var file = await openPicker.PickSingleFileAsync();

    var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);

    // mediaControl is a MediaElement defined in XAML
    if (null != file)
    {
        mediaControl.SetSource(stream, file.ContentType);

        mediaControl.Play();
    }
}

Upvotes: 2

Jesse Glover
Jesse Glover

Reputation: 335

I will answer this, and with this answer, I am not trying to demean your intelligence whatsoever. Whenever you have a different file extension in code, you want to make sure the file extension is the exact same on the file itself.

Example:

<MediaElement x:Name="UxVideo" Source="D:\BABYMETAL - Megitsune.Mp4" />
<MediaElement x:Name="UxVideo" Source="D:\BABYMETAL - Megitsune.XYZ" />

Which one would work?

In the picture, I have 2 files that are the same except for the file extension. With this first image and code sample, they both reflect mp4 and will work appropriately. The second image and code sample both reflect the .xyz extension, and will work appropriately.

Simple answer, make sure the file and code extensions match.

Upvotes: -2

Related Questions