Show a tcp video stream (from FFPLAY / FFMPEG) in

2019-03-16 22:20发布

问题:

I try 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 iside 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.

回答1:

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.



回答2:

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


回答3:

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:admin@192.168.0.163/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