ffmpeg won't start until java exits - java

I am trying to make a java program that automatically converts wtv files in an input folder to mpg files in output folder. The twist is that I make it run periodically, so it acts as a synchronizer.
The following code works for converting the .wtv to a .dvr-ms, which is required by ffmpeg since it cannot convert .wtv files directly.
Process p = Runtime.getRuntime().exec("C:\\Windows\\ehome\\WTVConverter C:\\Users\\Andrew\\Desktop\\test\\input\\input.wtv C:\\Users\\Andrew\\Desktop\\test\\output\\input.dvr-ms");
p.waitFor();
WTVConverter has no problems running from a java application. ffmpeg is a different story. Once the above line runs, I then run this...
Process p = Runtime.getRuntime().exec("ffmpeg\\bin\\ffmpeg -y -i \"C:\\Users\\Andrew\\Desktop\\test\\output\\input.dvr-ms'" -vcodec copy -acodec copy -f dvd \"C:\Users\Andrew\Desktop\test\output\input.mpg\"");
p.waitFor();
Suddenly, there is a problem... The application ffmpeg shows up in the task manager, but it's cpu usage is 0, and no mpeg files is being generated. If I force the java application to close, though, suddenly it starts working! Huh?
What reason would there be for a command line application to wait for its calling application to quit before it executes? I'm not incredibly command line savvy, so I don't really know how to diagnose this problem.

Bah, this always happens. I post a question, and THEN I figure it out on my own. Turns out, ffmpeg expects you to read in its text output before it loads each frame. If a calling program does not do this, it simply waits. If there is no calling program, I assume that it just outputs it nowhere. What I did is ran the program as usual, but also read in text from the process's input stream like so...
Process p = Runtime.getRuntime.exec(".....");
final Scanner in = new Scanner(p.getInputStream());
new Thread()
{
#Override
public void run()
{
System.out.println(in.nextLine());
}
}.start();
Lesson learned, I guess.

Related

Process launched from Java code doesn't return

This is my code :
Process p1;
try {
p1 = Runtime.getRuntime().exec( "utils/a.out < utils/test_c2.txt > utils/result.txt" );
p1.waitFor();
} catch ( Exception e ) {
System.out.println("Something went bad!");
}
I've read that there should be a problem with the input buffer size, but in this case, all the output from the launched process is redirected to " utils/result.txt", so the launched process should not reach deadlock. When I run the same command from terminal it works. Maybe it would be helpful to describe what is "a.out". I obtained it from a flex file as follows:
$ flex rulex.lex
$ gcc lex.yy.c -lfl
Any help would be appreciated.
The subprocess is waiting to read data on stdin. Java does not launch the subprocess within a shell, so no pipes are available. You need to make your subprogram take files as arguments and open the files itself. Another option is to start a shell (like bash) and tell it to run the program, then the piping of files will work.

Sending commands to a background executable via Java ProcessBuilder in MATLAB

I am using Java ProcessBuilder in MATLAB to open an executable in the background. This executable does some automated tasks, then pauses, waiting for user to type in some text and press enter.
I am able to send "enter key" commands to the executable via ProcessBuilder, but I am unable to send text strings. Can someone help me in this? Here is my code so far that initiates the executable in the background:
% specify the executable to run
run_exe_file = {'my_executable_program.exe'};
% initialize the java ProcessBuilder, run the executable
processBuilder = java.lang.ProcessBuilder(run_exe_file);
myProcess = processBuilder.start();
% initialize the reader. notice the myProcess in myProcess.getInputStream
reader = ...
java.io.BufferedReader(...
java.io.InputStreamReader(...
myProcess.getInputStream() ...
) ...
);
% initialize the writer. notice the myProcess in myProcess.getOutputStream
writer = ...
java.io.BufferedWriter(...
java.io.OutputStreamWriter(...
myProcess.getOutputStream() ...
) ...
);
After running the code above, 'my_executable_program.exe' starts running in the background successfully. After the background program run some tasks, it waits for user input. If for example I want to send an "enter key" press to the program I type in MATLAB the following:
writer.newLine; writer.flush; reader.readLine;
Which successfully sends the enter key command. However if I want to send some text to the program, from my understanding I am supposed to use the following code:
writer.write("Here is some text I'm sending to the program"); writer.flush; reader.readLine;
However running the above code does not send the text string to the program in my testing. Can someone help me with what is the proper syntax to send the text?
Thank you

give buffered input to runtime exec in java

This is my code for run a java file in other java application but i dont knoow what to do if the program takes only bufferedinputs ??
try {
Runtime rt = Runtime.getRuntime();
// compile the java file
Process pr = rt.exec("javac Main.java");
pr.waitFor();
// run the java file
pr = rt.exec("java Main " + inputs.toString()); // using this i can give command line arguments
pr.waitFor();
}
This is my code i can give command line arguments at run time but what if i want to give bufferedinput to the program ?
Thanks in advance
You state:
This is my code for run a java file in other java application but i dont knoow what to do if the program takes only bufferedinputs ??
To attach to another processes input and output streams, look at the API for the Process class where you'll find and use the getErrorStream(), getInputStream() and getOutputStream() methods. You can then wrap your Input and Output and Error Streams in their respective Buffered Streams.
Note however that you should be wary of common pitfalls which are well explained in the slightly dated article, When Runtime Exec Won't
Having said this, you're far better off using the Java classes themsevels rather than running it in another JVM. Is there a reason that you can't do this? And what do you mean by "buffered" input?

How to create a process which can execute concurrently with respect to java process [duplicate]

I am working on a program written in Java which, for some actions, launches external programs using user-configured command lines. Currently it uses Runtime.exec() and does not retain the Process reference (the launched programs are either a text editor or archive utility, so no need for the system in/out/err streams).
There is a minor problem with this though, in that when the Java program exits, it doesn't really quit until all the launched programs are exited.
I would greatly prefer it if the launched programs were completely independent of the JVM which launched them.
The target operating system is multiple, with Windows, Linux and Mac being the minimum, but any GUI system with a JVM is really what is desired (hence the user configurability of the actual command lines).
Does anyone know how to make the launched program execute completely independently of the JVM?
Edit in response to a comment
The launch code is as follows. The code may launch an editor positioned at a specific line and column, or it may launch an archive viewer. Quoted values in the configured command line are treated as ECMA-262 encoded, and are decoded and the quotes stripped to form the desired exec parameter.
The launch occurs on the EDT.
static Throwable launch(String cmd, File fil, int lin, int col) throws Throwable {
String frs[][]={
{ "$FILE$" ,fil.getAbsolutePath().replace('\\','/') },
{ "$LINE$" ,(lin>0 ? Integer.toString(lin) : "") },
{ "$COLUMN$",(col>0 ? Integer.toString(col) : "") },
};
String[] arr; // array of parsed tokens (exec(cmd) does not handle quoted values)
cmd=TextUtil.replace(cmd,frs,true,"$$","$");
arr=(String[])ArrayUtil.removeNulls(TextUtil.stringComponents(cmd,' ',-1,true,true,true));
for(int xa=0; xa<arr.length; xa++) {
if(TextUtil.isQuoted(arr[xa],true)) {
arr[xa]=TextDecode.ecma262(TextUtil.stripQuotes(arr[xa]));
}
}
log.println("Launching: "+cmd);
Runtime.getRuntime().exec(arr);
return null;
}
This appears to be happening only when the program is launched from my IDE. I am closing this question since the problem exists only in my development environment; it is not a problem in production. From the test program in one of the answers, and further testing I have conducted I am satisfied that it is not a problem that will be seen by any user of the program on any platform.
There is a parent child relation between your processes and you have to break that.
For Windows you can try:
Runtime.getRuntime().exec("cmd /c start editor.exe");
For Linux the process seem to run detached anyway, no nohup necessary.
I tried it with gvim, midori and acroread.
import java.io.IOException;
public class Exec {
public static void main(String[] args) {
try {
Runtime.getRuntime().exec("/usr/bin/acroread");
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Finished");
}
}
I think it is not possible to to it with Runtime.exec in a platform independent way.
for POSIX-Compatible system:
Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "your command"}).waitFor();
I have some observations that may help other people facing similar issue.
When you use Runtime.getRuntime().exec() and then you ignore the java.lang.Process handle you get back (like in the code from original poster), there is a chance that the launched process may hang.
I have faced this issue in Windows environment and traced the problem to the stdout and stderr streams. If the launched application is writing to these streams, and the buffer for these stream fills up then the launched application may appear to hang when it tries to write to the streams. The solutions are:
Capture the Process handle and empty out the streams continually - but if you want to terminate the java application right after launching the process then this is not a feasible solution
Execute the process call as cmd /c <<process>> (this is only for Windows environment).
Suffix the process command and redirect the stdout and stderr streams to nul using 'command > nul 2>&1'
It may help if you post a test section of minimal code needed to reproduce the problem. I tested the following code on Windows and a Linux system.
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws Exception {
Runtime.getRuntime().exec(args[0]);
}
}
And tested with the following on Linux:
java -jar JustForTesting.jar /home/monceaux/Desktop/__TMP/test.sh
where test.sh looks like:
#!/bin/bash
ping -i 20 localhost
as well as this on Linux:
java -jar JustForTesting.jar gedit
And tested this on Windows:
java -jar JustForTesting.jar notepad.exe
All of these launched their intended programs, but the Java application had no problems exiting. I have the following versions of Sun's JVM as reported by java -version :
Windows: 1.6.0_13-b03
Linux: 1.6.0_10-b33
I have not had a chance to test on my Mac yet. Perhaps there is some interaction occuring with other code in your project that may not be clear. You may want to try this test app and see what the results are.
You want to launch the program in the background, and separate it from the parent. I'd consider nohup(1).
I suspect this would require a actual process fork. Basically, the C equivalent of what you want is:
pid_t id = fork();
if(id == 0)
system(command_line);
The problem is you can't do a fork() in pure Java. What I would do is:
Thread t = new Thread(new Runnable()
{
public void run()
{
try
{
Runtime.getRuntime().exec(command);
}
catch(IOException e)
{
// Handle error.
e.printStackTrace();
}
}
});
t.start();
That way the JVM still won't exit, but no GUI and only a limited memory footprint will remain.
I tried everything mentioned here but without success. Main parent Java process can't quit until the quit of subthread even with cmd /c start and redirecting streams tu nul.
Only one reliable solution for me is this:
try {
Runtime.getRuntime().exec("psexec -i cmd /c start cmd.cmd");
}
catch (Exception e) {
// handle it
}
I know that this is not clear, but this small utility from SysInternals is very helpful and proven. Here is the link.
One way I can think of is to use Runtime.addShutdownHook to register a thread that kills off all the processes (you'd need to retain the process objects somewhere of course).
The shutdown hook is only called when the JVM exits so it should work fine.
A little bit of a hack but effective.

cmd java wait for process

I'm writing an application with a Java GUI which calls some FORTRAN code. I want to return a file (solution.ps) which is updated and compiled based on changes in the FORTRAN code, which are created earlier in my ActionPerformed method. However the code I have at present just returns the old version of the file rather than waiting for the updated results of the cmd compilation. Is there a way to make the cmd wait for the process to run before completing the next step? (It works fine running directly from cmd)
I've searched but can't find anything except process.waitFor() which won't seem to pause the execution at the right point. Tried Thread.waitFor() too.
I'm thinking this could be useful for anyone who wants to send user inputs to another program and return a compiled result which uses these inputs.
Anyway here is the code, thanks in advance for any help and I hope I made the problem clear.
String[] command ={"cmd",};
try {
Process p = Runtime.getRuntime().exec(command);
new Thread(new SyncPipe(p.getErrorStream(), System.err)).start();
new Thread(new SyncPipe(p.getInputStream(), System.out)).start();
PrintWriter stdin = new PrintWriter(p.getOutputStream());
stdin.println("cd c:\\g77");
stdin.println("g77setup.bat");
stdin.println("cd c:\\users\\laurence\\workspace\\areaplanner");
stdin.println("g77 -O4 genpack.f -o genpack");
stdin.println("genpack");
stdin.println("5");
/*
* The following line sets the time to run the FORTRAN code for
* - need to wait for this to complete before calling mpost
*/
stdin.println("30");
stdin.println("mpost solution.mp");
stdin.println("latex solution.tex");
stdin.println("dvips solution.dvi -o solution.ps");
stdin.close();
} catch(IOException e4){}
You are only runnng the windows shell command. To fix, suggest writing the batch file first and wait for it to finish:
String command = "cmd /c mybatchfile.bat";
Process p = Runtime.getRuntime().exec(command);
p.waitFor();
To get another section to kick off before the the first set of commands have completed, you will have to write another batch file and repeat the above. Make sure you have both process then in separate threads.
Try using waitFor so as to make the current thread wait for the process to finish its job.
Process p = Runtime.getRuntime().exec(command);
p.waitFor()
The command in your code is incomplete. And also it is advisable to use a ProcessBuilder.start() instead of Process.

Categories