FranceBB
3rd November 2020, 13:05
Hi there,
since the need of an open source and free to use Waveform Monitor was growing among my colleagues, I gave them my VideoTek (https://forum.doom9.org/showthread.php?t=175249) which is great.
Too bad, none of them knows how to code in Avisynth 'cause they're QC-guys, it's not their job to encode.
So I was like: "fine, I can automatize it and put it in a graphical user interface", but it's turning out to be more complicated than I thought.
With this code:
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.IO;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;
namespace VideoTek
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//Getting installation directory to load .DLLs
string my_program_directory = System.IO.Directory.GetCurrentDirectory();
// "Open File" Button
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.InitialDirectory = "c:\\";
openFileDialog1.RestoreDirectory = true;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
string selectedFileName = openFileDialog1.FileName;
//Save the path, name + extension of the selected file
System.IO.File.WriteAllText(my_program_directory + @"\MyFile.ini", selectedFileName);
//Creating .avs Script
string escape = "\"";
string myplugin1 = @"LoadPlugin(" + escape + my_program_directory + @"\LSMASHSource.dll" + escape + ")";
string myplugin2 = @"Import(" + escape + my_program_directory + @"\Videotek.avs" + escape + ")";
string my_AVS_Script = myplugin1 + System.Environment.NewLine + myplugin2 + System.Environment.NewLine + @"LWLibavVideoSource(" + escape + selectedFileName + escape + @")" + System.Environment.NewLine + @"VideoTek()";
System.IO.File.WriteAllText(my_program_directory + @"\AVS_Script.avs", my_AVS_Script);
}
}
// "Play" Button
private void button2_Click(object sender, EventArgs e)
{
//Importing dependencies
[DllImport("user32.dll", SetLastError = true)]
static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
// start ffplay
var ffplay = new Process
{
StartInfo =
{
FileName = "ffplay",
//open the AVS Script
Arguments = my_program_directory + @"\AVS_Script.avs",
// 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 1280x720
MoveWindow(ffplay.MainWindowHandle, 0, 0, 1280, 720, true);
var mymonitor = ffplay.MainWindowHandle;
//groupBox1.Controls.Add();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void groupBox1_Enter(object sender, EventArgs e)
{
}
}
}
I'm using the button1_Click action to basically prompt the user to pick-up a video. After that, I store the path of wherever the program has been installed and I save the whole name in an .ini file. After that, it's just a matter of creating an Avisynth Script with an Indexer (LWLibav) and VideoTek().
After that, FFPlay is called and compiles the Avisynth Script in real time, thus showing the result to the user.
So far so good, but there's a problem.
FFPlay generates a different, separate process and as such, it generates a different window which I'm desperately trying to "overlay/redraw" inside my program, in particular inside groupBox1. The problem is that I don't know how to do that.
I thought that this was going to do it:
// 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 1280x720
MoveWindow(ffplay.MainWindowHandle, 0, 0, 1280, 720, true);
by setting the ffplay.MainWindowHandle to this.Handle, however it really doesn't do what I wanted...
Any suggestion?
since the need of an open source and free to use Waveform Monitor was growing among my colleagues, I gave them my VideoTek (https://forum.doom9.org/showthread.php?t=175249) which is great.
Too bad, none of them knows how to code in Avisynth 'cause they're QC-guys, it's not their job to encode.
So I was like: "fine, I can automatize it and put it in a graphical user interface", but it's turning out to be more complicated than I thought.
With this code:
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.IO;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;
namespace VideoTek
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//Getting installation directory to load .DLLs
string my_program_directory = System.IO.Directory.GetCurrentDirectory();
// "Open File" Button
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.InitialDirectory = "c:\\";
openFileDialog1.RestoreDirectory = true;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
string selectedFileName = openFileDialog1.FileName;
//Save the path, name + extension of the selected file
System.IO.File.WriteAllText(my_program_directory + @"\MyFile.ini", selectedFileName);
//Creating .avs Script
string escape = "\"";
string myplugin1 = @"LoadPlugin(" + escape + my_program_directory + @"\LSMASHSource.dll" + escape + ")";
string myplugin2 = @"Import(" + escape + my_program_directory + @"\Videotek.avs" + escape + ")";
string my_AVS_Script = myplugin1 + System.Environment.NewLine + myplugin2 + System.Environment.NewLine + @"LWLibavVideoSource(" + escape + selectedFileName + escape + @")" + System.Environment.NewLine + @"VideoTek()";
System.IO.File.WriteAllText(my_program_directory + @"\AVS_Script.avs", my_AVS_Script);
}
}
// "Play" Button
private void button2_Click(object sender, EventArgs e)
{
//Importing dependencies
[DllImport("user32.dll", SetLastError = true)]
static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
// start ffplay
var ffplay = new Process
{
StartInfo =
{
FileName = "ffplay",
//open the AVS Script
Arguments = my_program_directory + @"\AVS_Script.avs",
// 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 1280x720
MoveWindow(ffplay.MainWindowHandle, 0, 0, 1280, 720, true);
var mymonitor = ffplay.MainWindowHandle;
//groupBox1.Controls.Add();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void groupBox1_Enter(object sender, EventArgs e)
{
}
}
}
I'm using the button1_Click action to basically prompt the user to pick-up a video. After that, I store the path of wherever the program has been installed and I save the whole name in an .ini file. After that, it's just a matter of creating an Avisynth Script with an Indexer (LWLibav) and VideoTek().
After that, FFPlay is called and compiles the Avisynth Script in real time, thus showing the result to the user.
So far so good, but there's a problem.
FFPlay generates a different, separate process and as such, it generates a different window which I'm desperately trying to "overlay/redraw" inside my program, in particular inside groupBox1. The problem is that I don't know how to do that.
I thought that this was going to do it:
// 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 1280x720
MoveWindow(ffplay.MainWindowHandle, 0, 0, 1280, 720, true);
by setting the ffplay.MainWindowHandle to this.Handle, however it really doesn't do what I wanted...
Any suggestion?