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

3

6

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.

Deification answered 7/1, 2013 at 18:33 Comment(5)
What code do you have thus far for doing this..?Elmiraelmo
check out this link and look at the documentation it may or may not help.. gstreamer.freedesktop.orgElmiraelmo
dronecontroller.codeplex.comElmiraelmo
Here is the repository - github.com/RobQuistNL/ARDrone-Control-.NET- i've edited some code but haven't pushed yet. Will do tonight :) EDIT: There is a video-streaming-code in there, but that one is for the 1.0 version of the drone. Doesn't work on the 2.0 version. I believe its an H.687 (or something like that) streamDeification
please put some code that you had tried in-order to help you to solve your problemParaclete
M
5

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.

Muchness answered 11/8, 2013 at 1:26 Comment(10)
Will try both methods tomorrow!Deification
No worries, I also added in how you would capture the output text into managed code from the process, allowing you to handle errors etc.Muchness
Very nice! Thank you :) A lot of ARDrone flyers will thank you if this works good!Deification
No worries at all. If you accept the answer people will be more likely to help you in the future too.Muchness
I still have to try it :P then i'll chose an answer. THanks!Deification
I also tried but my form hangs. Playback continues as I hear the audio but picture is still and cannot click any widget on the form. I saw that ffplay hangs.Presuppose
@MertGülsoy this is an old question but it should work as shown. The issue is probably the either the line Thread.Sleep(200); which is too short a time, or else ffplay is hanging for some other reason. What does the ffmpeg log output look like?Muchness
@Muchness you're right. ffplay hanging for some reason. Possibly the stream source is poor. Thanks.Presuppose
Ah, You can probably just check if there is an ffplay process running via Process.GetProcessesByName("ffplay"); and relaunch it if it has crashed. Also the ffplay process itself could be waiting for you to read its output, so you could create a separate thread to read from its standard output while you're waiting for it to exit. Without seeing the actual code/error logs it is hard to help. Maybe post your own question - I'd be happy to take a look for you.Muchness
since ffplay opens a console window first, you need to wait until ffplay.MainWindowHandle becomes not IntPtr.ZeroMantelpiece
S
-1

Have you tried streaming with media player? Just add the control from the toolbox on the form and then add the following code to your form.cs

 private void Form1_Load(object sender, EventArgs e)
    {
        axWindowsMediaPlayer1.URL = "your URL";
    }
}

Details in the following link

http://msdn.microsoft.com/en-us/library/bb383953%28v=vs.90%29.aspx
Strumpet answered 26/7, 2013 at 13:24 Comment(3)
well, that might work.. I'll try it tonight. But I guess this is not really a direct stream and i'll have some more latency this way. I'll get back at you tonight!Deification
any luck with the video?Strumpet
media player does not work with ffmpeg hosted streamMantelpiece
R
-1
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Drawing.Text;
using System.Text.RegularExpressions;
using System.Configuration;
using Microsoft.Win32;
using System.Windows.Forms.VisualStyles;


namespace FfplayTest
{
    public partial class Form1 : Form
    {
        [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);

        [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
        public static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);


        public Form1()
        {
            InitializeComponent();
            Application.EnableVisualStyles();
            this.DoubleBuffered = true;
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        public Process ffplay = new Process();
        private void xxxFFplay()
        {


            ffplay.StartInfo.FileName = "ffplay.exe";

            string _argString = "-fflags nobuffer \"rtsp://admin:[email protected]/live0.264\" -x 640 -y 480";
            string _newArgString = _argString.Replace("\",\"", ";");
            ffplay.StartInfo.Arguments = _newArgString;

            ffplay.StartInfo.CreateNoWindow = true;
            ffplay.StartInfo.RedirectStandardOutput = true;
            ffplay.StartInfo.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();
            IntPtr intPtr = ffplay.MainWindowHandle;
            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);


        }

        private void button1_Click(object sender, EventArgs e)
        {
            xxxFFplay();
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            try { ffplay.Kill(); }
            catch { }
        }
    }
}

My Code is this, How ever it is loading ffplay but don't move in to panel or don't position it to given

Runner answered 9/6, 2018 at 15:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.