javaandroidffmpegjavacv

ProcessBuilder is not called when trying to start a process


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)

Solution

  • 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();
        }
        
    }