Android Preveiw Frame Rate Query - PullRequest
       1

Android Preveiw Frame Rate Query

0 голосов
/ 01 марта 2012

Я хочу задать вопрос, который хочу улучшить частоту кадров. Я отправляю с устройства Android, которое использует предварительный вызов с буфером. Я получаю его на стороне сервера. У меня все хорошо. Частота кадров ужасно медленная. Можете ли вы направить меня. Я делаю преобразование YUV в JPEG на Android тоже, работает нормально, но делает его ужасно медленным

Спасибо

Привет

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.hardware.Camera;
import android.hardware.Camera.ErrorCallback;
import android.hardware.Camera.Size;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.Camera.PreviewCallback;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.Toast;
import android.app.Service;
import android.graphics.ImageFormat;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.net.Uri;
import android.os.IBinder;
import android.provider.MediaStore;
import android.view.LayoutInflater;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.net.InetAddress;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.List;

import android.widget.TextView;

public class SdfJuliaActivity extends Activity implements SensorEventListener
{
    private static String TAG = "SDFJulia";

    /*
     * WiFi Methods
     * ------------
     * Please do not delete any method, just adjust them if necessary.
     * 
     * Problems:
     * - if server is not available / running and app tries to connect,
     *      it crashes the emulator. Works fine on smartphone, though.
     * 
     */

    protected static  DataOutputStream os;
    protected static Socket socket;
    private static String address = "192.168.2.102:4444";           //also default IP address
    private static String ipAddress;
    private static int port;

    //Connect to given ip address on given port
    protected static boolean connect(String serverName, int port)
    {
        Log.d(TAG, "Connecting to " + serverName + ":" + port);

        try
        {
            socket = new Socket(serverName,port);       
            os = new DataOutputStream(socket.getOutputStream());
        }
        catch (UnknownHostException e)
        {
            Log.d(TAG, "Unknown Host Exception while connecting: " + e);
            return false;
        }
        catch (IOException e)
        {
            Log.d(TAG, "IO Exception while connecting: " + e);
            return false;
        }

        if (!socket.isConnected()) { return false; }

        return true;
    }

    //Close the current connection
    protected static void disconnect()
    {   
        if (!socket.isClosed())
        {
            try { socket.close(); }
            catch (IOException e) {}
        }
    }

    //Check if we are connected
    protected static boolean connected()
    {
        //Check if socket is open
        if (socket.isClosed())
        {   return false;   }

        //Check if socket is actually connected to a remote host
        if (!socket.isConnected())
        {   return false;   }

        //We are connected!
        return true;
    }

    //Send a single frame to the server
    //YUV-Image
    protected static void sendFrame(byte[] data)
    {   
        //Check if a frame is actually available
        if (data != null)
        {
            try
            {       
                os.writeInt(data.length);
                os.write(data, 0, data.length);         
                os.flush();
            }
            catch (IOException e) {};
        }
    }

    //Send all sensor data to the server
    protected static void sendData()
    {
        try
        {
            os.writeFloat(orientation_x);
            os.writeFloat(orientation_y);
            os.writeFloat(orientation_z);
            os.writeDouble(gps_longitude);
            os.writeDouble(gps_latitude);
            os.writeDouble(gps_altitude);
        }
        catch (IOException e) {};
    }

    public static String getAddress()
    {   return address; };

    /*
     * Sensor Stuff
     * ------------
     */

    SensorManager sensorManager = null;
    private static float accelerometer_x;
    private static float accelerometer_y;
    private static float accelerometer_z;

    private static float orientation_x;
    private static float orientation_y;
    private static float orientation_z; 


    //New sensor data available
    public void onSensorChanged(SensorEvent event)
    {
        synchronized (this)
        {
            switch (event.sensor.getType())
            {
                case Sensor.TYPE_ACCELEROMETER:
                    accelerometer_x = event.values[0];
                    accelerometer_y = event.values[1];
                    accelerometer_z = event.values[2];
                    break;

                case Sensor.TYPE_ORIENTATION:
                    orientation_x = event.values[0];
                    orientation_y = event.values[1];
                    orientation_z = event.values[2];
                    break;                  
            }
        }
    }

    //Sensor accuracy has changed (unused)
    public void onAccuracyChanged(Sensor sensor, int accuracy) {}

    private static double gps_latitude;
    private static double gps_longitude;
    private static double gps_altitude;
    private static long gps_lastfix;

    /*
     * Camera Methods
     * --------------
     * 
     */

    private Camera mCamera;
    SurfaceView mPreview;

    private void startVideo()
    {
        SurfaceHolder videoCaptureViewHolder = null;

        try { mCamera = Camera.open(); }
        catch (Exception e) { Log.d(TAG,"Can not open camera. In use?"); };

        mCamera.setErrorCallback
        (
            new ErrorCallback()
            {   public void onError(int error, Camera camera) {}    }
        );

        Camera.Parameters parameters = mCamera.getParameters();

        final int previewWidth = parameters.getPreviewSize().width;
        final int previewHeight = parameters.getPreviewSize().height;

        parameters.setPreviewFrameRate(30);
        mCamera.setParameters(parameters);

        parameters = mCamera.getParameters();
        Log.d(TAG,"Format: " + parameters.getPreviewFormat());
        Log.d(TAG,"FPS: " + parameters.getPreviewFrameRate());        

        if (null != mPreview)
        {   videoCaptureViewHolder = mPreview.getHolder();  }


        try { mCamera.setPreviewDisplay(videoCaptureViewHolder); }
        catch (Throwable t) {}

        //Get Preview Size to set the data buffers to it 
        Size previewSize=mCamera.getParameters().getPreviewSize();
        //Set the Buffer Size according to Preview Size
        int dataBufferSize=(int)(previewSize.height*previewSize.width*
                               (ImageFormat.getBitsPerPixel(mCamera.getParameters().getPreviewFormat())/8.0));

        mCamera.addCallbackBuffer(new byte[dataBufferSize]);
        mCamera.addCallbackBuffer(new byte[dataBufferSize]);
        mCamera.addCallbackBuffer(new byte[dataBufferSize]);
        //This method is called for every preview frame
        //we use it to transmit both the current preview frame as well as the sensor data
        mCamera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback()
        {
            int fpsCount = 0;
            boolean test = true;


            public void onPreviewFrame(byte[] data, Camera camera)
            {
                //Check if connection is present; if not, try to reconnect
                if (!connected())
                {   connect(ipAddress, port);   }
                else
                {
                    //Prediction step XXX

                    //Log.d(TAG, "Transmitting data.");

                    //Convert image to YUV
                    /*YuvImage image = new YuvImage(data,ImageFormat.NV21,previewWidth,previewHeight,null);
                    Rect rect = new Rect(0,0,previewWidth,previewHeight);
                    ByteArrayOutputStream oas = new ByteArrayOutputStream();
                    image.compressToJpeg(rect,100,oas);
                    byte[] imageJPG = oas.toByteArray();*/

                    //if (test)
                    //{ Log.d(TAG,"Length: " + imageJPG.length);    test = false;   };

                    //Send the current frame to the server
                    sendFrame(data);

                    //Send the corresponding sensor data to the server
                    sendData();

                    camera.addCallbackBuffer(data);

                }
            }
        });

        try { mCamera.startPreview(); }
        catch (Throwable e)
        {
            mCamera.release();
            mCamera = null;
            return;
        }
    }

    private void stopVideo() 
    {
        if (mCamera == null)
        { return; }

        try
        {
            mCamera.stopPreview();
            mCamera.setPreviewDisplay(null);
            mCamera.setPreviewCallback(null);
            mCamera.release();
        }
        catch (IOException e)
        {
            e.printStackTrace();
            return;
        }

        mCamera = null;
    }   

    /* Input Validation
     * ----------------
     */

    //Check if user specified address is valid 
    private static boolean checkAddress(String userinput)
    {
        String [] part = userinput.split("\\:");

        if (part.length != 2)
        {   return false;   }

        if (!validIP(part[0]))
        {   return false;   }

        int i = Integer.parseInt(part[1]);
        if (i < 1 || i > 10000)
        {   return false;   }

        return true;
    }

    //Check for valid IP address
    private static boolean validIP (String userinput)
    {
        String [] part = userinput.split("\\.");

        if (part.length != 4)
        {
            Log.d(TAG,"Invalid ip address length.");
            return false;
        }

        for (String s : part)
        {
            int i = Integer.parseInt(s);
            if (i < 0 || i > 255)
            {   
                Log.d(TAG,"Invalid ip address values.");
                return false;
            }
        }

        return true;
    }    

    /*
     * Activity Creation
     * -----------------
     */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        //Always use portrait view
        //Otherwise activity gets destroyed when orientation is changed --> network & video stream is lost
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        setContentView(R.layout.main);        

        socket = new Socket();

        /*
         * Sensors
         * -------
         * This registers our app to receive the latest sensor data.
         */            

        sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);       
        sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), sensorManager.SENSOR_DELAY_FASTEST);
        sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), sensorManager.SENSOR_DELAY_FASTEST);

        /*
         * GPS
         * ---
         * This registers our app to receive the latest GPS data.
         */        

        LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        LocationListener locationListener = new LocationListener()
        {
            public void onLocationChanged(Location location)
            {
                gps_latitude = location.getLatitude();
                gps_longitude = location.getLongitude();
                gps_altitude = location.getAltitude();
                gps_lastfix = System.currentTimeMillis();
            }

            public void onStatusChanged(String provider, int status, Bundle extras) {}
            public void onProviderEnabled(String provider) {}
            public void onProviderDisabled(String provider) {}
        };

        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);        

        final Button serviceButton = (Button) findViewById(R.id.btn_serviceButton);
        final EditText ipText = (EditText) findViewById(R.id.text_ipAddress);
        ipText.setText(address);

        //CameraStuff here first
        mPreview = (SurfaceView) findViewById(R.id.cameraView);

        SurfaceHolder videoCaptureViewHolder = mPreview.getHolder();
        videoCaptureViewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        videoCaptureViewHolder.addCallback(new Callback()
        {
            public void surfaceDestroyed(SurfaceHolder holder) { stopVideo(); }
            public void surfaceCreated(SurfaceHolder holder) {}
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
        });

        //Click Listener for Button
        //starts & stops the service
        serviceButton.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(View v)
            {
                if (connected())
                {
                    Toast.makeText(getApplicationContext(), "Connection terminated.", Toast.LENGTH_SHORT).show();
                    serviceButton.setText("Connect");

                    //Stop the app
                    stopVideo();                //Stop video & sending data
                    disconnect();               //Stop network services
                }
                else
                {
                    address = ipText.getText().toString();
                    String [] part = ipText.getText().toString().split("\\:");

                    //Validate input
                    ipAddress = part[0];
                    port = Integer.parseInt(part[1]);
                    //int port = 4444;

                    if (!checkAddress(address))
                    {
                        //Invalid ip address specified
                        Toast.makeText(getApplicationContext(), "Invalid address specified.", Toast.LENGTH_SHORT).show();
                        Log.d(TAG,"Invalid address specified.");                
                    }
                    else
                    {
                        if (!connect(ipAddress, port))
                        {
                            //Connection failed
                            Toast.makeText(getApplicationContext(), "Could not connect.", Toast.LENGTH_SHORT).show();
                            Log.d(TAG,"Could not connect.");
                        }
                        else
                        {
                            //Connection successful
                            Log.d(TAG,"Connected.");
                            Toast.makeText(getApplicationContext(), "Connection successful.", Toast.LENGTH_SHORT).show();
                            serviceButton.setText("Disconnect");

                            //Start video & sending data
                            startVideo();
                        }
                    }
                }
            }
        });
    }

    //Don't do anything if configuration is changed (e.g. phone has been rotated)
    @Override
    public void onConfigurationChanged(Configuration newConfig) {}
}

1 Ответ

1 голос
/ 08 марта 2012
  1. Вы должны вызвать getSupportedPreviewFpsRange () com.android.hardware.Camera, и вы получите список поддерживаемых диапазонов FPS
  2. Выберите правильный и вызовите setSupportedPreviewFpsRange ()
  3. все, что должно быть вызвано перед вызовом startPreview ().

Вы можете обратиться к руководству по SDK.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...