Vlc.DotNet icon indicating copy to clipboard operation
Vlc.DotNet copied to clipboard

How to play any track of AVI file with multiple video tracks.

Open marksard opened this issue 5 years ago • 15 comments

I have a question about Vlc.DotNet.Wpf

Generic information

  • Vlc.DotNet version : 3.0.0
  • Vlc.DotNet project used : WPF/Core
  • libvlc version : VideoLAN.LibVLC.Windows 3.0.7.1
  • .net version : 4.7.2
  • Project language : C#
  • Project build architecture : AnyCPU
  • Operating system : Windos10 x64

Summary

I have an AVI file that contains two tracks. I want to play track # 2 from the start of playing this file. Please tell me the procedure.

+----[ Stream 0 ]
|
| Codec: H264 - MPEG-4 AVC (part 10) (H264)
| Type: Video
| Video resolution: 1280x720
| Buffer dimensions: 1280x720
| Frame rate: 19.100000
| Decoded format:
| Orientation: Top left
| Chroma location: Left
|
+----[ Stream 1 ]
|
| Codec: H264 - MPEG-4 AVC (part 10) (H264)
| Type: Video
| Video resolution: 1280x720
| Buffer dimensions: 1280x720
| Frame rate: 19.100000
| Orientation: Top left
|
+----[ Stream 2 ]
|
| Codec: araw
| Type: Audio
| Channels: Stereo
| Sample rate: 44100 Hz
| Bits per sample: 16
|
+----[ end of stream info ]

I did a preliminary survey. We have obtained the information that we can substitute the second track object "SourceProvider.MediaPlayer.Video.Tracks.All.ElementAt (2)" into "SourceProvider.MediaPlayer.Video.Tracks.Current". However, right after SetMedia () there is nothing in Video.Tracks, so some steps are required.

Thank you for your cooperation.

marksard avatar Jul 30 '19 07:07 marksard

Did you try to Parse() your media?

jeremyVignelles avatar Jul 30 '19 08:07 jeremyVignelles

Where/which is there parse() method?

I tried a below in a UI thread.

var videoItem = VlcControl.SourceProvider.MediaPlayer; // VlcControl is definition at xaml
videoItem.SetMedia(new Uri(fileName));
videoItem.GetMedia().Parse();
videoItem.Video.Tracks.Current = videoItem.Video.Tracks.All.ElementAt(a); <==== exception

Exception occured -> System.ArgumentOutOfRangeException. videoItem.Video.Tracks.Count is zero and Current is null.

Regards,

marksard avatar Jul 30 '19 09:07 marksard

I investigated a little. Additional Info:

var videoItem = VlcControl.SourceProvider.MediaPlayer; // VlcControl is definition at xaml
videoItem.SetMedia(new Uri(fileName));

var media = videoItem.GetMedia();
media.Parse();
var mediaTrack = media.Tracks.ElementAt(1);  // (A) element #1 is second video track.

var tracks = videoItem.Video.Tracks.All.ToArray(); // (B) tracks.current is null. 

(A) mediaTrack is MediaTrack class. (B) tracks.current is TrackDiscription class. And it class is Readonly. We (Users) is not create. Therefore I can't select second track.

How can I play the second track? Please tell me the correct procedure.

Best Regards,

marksard avatar Aug 01 '19 06:08 marksard

Did you try this?

videoItem.Video.Tracks.Current = videoItem.Video.Tracks.All.Skip(1).First();

Here, it takes the second item in Tracks.All.

I think you can remove the synchronous Parse() and make your stream selection in the Parsed event.

jeremyVignelles avatar Aug 01 '19 07:08 jeremyVignelles

I tried.

var videoItem = VlcControl.SourceProvider.MediaPlayer; // VlcControl is definition at xaml
videoItem.SetMedia(new Uri(fileName));

var media = videoItem.GetMedia();
media.Parse();
var mediaTrack = media.Tracks.ElementAt(1);  // (A) element #1 is second video track.

var tracks = videoItem.Video.Tracks.All.Skip(1).First(); // <--- System.InvalidOperationException
videoItem.Video.Tracks.Current = tracks;

Uh, Tracks count is zero.

marksard avatar Aug 01 '19 08:08 marksard

Do you have a sample file so that I can try?

jeremyVignelles avatar Aug 03 '19 09:08 jeremyVignelles

I shared link at googledrive https://drive.google.com/open?id=16IKj_Ni8lfapEEHZKlxgXqr3qQAVE0rA

Thank you for your help.

marksard avatar Aug 05 '19 02:08 marksard

Hi, Did you find something wrong with the video? Is another sharing method better?

Best Regards,

marksard avatar Aug 20 '19 05:08 marksard

Thanks for pinging me. I have been on vacation for a week and totally forgot about that. You might hear from me in the next few days, please ping again if I don't.

jeremyVignelles avatar Aug 20 '19 07:08 jeremyVignelles

Oh, I'm Sorry, thanks replying.

marksard avatar Aug 20 '19 07:08 marksard

Hello. I would like to solve this problem but need some help. Thank you.

marksard avatar Oct 01 '19 00:10 marksard

Aaand.... I totally forgot again :D Did you manage to play the other track in VLC itself?

jeremyVignelles avatar Oct 01 '19 06:10 jeremyVignelles

Shared AVI file can play video track 2 with VLCPlayer.

marksard avatar Oct 01 '19 08:10 marksard

I've tried your sample and didn't manage to switch the track. I tried this:

            vlcControl.VlcMediaPlayer.Playing += (s, e) =>
            {
                ThreadPool.QueueUserWorkItem(_ =>
                {
                    var t = vlcControl.VlcMediaPlayer.Video.Tracks.All.ToArray();
                    if (t.Length >= 2)
                    {
                        vlcControl.VlcMediaPlayer.Video.Tracks.Current = t[2];
                    }
                });
            };

t[0] works (it disables the video), but 1 and 2 show the same stream.

There seems to be a --video-track option in VLC, but it doesn't seem to work either. I guess your next step would be to ask videolan directly :

  • Send them the video files at http://streams.videolan.org/upload/
  • Submit a trac report by linking the video file and linking this thread.

jeremyVignelles avatar Oct 08 '19 22:10 jeremyVignelles

Hi, Thank you for your reply. I tried I created new simple project. And then your code pasted as below.

<Window x:Class="VLCSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:wpf="clr-namespace:Vlc.DotNet.Wpf;assembly=Vlc.DotNet.Wpf"
        xmlns:local="clr-namespace:VLCSample"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <wpf:VlcControl x:Name="VlcControl"/>
    </Grid>
</Window>
public MainWindow()
{
    InitializeComponent();

    var currentAssembly = Assembly.GetEntryAssembly();
    var currentDirectory = new FileInfo(currentAssembly.Location).DirectoryName;
    var libDirectory = new DirectoryInfo(System.IO.Path.Combine(currentDirectory, "libvlc", IntPtr.Size == 4 ? "win-x86" : "win-x64"));
    VlcControl.SourceProvider.CreatePlayer(libDirectory);

    var player = VlcControl.SourceProvider.MediaPlayer;
    player.SetMedia(new Uri(@"N:\VMShare\avi\COMTEC_ZDR-015\2017_04_06_21_25_49_Nor.AVI"));
    player.Playing += (s, e) =>
    {
        ThreadPool.QueueUserWorkItem(_ =>
        {
            var t = player.Video.Tracks.All.ToArray();
            if (t.Length >= 2)
            {
                player.Video.Tracks.Current = t[2];
            }
        });
    };

    player.Play();
}

This code played track 2. However, it will end without an exception during playback.

And I also modified the sample code of LibVLCSharp.WPF (https://github.com/videolan/libvlcsharp/tree/223a1e86db0b0ffd120247a0ccf7f85c01d2c470/Samples/LibVLCSharp.WPF.Sample), but also played video track 2. This was played on another window. (But I don't need behavior on another window)

Thank you,

marksard avatar Oct 09 '19 10:10 marksard