2011-07-14 7 views
0

私は、JPEG画像のストリーム(MJPEGストリーム)をリモートPCに送信するアプリケーションを開発中です。カメラパラメータのプレビューフレームレートを変更するのに問題があります。どんなレートを設定しても、カメラは私に15fpsのフレームしか与えないようです。最初は、画像の圧縮とデータの送信が原因だと思っていました。しかし、最初に圧縮されたJPEGイメージを格納し、onPreviewFrame関数が呼び出されるたびにそのイメージを送信するデバッグインスタンスを作成しました。信頼できる15fpsが得られますが、30fpsに設定しました。誰もがなぜfpsが矛盾しているのかというアイデアはありますか?すべてのプレビューフレームを圧縮してwifiを送信するように設定すると、5〜40FPSのレートが得られ、すべての場所でジャンプします。ここでMotorola Atrix不整合プレビューフレーム

public class Preview extends SurfaceView implements PreviewCallback, SurfaceHolder.Callback { 
SurfaceHolder mHolder; 
Camera mCamera; 
DatagramSocket udpSocket = null; 
final int PORT = 1235; 
final String IPAddress = "192.168.1.101"; 
int packetSize = 1024; // Specify max size of each UDP packet 
int WIDTH = 640; 
int HEIGHT = 480; 
int FPS = 30;  
int quality = 70; 
/** 
* Initialize the Camera Preview Holder and create a udpSocket. 
* @param context 
*/ 
Preview(Context context) { 
    super(context); 
    mHolder = getHolder(); 
    mHolder.addCallback(this); 
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    try { 
     udpSocket = new DatagramSocket(); 
    } catch (SocketException e) { 
     Log.e(tag, "Error creating UDP Socket!"); 
    } 
} 
public void surfaceCreated(SurfaceHolder holder) { 
    mCamera = Camera.open(); 
    try { 
     mCamera.setPreviewDisplay(holder); 
    } catch (IOException exception) { 
     mCamera.release(); 
     mCamera = null; 
     Log.e(tag, "Error settign Camera Preview Holder!"); 
    } 
} 
public void surfaceDestroyed(SurfaceHolder holder) { 
    mCamera.setPreviewCallback(null); 
    mCamera.stopPreview(); 
    udpSocket.close(); 
    mCamera.release(); 
    udpSocket = null; 
    mCamera = null; 
} 
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
    Camera.Parameters parameters = mCamera.getParameters(); 
    parameters.setPreviewSize(WIDTH, HEIGHT); 
    parameters.setPreviewFrameRate(FPS); 
    parameters.setRotation(90); 

    mCamera.setParameters(parameters); 
    mCamera.setPreviewCallback(this); 
    mCamera.startPreview(); 
} 
/** Compresses the preview framer (data) into a JPEG image and send to a host at 
* the specified IPAddress and Port number for playback. Only sends frame if sendFrame 
* is true. 
* (non-Javadoc) 
* @see android.hardware.Camera.PreviewCallback#onPreviewFrame(byte[], android.hardware.Camera) 
* @see android.hardware.Camera 
*/ 
public void onPreviewFrame(byte[] data, Camera camera) { 
    final YuvImage imgPreview = new YuvImage(data, ImageFormat.NV21, WIDTH, HEIGHT, null); 
    byte[] buffer; 
    ByteArrayOutputStream jpegOutStream = new ByteArrayOutputStream(); 

    int offset = 0; 
    int TotalLength, lengthLeft; 
    DatagramPacket dgpout; 
    // Compress image into JPEG 
    imgPreview.compressToJpeg(new Rect(0, 0, imgPreview.getWidth(), imgPreview.getHeight()), quality, jpegOutStream); 
    buffer = jpegOutStream.toByteArray(); 
    TotalLength = lengthLeft = buffer.length; 
    // Send frame out. Split into packets of desired length. 
    try { 
     while(lengthLeft>packetSize){ 
      dgpout= new DatagramPacket(buffer, offset, packetSize); 
      offset+=packetSize; 
      lengthLeft-=packetSize; 
      dgpout.setAddress(InetAddress.getByName(IPAddress)); 
      dgpout.setPort(PORT); 
      udpSocket.send(dgpout); 
     } 
     if(lengthLeft>0){ 
      dgpout= new DatagramPacket(buffer,offset,lengthLeft); 
      offset+=lengthLeft; 
      lengthLeft-=lengthLeft; 
      dgpout.setAddress(InetAddress.getByName(IPAddress)); 
      dgpout.setPort(PORT); 
      udpSocket.send(dgpout); 
     } 
     Log.i(tag, "Sent Successfully: frame size="+TotalLength +"Buffer Size: "+udpSocket.getSendBufferSize()); 
    } catch (UnknownHostException e1) { 
     Log.e(tag , "UnknownHostException. Sending failed."); 
    } catch (IOException e) { 
     Log.e(tag , "IOException. Sending failed."); 
    } 
} 

}

そして、ここで私のデバッグサンプルのみを越えて

上で同じJPEGを送信するためである(フルスクリーンでカメラを設定します)私のプレビューのための私のコードであります
if(sendFrame){ 
     sendFrame = false; 
     final YuvImage imgPreview = new YuvImage(data, ImageFormat.NV21, WIDTH, HEIGHT, null); 

     fixImage = data; 
       byte[] buffer; 
       ByteArrayOutputStream jpegOutStream = new ByteArrayOutputStream(); 

       int offset = 0; 
       int TotalLength, lengthLeft; 
       DatagramPacket dgpout; 
       // Compress image into JPEG 
       imgPreview.compressToJpeg(new Rect(0, 0, imgPreview.getWidth(), imgPreview.getHeight()), quality, jpegOutStream); 
       buffer = jpegOutStream.toByteArray(); 

       fixJPEG = buffer; 
       fixTotalLength = buffer.length; 

    } 
    int lengthLeft = 0; 
    int offset = 0; 
    DatagramPacket dgpout; 
    if(fixImage==null || fixJPEG==null) 
     return; 
    /* Compress Optional */ 
    if(true){ 
     final YuvImage imgPreview = new YuvImage(fixImage, ImageFormat.NV21, WIDTH, HEIGHT, null); 
     ByteArrayOutputStream jpegOutStream = new ByteArrayOutputStream(); 
     imgPreview.compressToJpeg(new Rect(0, 0, imgPreview.getWidth(), imgPreview.getHeight()), quality, jpegOutStream); 
     fixJPEG = jpegOutStream.toByteArray(); 
    } 
    fixTotalLength = lengthLeft = fixJPEG.length; 
    // Send frame out. Split into packets of desired length. 
    try { 
     while(lengthLeft>packetSize){ 
      dgpout= new DatagramPacket(fixJPEG, offset, packetSize); 
      offset+=packetSize; 
      lengthLeft-=packetSize; 
      dgpout.setAddress(InetAddress.getByName(IPAddress)); 
      dgpout.setPort(PORT); 
      udpSocket.send(dgpout); 
     } 
     if(lengthLeft>0){ 
     dgpout= new DatagramPacket(fixJPEG,offset,lengthLeft); 
      offset+=lengthLeft; 
      lengthLeft-=lengthLeft; 
      dgpout.setAddress(InetAddress.getByName(IPAddress)); 
      dgpout.setPort(PORT); 
      udpSocket.send(dgpout); 
     } 
     Log.i(tag, "Sent Successfully: frame size="+fixTotalLength +"Buffer Size: "+udpSocket.getSendBufferSize()); 
    } catch (UnknownHostException e1) { 
     Log.e(tag , "UnknownHostException. Sending failed."); 
    } catch (IOException e) { 
     Log.e(tag , "IOException. Sending failed."); 
    } 

効率を改善するためのアイデアはありますか?これはすべてのデバイスで発生しますか?私はAndroid 2.2を実行しています。任意のアイデアが評価されます。

* EDITを追加しました全体プレビュークラス

+0

カメラの設定に使用しているコードを投稿することはできますか? – mportuesisf

+0

@mportuesisf要求された情報を含むPreviewクラス全体を投稿しました。レスポンスありがとう。 –

答えて

2

それはATRIXはかなり可能です(合法的に)あなたの要求を無視して、プレビューフレームレートを変更します。あなたのsurfaceChangedコールバックで

は、以下のデバッガで値を検査起動してみてください:

List<Integer> rates = parameters.getSupportedPreviewFrameRates(); 

Androidのドキュメントは言う:

は、サポートされているプレビューフレームレートのリストを返します。プレビューフレーム レート設定がサポートされていない場合はnull。

また、setPreviewFrameRate()のための文書は言う:

これは、ターゲットフレームレートです。実際のフレームレートは、 ドライバに依存します。

したがって、Atrixはプレビュー用に15fps以外のものをサポートしていない可能性があります。

いずれにせよ、プレビューフレームレートを使用する適切な方法は、最初にgetSupportedPreviewFrameRates()を呼び出すことです。 null以外の結果を返す場合は、リスト内の最も近い数字を探して、それをsetPreviewFrameRate()に渡します。さもなければ、デバイスがサポートするどんなレートでも生きなければなりません。

+0

ありがとうございました。あなたの答えは私のためにいくつかの光を放つ。ターゲットフレームレートは実際のフレームレートとはかなり異なるようです。これからは、適切な方法でパラメータを設定します。再度、感謝します! –

関連する問題