Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
21st August 2010, 01:29 | #1 | Link |
Registered User
Join Date: Aug 2010
Location: Hamilton, Ontario, Canada
Posts: 15
|
x264 Progress Bar
hey, I was just wondering if anyone could help me make a progress bar for x264 with vb10? I am sort of new to programing, but I still know some things. I am making a DVD and Blu Ray Ripper that encodes the videos to be compatible to be streamed to the 360. I have that all done, but I just want to add a progress bar to everything, The Demuxing, Audio Encoding, Video Encoding, and Muxing. Right now I just have a marquee progress bar that will keep active till a file is created after one of the procedures are done.
So does anyone know how to help me make a progress bar for these things? First on the list the x264 procedure. |
21st August 2010, 01:43 | #2 | Link |
Software Developer
Join Date: Jun 2005
Location: Last House on Slunk Street
Posts: 13,248
|
What exactly is your problem/question ???
__________________
Go to https://standforukraine.com/ to find legitimate Ukrainian Charities 🇺🇦✊ |
21st August 2010, 01:57 | #3 | Link |
Un-Registered User
Join Date: Mar 2008
Location: Audio Stream - 0x80
Posts: 341
|
Add a ProgressBar to your form, then you will have to capture the stdout of the program(s), parse it and update the progressbar.
For x264, it should be pretty easy (i.e., just round it's percentage to an integer and set ProgressBar1.Value = x264Percentage) |
21st August 2010, 02:35 | #4 | Link | |
Registered User
Join Date: Aug 2010
Location: Hamilton, Ontario, Canada
Posts: 15
|
Quote:
So could you tell me how I could do this? Thanks. Metroidn1f |
|
21st August 2010, 03:50 | #5 | Link |
Mr. Sandman
Join Date: Sep 2003
Location: Haddonfield, IL
Posts: 11,768
|
http://msdn.microsoft.com/en-us/library/3x292kth.aspx
every program outputs console info to stdout and stderr (IIRC x264 outputs the progress percentage to stderr). you should parse them and get the info (percentage text) you need from that output, convert that into an int and set your progressbar.value property to that value. obviously you need a continous or timed capture of the stdout/stderr.
__________________
MPEG-4 ASP Custom Matrices: EQM V1(old), EQM AutoGK Sharpmatrix (aka EQM V2), EQM V3HR (updated 01/10/2004), EQM V3LR, EQM V3ULR (updated 04/02/2005), EQM V3UHR (updated 17/12/2004) and EQM V3EHR (updated 05/10/2004) Info about my ASP matrices. MPEG-4 AVC Custom Matrices: EQM AVC-HR Info about my AVC matrices My x264 builds. Mooo!!! Last edited by Sharktooth; 21st August 2010 at 04:06. |
21st August 2010, 04:10 | #6 | Link |
Un-Registered User
Join Date: Mar 2008
Location: Audio Stream - 0x80
Posts: 341
|
I honestly don't know how to capture stdout in realtime, my best suggestion would be to look into LoRd_MuldeR's Logger program.
|
21st August 2010, 04:14 | #7 | Link |
Mr. Sandman
Join Date: Sep 2003
Location: Haddonfield, IL
Posts: 11,768
|
look at ProcessStartInfo class and ProcessStartInfo.RedirectStandardOutput and ProcessStartInfo.RedirectStandardError properties
start here: http://msdn.microsoft.com/en-us/libr...v=VS.100).aspx then here: http://msdn.microsoft.com/en-us/libr...darderror.aspx and here: http://msdn.microsoft.com/en-us/libr...ardoutput.aspx
__________________
MPEG-4 ASP Custom Matrices: EQM V1(old), EQM AutoGK Sharpmatrix (aka EQM V2), EQM V3HR (updated 01/10/2004), EQM V3LR, EQM V3ULR (updated 04/02/2005), EQM V3UHR (updated 17/12/2004) and EQM V3EHR (updated 05/10/2004) Info about my ASP matrices. MPEG-4 AVC Custom Matrices: EQM AVC-HR Info about my AVC matrices My x264 builds. Mooo!!! |
21st August 2010, 06:31 | #8 | Link |
Registered User
Join Date: Aug 2010
Location: Hamilton, Ontario, Canada
Posts: 15
|
Sorry for my lack of knoledge, but I for the first link, I don't see what a progress bar has to do with Internet Explorer.
If possible, could someone give me an example of how to do it with x264, I am making batch files with VB then starting them, will that interfeer with anything? I learn better from examples no looking at some code that has nothing to do with or nothing to do with the same subject that I want to deal with. I know that might not make sence, but I am not good at expaining my self. To tell you the truth, this is my first application that I have attempted to make. If you need to know anything about my code, just ask me and I can provide it for you, or I can even give you the source to see how I have it programed. If you see it you will probably laugh on how I have it programed and set up. Well here is the link to my source. It is just a little under 12MB, it is a rar, compressed at stored/Fastest. The only thing that will work is the media info. I did not inckude the tools, the file would have been over 100MB. If you want me to include the tools, just ask and I will. http://download898.mediafire.com/5nt...r+-+Source.rar |
21st August 2010, 13:04 | #9 | Link |
Software Developer
Join Date: Jun 2005
Location: Last House on Slunk Street
Posts: 13,248
|
Well, it's not written in VisualBasic but in Pascal/Delphi, however here is a class that I use to redirect the stdout/stderr in several of my projects:
http://code.google.com/p/mulder/sour...RunProcess.pas This should be relatively easy to adapt for C/C++ or other languages (I often did it the other way around), as long as you are on the Windows platform (the code heavily uses Win32 API calls). Another project of mine related to stdout/stderr redirection that might be interesting in this context: http://code.google.com/p/mulder/sour...ger/logger.dpr (Please remember to release your software under a GPL license, in case you decide to re-use any of the code from the above mentioned projects ^^) See also: http://support.microsoft.com/kb/190351
__________________
Go to https://standforukraine.com/ to find legitimate Ukrainian Charities 🇺🇦✊ Last edited by LoRd_MuldeR; 21st August 2010 at 13:09. |
21st August 2010, 13:24 | #10 | Link |
Registered User
Join Date: Jun 2002
Location: On thin ice
Posts: 6,837
|
Why not use StaxRip, RipBot264, HDConvertToX, Handbrake etc.?
Answer to your question: http://forum.doom9.org/showthread.php?t=153580
__________________
https://github.com/stax76/software-list https://www.youtube.com/@stax76/playlists |
21st August 2010, 14:51 | #11 | Link | |
Mr. Sandman
Join Date: Sep 2003
Location: Haddonfield, IL
Posts: 11,768
|
Quote:
__________________
MPEG-4 ASP Custom Matrices: EQM V1(old), EQM AutoGK Sharpmatrix (aka EQM V2), EQM V3HR (updated 01/10/2004), EQM V3LR, EQM V3ULR (updated 04/02/2005), EQM V3UHR (updated 17/12/2004) and EQM V3EHR (updated 05/10/2004) Info about my ASP matrices. MPEG-4 AVC Custom Matrices: EQM AVC-HR Info about my AVC matrices My x264 builds. Mooo!!! Last edited by Sharktooth; 21st August 2010 at 15:04. |
|
21st August 2010, 15:48 | #12 | Link |
Registered User
Join Date: Sep 2008
Location: Birmingham (UK)
Posts: 69
|
@Metroidn1f
Heres a c# example - translation to vb should be straight forward. First launch your process - x264 in your case Code:
Process process = new Process(); process.StartInfo.FileName = <path to your x264.exe>; process.StartInfo.Arguments = <command line args you want to pass>; process.EnableRaisingEvents = false; process.StartInfo.UseShellExecute = false; process.StartInfo.CreateNoWindow = false; process.StartInfo.RedirectStandardOutput = false; process.StartInfo.RedirectStandardError = true; bool ok = process.Start(); Now attach to the stream you want to read Code:
using (StreamReader reader = process.StandardError) { string line = reader.ReadLine(); if( line == null ) break; // Interpret the line as you see fit } TTFN, Jon |
21st August 2010, 23:13 | #13 | Link | ||
Registered User
Join Date: Aug 2010
Location: Hamilton, Ontario, Canada
Posts: 15
|
Quote:
@JonE What are the arguments though? Are the arguments my command line? This is what I have so far. Code:
Dim process = New Process() process.StartInfo.FileName = "C:\Users\Metroidn1f\Desktop\Metroidn1f Encoder v4.2.38.3\Tools\x264\x264.exe" process.StartInfo.Arguments = "x264 --help> ""help.txt""" process.EnableRaisingEvents = False Process.StartInfo.UseShellExecute = False process.StartInfo.CreateNoWindow = False process.StartInfo.RedirectStandardOutput = False process.StartInfo.RedirectStandardError = True process.Start() Using IO.StreamReader(process.StandardError) String.line = reader.ReadLine() If (line = null) Then break() End If End Using Quote:
Last edited by Metroidn1f; 21st August 2010 at 23:45. |
||
22nd August 2010, 00:14 | #14 | Link |
Registered User
Join Date: Sep 2008
Location: Birmingham (UK)
Posts: 69
|
Yep, it is the command line args.
I've not used x264 in this scenario yet (used it with ffmpeg - nightmare!) but I guess the c# code would b something like Code:
process.StartInfo.Arguments = "x264 --help \"help.txt\"" The "using" statement looks wrong. It should be along the lines of "using <type> name = ...." but you do not seem to be setting a name for the variable. Its not a "using" statement like a using statement at the head of a file - you aren't specifying a namespace that is being used - rather, the "using" statement is a way of wrapping certain types of variable such that it is released when it goes out of scope, be that normal loop exit, via a break statement or even an exception. Try removing the "using" block and replacing it with Code:
StreamReader reader = process.StandardError; while( true) { string line = reader.Readline(); if( line == null ) break; // Do stuff with 'line' } TTFN, Jon |
31st August 2010, 23:32 | #15 | Link |
Registered User
Join Date: Aug 2010
Location: Hamilton, Ontario, Canada
Posts: 15
|
Alright, I have the progress bar working now, but I have 2 problems now.
The first on is I can't get my form 3 to do anything. As soon as I click the encode button it will start encoding, but it will not display anything in the form 3. I think I might have to use a background worker, but I don't know how. This is part of the code that I am using for the encode button. Code:
If VideoMode = "ConstantQuality" Then Dim s = Sub() Form3.Show() Using p As New Process AddHandler p.ErrorDataReceived, Sub(sendingProcess As Object, outLine As DataReceivedEventArgs) If outLine.Data <> "" Then BeginInvoke(Sub() Form3.Label1.Text = outLine.Data.Substring(1).Split("]")(0)) If ProgressETACheck < 1 Then If outLine.Data <> "" Then BeginInvoke(Sub() ProgressETA = outLine.Data.Split(" ")(6)) If ProgressETA = "kb/s," Then ProgressETACheck = ProgressETACheck + 1 End If End If If ProgressETACheck = 1 Then If outLine.Data <> "" Then BeginInvoke(Sub() Form3.Label5.Text = "ETA:" & outLine.Data.Split(" ")(8)) If outLine.Data <> "" Then BeginInvoke(Sub() Form3.Label4.Text = outLine.Data.Split(" ")(5) & " KB/s") If outLine.Data <> "" Then BeginInvoke(Sub() Form3.Label2.Text = outLine.Data.Split(" ")(1) & " Frames") If outLine.Data <> "" Then BeginInvoke(Sub() Form3.Label3.Text = outLine.Data.Split(" ")(3) & " fps") End If End Sub p.StartInfo.FileName = WorkingDirectory & "\Tools\x264\x264.exe" p.StartInfo.Arguments = "--quiet --profile " & VideoProfileDropDown.Invoke(New GetTextDelegate(AddressOf GetText), VideoProfileDropDown).ToString _ & " --level " & VideoLevelDropDown.Invoke(New GetTextDelegate(AddressOf GetText), VideoLevelDropDown).ToString & _ " --preset medium --no-dct-decimate --no-fast-pskip --crf " & _ VideoCrfUpDown.Invoke(New GetTextDelegate(AddressOf GetText), VideoCrfUpDown).ToString & " " & Trellis & " " & SubME & " " & MeAlgorhithim & " " & _ BAdapt & " --merange " & VideoMERangeUpDown.Text & " --fps " & fps & " --ref " _ & VideoReferenceFramesUpDown.Invoke(New GetTextDelegate(AddressOf GetText), VideoReferenceFramesUpDown).ToString & " --bframes " _ & VideoBFramesUpDown.Invoke(New GetTextDelegate(AddressOf GetText), VideoBFramesUpDown).ToString & " --deblock " _ & VideoDeblockStrengthUpDown.Invoke(New GetTextDelegate(AddressOf GetText), VideoDeblockStrengthUpDown).ToString & ":" _ & VideoDeblockThresholdUpDown.Invoke(New GetTextDelegate(AddressOf GetText), VideoDeblockThresholdUpDown).ToString & " --scenecut " _ & VideoIFramesUpDown.Invoke(New GetTextDelegate(AddressOf GetText), VideoIFramesUpDown).ToString & " --slices " _ & VideoSlicesUpDown.Invoke(New GetTextDelegate(AddressOf GetText), VideoSlicesUpDown).ToString & " --rc-lookahead " _ & VideoLookaheadUpDown.Invoke(New GetTextDelegate(AddressOf GetText), VideoLookaheadUpDown).ToString & " --qpmin " _ & VideoQuantinizersMinUpDown.Invoke(New GetTextDelegate(AddressOf GetText), VideoQuantinizersMinUpDown).ToString & " --qpmax " _ & VideoQuantinizersMaxUpDown.Invoke(New GetTextDelegate(AddressOf GetText), VideoQuantinizersMaxUpDown).ToString & " --qpstep " _ & VideoQuantinizersStepUpDown.Invoke(New GetTextDelegate(AddressOf GetText), VideoQuantinizersStepUpDown).ToString _ & " --output """ & VideoOutputBox.Invoke(New GetTextDelegate(AddressOf GetText), VideoOutputBox).ToString & """ """ _ & VideoInputBox.Invoke(New GetTextDelegate(AddressOf GetText), VideoInputBox).ToString & """" p.StartInfo.UseShellExecute = False p.StartInfo.RedirectStandardError = True p.StartInfo.CreateNoWindow = False p.Start() p.BeginErrorReadLine() p.WaitForExit() End Using End Sub s.BeginInvoke(Nothing, Nothing) End If End If My second problem is I don't know how to end the process if one of the windows are closed. I tried using on form closing but it will not let me cancel or kill the task with the variable. I tried making it a public variable but it still did not work. Can anyone help me out? |
1st September 2010, 07:01 | #16 | Link |
Registered User
Join Date: Aug 2007
Posts: 1,430
|
You're right, your form won't be repainted unless you use a background worker or a thread. If you go the thread route, you could try something like this:
Code:
Imports System.Threading Public Class Form1 Public t As Thread = New Thread(AddressOf doWork) Public p As Process = New Process() Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing If Not p.HasExited Then p.Close() 'or maybe p.Kill() End If If t.ThreadState = ThreadState.Running Then t.Abort() End If End Sub Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load t.Start() End Sub Private Sub doWork() 'code that interacts with x264 'p.StartInfo = ... 'p.Start() '... End Sub End Class |
1st September 2010, 17:53 | #17 | Link |
Registered User
Join Date: Aug 2010
Location: Hamilton, Ontario, Canada
Posts: 15
|
What ever I try in the formclosing, the form will never close. I try e.Cancel = False, Me.Close(), End but the form will never close. It will only close if I do not have the p.Kill() there. I also tried what said to do if not p.hasexited. I did not bother putting the thread part because I got it to work. I don't know why, I had this problem before that I could not get the form to close if I had anything else in the formclosing but the end or stuff like that. I even tried closing the form 3 first then closing the main form, but it will not close.
|
1st September 2010, 22:05 | #18 | Link | |
Registered User
Join Date: Sep 2008
Location: Birmingham (UK)
Posts: 69
|
I'm concerned that an attempt is being made to kill a process on which a subsequent thread may currently be working. Not necessarily wrong, but does ring alarm bells.
So the first step I'd take is to introduce two bools (there are better ways but this illustrates the process). Initially set bool's A and B to false. When you want to exit via form closing, you set A and then whilst B is false call System.Threading.Thread.Sleep(100). [Its good practice to include a timeout - say, try 10 times then give up and exit anyway - setting the thread's IsBackground to true is also a good idea as a backup plan) Meanwhile, inside the thread itself, after processing each line, check if A is set and if so stop reading the process (exit the "while" loop), dispose of the reader, and only then try and kill the process. Then, regardless of how you get to the end of the thread function, set B to true. This means that the process is terminated only after you stop trying to read it and is closed from within the thread that launched it (good practice if nothing else). Also there is no timing problems. for example Quote:
Another thing is that if I read correctly you are using some of form3's controls to supply parameters for the encoding process ? If so, note that Form3.Show() is modeless so returns immediately, so you'll only ever be using the default values of form3. Try Form3.ShowDialog(). Or, is Form3 showing the progress too? Anyhow, if you are still learning then trying to use threads may be a bit of a big learning curve. So, what you can do instead, is forget threads and maybe instead on your "encode" button run the inline code to launch process and read lines, but call DoEvents() for each line read as this will keep your UI updated (if a bit sluggish - depends on how frequently x264 outputs a new line of text). Don't get me wrong, Snowknight26's suggestion to use threads is absolutely the right design choice (DoEvents() is the spawn of Satan), however at this stage to just get something working give DoEvents() a whirl, you should also then not have any cross-thread issues to worry about. TTFN, Jon |
|
8th September 2010, 22:42 | #19 | Link |
Registered User
Join Date: Aug 2010
Location: Hamilton, Ontario, Canada
Posts: 15
|
Well I can't figure out a way to do it. I have another problem on not getting the stdout from mkvextract and ffmpeg. I have not tried mp4box yet though. I am using the same code as I did before with the dim s = sub() but I am not getting anything. Do you know the cause of this? Also, is there a way that I can take out subtitles with avisynth without cropping the video to a smaller clip?
|
10th September 2010, 11:16 | #20 | Link |
Registered User
Join Date: Sep 2008
Location: Birmingham (UK)
Posts: 69
|
Well, attached is an example of a form that launches a command line (ffmsindex.exe in this instance) and retrieves progress information which it uses to update a progress bar. It also implements a cancel.
For reasons of file size, I've omitted ffms2.dll and ffmsindex.exe which are part of the avisynth add-in for FfmpegSource, but hopefully you wont need to run the code to see how it works. (If you want to run the code then add them them to the project directory.) Example code to run the form :- Code:
var form = new OpenFileDialog(); form.RestoreDirectory = true; form.Filter = "Video file|*.avi;*.flv;*.mpg;*.vob;*.mp4|All Files|*.*"; if (form.ShowDialog() == DialogResult.OK) { var form2 = new Synthedit.FfmpegSource.FormFfmpegSourceImport(); form2.VideoFilename = form.FileName; MessageBox.Show(form2.ShowDialog().ToString(), "Result :", MessageBoxButtons.OK, MessageBoxIcon.None); } Code:
... proc.StartInfo.RedirectStandardError = false; proc.StartInfo.RedirectStandardOutput = true; ... ... using (StreamReader reader = proc.StandardOutput) or if you reverse the above true/false pair :- using (StreamReader reader = proc.StandardError) ... Hope this helps. TTFN, Jon PS : Ignore any bit where e.Result is set to something at the same time that e.Cancel is set to true. Micro$oft thought it a jolly good wheeze to make accessing e.Result impossible when a cancel occurs. Thanks Bill :-( |
Tags |
how to, programing, progress bar, visual basic 2010, x264 |
|
|