Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Show a tcp video stream (from FFPLAY / FFMPEG) in an C# application

I' trying to make my Parrot AR Drone 2.0 work with a Windows machine.

I have a simple C# application to control it - but now i want the video stream inside of my application.

If I execute ffplay tcp://192.168.1.1:5555 it connects to the videostream and shows a window with the video.

How can I get this video inside of my application? Like, a simple 'frame' or 'image' that gets filled with that content?

I have never worked that much with C# so any help would be awesome.

like image 981
Rob Avatar asked Nov 12 '22 13:11

Rob


1 Answers

You can launch the ffplay process and then PInvoke SetParent to place the player window inside your form and MoveWindow to position it.

To do this you would need to define the following.

[DllImport("user32.dll", SetLastError = true)]
private static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);

[DllImport("user32.dll")]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

Then you can use the two native methods like so.

// start ffplay 
var ffplay = new Process
    {
        StartInfo =
            {
                FileName = "ffplay",
                Arguments = "tcp://192.168.1.1:5555",
                // hides the command window
                CreateNoWindow = true, 
                // redirect input, output, and error streams..
                RedirectStandardError = true,
                RedirectStandardOutput = true,
                UseShellExecute = false    
            }
    };

ffplay.EnableRaisingEvents = true;
ffplay.OutputDataReceived += (o, e) => Debug.WriteLine(e.Data ?? "NULL", "ffplay");
ffplay.ErrorDataReceived += (o, e) => Debug.WriteLine(e.Data ?? "NULL", "ffplay");
ffplay.Exited += (o, e) => Debug.WriteLine("Exited", "ffplay");
ffplay.Start();

Thread.Sleep(200); // you need to wait/check the process started, then...

// child, new parent
// make 'this' the parent of ffmpeg (presuming you are in scope of a Form or Control)
SetParent(ffplay.MainWindowHandle, this.Handle);

// window, x, y, width, height, repaint
// move the ffplayer window to the top-left corner and set the size to 320x280
MoveWindow(ffplay.MainWindowHandle, 0, 0, 320, 280, true);

The standard output of the ffplay process, the text you usually see in the command window is handled via ErrorDataReceived. Setting the -loglevel to something like fatal in the arguments passed to ffplay allows you to reduce the amount of events raised and allows you to handle only real failures.

like image 111
Fraser Avatar answered Nov 15 '22 05:11

Fraser