Java多线程: Passing camera frame to running worker thread

标签 java android multithreading ftp streaming

我正在使用 OpenCV4Android 并捕获相机帧,因此每次捕获帧时,都会调用方法 Mat onCameraFrame(CvCameraViewFrame inputFrame) 。在该方法中,我接收 Mat 对象 (mRgba) 中的帧。

单击按钮后,我开始将这些帧发送到连接的 FTP 服务器。当再次单击该按钮时,我停止发送帧。我需要将其放在单独的线程上,因为发送这些帧会导致大量 GUI 延迟。

我正在努力概念化和编码的是......能够有一个线程在单击按钮时启动和停止,并初始化并启动线程一次 - 启动时,从相机接收每个相机帧并推送该摄像机帧发送到 FTP 服务器。

目前我有这个:

public class FdActivity extends Activity implements CvCameraViewListener2 { 

    private FTPImage ftp;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //connect to FTP server
        ftp = new FTPImage();   

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                String ftpResult = ftp.connectToFTP(config.getFtpIP());
            }
        };
        new Thread(runnable).start();       
    }

    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
        mRgba = inputFrame.rgba();
        mGray = inputFrame.gray();

        if (isRecordFrames) {       
            Bitmap bmp;
            try {
                //convert Mat to Bitmap
                bmp = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888);         
                Utils.matToBitmap(mRgba, bmp);  
                //scale down Bitmap
                final Bitmap scaledBmp = Bitmap.createScaledBitmap(bmp, bmp.getWidth()/2, bmp.getHeight()/2, false);

                //issue - this is going to create a Runnable for each frame     
                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {
                        ftp.writeImageToFTP(scaledBmp);
                    }
                };
                new Thread(runnable).start();   
            }
            catch(Exception ex) {
                Log.i(TAG, "Exception onCameraFrame");
            }
        }   
        return mRgba;
    }
}

FTPImage 类:

public class FTPImage {

    private FTPClient ftpClient = null;

    public String connectToFTP(String ftpIP) {
        ftpClient = new FTPClient();
        String reply = "";

        try {
            ftpClient.connect(InetAddress.getByName(ftpIP));

            if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
                ftpClient.disconnect();
            }       
            ftpClient.enterLocalPassiveMode();          
            ftpClient.login("anonymous", "");       
            reply = ftpClient.getReplyString();         

        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                }
                catch (IOException ex)
                { }
            }
            e.printStackTrace();
        }
        return reply;
    }

    public void writeImageToFTP(Bitmap b) {
        if (ftpClient != null) {
            if (ftpClient.isConnected()) {
                try {
                    boolean res = ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

                    ByteArrayOutputStream stream = new ByteArrayOutputStream();         
                    b.compress(CompressFormat.PNG, 100, stream);

                    BufferedInputStream buffIn = new BufferedInputStream(
                            new ByteArrayInputStream(stream.toByteArray()));

                    res = ftpClient.storeFile("testImg.jpg", buffIn);
                    //when res returns, storeFile has finished uploading
                    String reply = ftpClient.getReplyString();

                    buffIn.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void disconnectFromFTP() {
        try {
            if (ftpClient.isConnected()) {
                ftpClient.logout(); 
                ftpClient.disconnect();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

如何将每个相机帧传递到一个单独的运行线程,然后将该帧发送到 FTP 服务器?

我希望这是有道理的......只是在线程部分遇到问题。预先感谢您!

最佳答案

我尝试在这里添加Thread UploadThread:

public class FdActivity extends Activity implements CvCameraViewListener2 { 

private FTPImage ftp;

// declaration
private UploadThread mUploadThread;
private Handler mUploadHandler;
public static int UPLOAD_IMAGE = 11;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
// initialization
mUploadThread = new UploadThread(this);
mUploadThread.start();
    //connect to FTP server
    ftp = new FTPImage();   

    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            String ftpResult = ftp.connectToFTP(config.getFtpIP());
        }
    };
    new Thread(runnable).start();       
}

public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
    mRgba = inputFrame.rgba();
    mGray = inputFrame.gray();

    if (isRecordFrames) {       
        Bitmap bmp;
        try {
            //convert Mat to Bitmap
            bmp = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888);         
            Utils.matToBitmap(mRgba, bmp);  
            //scale down Bitmap
            final Bitmap scaledBmp = Bitmap.createScaledBitmap(bmp, bmp.getWidth()/2, bmp.getHeight()/2, false);



    Message msg = Message.obtain();
    msg.what = UPLOAD_IMAGE;
    mUploadHandler.sendMessage(msg);    // this way we send message to upload thread queue
        }
        catch(Exception ex) {
            Log.i(TAG, "Exception onCameraFrame");
        }
    }   
    return mRgba;
}

Thread UploadThread = new Thread() {
    private Context;
    public UploadThread(Context context) {
        this.context = context;
    }
    @Override
    public void run() {
        Looper.prepare();
        mUploadHandler = new Handler() {
            public void handleMessage(msg) {
                case UPLOAD_IMAGE:
                ftp.writeImageToFTP(scaledBmp);     // uploading    
                break;              
            }
        }               


        Looper.loop();

        }
};

关于Java多线程: Passing camera frame to running worker thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29366839/

相关文章:

在应用程序 onCreate 中初始化类时出现 java.lang.NoClassDefFoundError

android - Android OpenGL ES 环境中的插值

java - 如何从 Callable 返回中期结果?

java - 如何在没有任何阻塞的情况下在 Java 8 中执行依赖任务

java - jetty 6 : Unknown Error 99

java - 如何为用户提供的国家名称预测正确的国家名称?

java - 创建android应用程序的多个副本

java - 矩形计算器应用程序

android - 在服务中调用 getIntent 方法

java - 如何将一个字符串元素与字符串元素数组进行比较?