I am trying to understand more about the ffmpeg usage in JavaCV for android studio and for said task I am trying to use ProcessBuilder. I tried writting a simple program to debug the pb.start();
Although, I am not getting a response. What I did was to start a default/empty activity and pasted the following program:
package com.example.myapplication;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import org.bytedeco.javacpp.Loader;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
static final int cols = 192;
static final int rows = 108;
static final String ffmpeg = Loader.load(org.bytedeco.ffmpeg.ffmpeg.class);
static final String rtmp_url = "test.flv";
static final String[] command = {ffmpeg,
"-y",
"-f", "rawvideo",
"-vcodec", "rawvideo",
"-pix_fmt", "bgr24",
"-s", (Integer.toString(cols) + "x" + Integer.toString(rows)),
"-r", "10",
"-i", "pipe:",
"-c:v", "libx264",
"-pix_fmt", "yuv420p",
"-preset", "ultrafast",
"-f", "flv",
rtmp_url};
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(t1).start();
}
private static Runnable t1 = () -> {
Log.e("TAG", "void OnCreate called successfully!");
ProcessBuilder pb = new ProcessBuilder(command).redirectErrorStream(true);
pb.redirectErrorStream(true);
try {
Process process = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
OutputStream writer = process.getOutputStream();
Log.e("TAG", "Something good happened here");
} catch (IOException e) {
e.printStackTrace();
Log.e("TAG", "Nothing good happened here");
}
};
}
My current problem is that I can't seem to start properly the processBuilder process via pb.start();
I get the following logs from the logcat panel:
2022-06-14 17:24:46.328 13371-13371/com.example.myapplication E/TAG: void OnCreate called successfully!
2022-06-14 17:24:46.333 13371-13371/com.example.myapplication E/TAG: Nothing good happened here
I'd like to understand why is it skipping the try/catch block and not starting the process?
EDIT: I made some changes as per @g00se's suggestions and I got the following stack trace from the code above:
2022-06-15 00:32:26.700 29787-29787/? E/USNET: USNET: appName: com.example.myapplication
2022-06-15 00:32:29.328 29787-29828/com.example.myapplication E/TAG: void OnCreate called successfully!
2022-06-15 00:32:29.330 29787-29828/com.example.myapplication E/AndroidRuntime: FATAL EXCEPTION: Thread-4
Process: com.example.myapplication, PID: 29787
java.lang.NullPointerException
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1012)
at com.example.myapplication.MainActivity.lambda$static$0(MainActivity.java:48)
at com.example.myapplication.MainActivity$$ExternalSyntheticLambda0.run(Unknown Source:0)
at java.lang.Thread.run(Thread.java:920)
A thread isn't necessary, nor reading the output to start a process, in this case errCode = process.waitFor();
did the trick.
package com.example.myapplication;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import org.bytedeco.javacpp.Loader;
import org.bytedeco.opencv.opencv_core.Point;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;
import org.opencv.imgproc.Imgproc;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
static final int cols = 192;
static final int rows = 108;
static final String ffmpeg = Loader.load(org.bytedeco.ffmpeg.ffmpeg.class);
static final String rtmp_url = "test.flv";
static final String[] command = {ffmpeg,
"-y",
"-f", "rawvideo",
"-vcodec", "rawvideo",
"-pix_fmt", "bgr24",
"-s", (Integer.toString(cols) + "x" + Integer.toString(rows)),
"-r", "10",
"-i", "pipe:",
"-c:v", "libx264",
"-pix_fmt", "yuv420p",
"-preset", "ultrafast",
"-f", "flv",
rtmp_url};
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//new Thread(t1).start();
ProcessBuilder pb = new ProcessBuilder("echo", "Hello World!");
pb.redirectErrorStream(true);
System.out.println("Run echo command");
Process process = null;
try {
process = pb.start();
} catch (IOException e) {
e.printStackTrace();
}
int errCode = 0;
try {
errCode = process.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Echo command executed, any errors? " + (errCode == 0 ? "No" : "Yes"));
try {
System.out.println("Echo Output:\n" + output(process.getInputStream()));
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
OutputStream writer = process.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
Log.e("TAG", "void OnCreate called successfully!");
}
private static String output(InputStream inputStream) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(inputStream));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line + System.getProperty("line.separator"));
}
} finally {
br.close();
}
return sb.toString();
}
}