2012-03-01 67 views
0

我想問一個問題,我想提高我的幀速率。我正在從使用預覽呼叫的Android設備發送緩衝區。我比在服務器端收到它。我很好。幀速率非常慢。你能指導我嗎?我做了YUV,在Android JPEG轉換過,工作正常,但它使得它非常緩慢Android Preveiw幀速率查詢

感謝

問候

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. 必須調用com.android的getSupportedPreviewFpsRange()。 hardware.Camera,您將獲得支持的FPS範圍列表
  2. 選擇正確的一個並調用setSupportedPreviewFpsRange()
  3. 所有必須的b e在startPreview()調用之前調用。

你可以參考SDK指南。