Как получить необработанные данные предварительного просмотра с объекта Camera не менее 15 кадров в секунду в Android?

Мне нужно получить необработанные данные предварительного просмотра из объекта Camera не менее 15 кадров в секунду , но я могу получить только кадр в 110 миллисекунд, что означает, что я могу получить только 9 кадров в секунду. Я кратко излагаю свой код.

Camera mCamera = Camera.open(); Camera.Parameters parameters = mCamera.getParameters(); parameters.setPreviewFrameRate(30); parameters.setPreviewFpsRange(15000,30000); mCamera.setParameters(parameters); mCamera.addCallbackBuffer(new byte[dataBufferSize]); //dataBufferSize stands for the byte size for a picture frame mCamera.addCallbackBuffer(new byte[dataBufferSize]); mCamera.addCallbackBuffer(new byte[dataBufferSize]); mCamera.setPreviewDisplay(videoCaptureViewHolder); //videoCaptureViewHolder is a SurfaceHolder object mCamera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() { private long timestamp=0; public synchronized void onPreviewFrame(byte[] data, Camera camera) { Log.v("CameraTest","Time Gap = "+(System.currentTimeMillis()-timestamp)); timestamp=System.currentTimeMillis(); //do picture data process camera.addCallbackBuffer(data); return; } } mCamera.startPreview(); 

В приведенном выше кратком коде, dataBufferSize и videoCaptureViewHolder определяется и вычисляется или назначается в других операторах.

Я запускаю свой код, я вижу предварительный просмотр на экране, и я беру журнал ниже:

 ... V/CameraTest( 5396): Time Gap = 105 V/CameraTest( 5396): Time Gap = 112 V/CameraTest( 5396): Time Gap = 113 V/CameraTest( 5396): Time Gap = 115 V/CameraTest( 5396): Time Gap = 116 V/CameraTest( 5396): Time Gap = 113 V/CameraTest( 5396): Time Gap = 115 ... 

Это означает, что onPreviewFrame (байт [] данные, камера камеры) вызывается каждые 110 миллисекунд, поэтому я могу получить не более 9 кадров в секунду. И независимо от того, какую частоту кадров предварительного просмотра я задал с помощью задачи setPreviewFrameRate (), и какой превью диапазон Fps, который я задал с помощью проблемы setPreviewFpsRange () , журнал тот же.

Кто-нибудь даст мне некоторую помощь по этой проблеме? Мне нужно получить необработанные данные предварительного просмотра с объекта камеры не менее 15 кадров в секунду. Заранее спасибо.

Я поместил весь свой код ниже.

CameraTest.java

 package test.cameratest; import java.io.IOException; import java.util.Iterator; import java.util.List; import android.app.Activity; import android.graphics.ImageFormat; import android.hardware.Camera; import android.hardware.Camera.ErrorCallback; import android.hardware.Camera.Parameters; import android.hardware.Camera.Size; import android.os.Bundle; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.SurfaceHolder.Callback; public class CameraTestActivity extends Activity { SurfaceView mVideoCaptureView; Camera mCamera; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mVideoCaptureView = (SurfaceView) findViewById(R.id.video_capture_surface); SurfaceHolder videoCaptureViewHolder = mVideoCaptureView.getHolder(); videoCaptureViewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); videoCaptureViewHolder.addCallback(new Callback() { public void surfaceDestroyed(SurfaceHolder holder) { } public void surfaceCreated(SurfaceHolder holder) { startVideo(); } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } }); } private void startVideo() { SurfaceHolder videoCaptureViewHolder = null; try { mCamera = Camera.open(); } catch (RuntimeException e) { Log.e("CameraTest", "Camera Open filed"); return; } mCamera.setErrorCallback(new ErrorCallback() { public void onError(int error, Camera camera) { } }); Camera.Parameters parameters = mCamera.getParameters(); parameters.setPreviewFrameRate(30); parameters.setPreviewFpsRange(15000,30000); List<int[]> supportedPreviewFps=parameters.getSupportedPreviewFpsRange(); Iterator<int[]> supportedPreviewFpsIterator=supportedPreviewFps.iterator(); while(supportedPreviewFpsIterator.hasNext()){ int[] tmpRate=supportedPreviewFpsIterator.next(); StringBuffer sb=new StringBuffer(); sb.append("supportedPreviewRate: "); for(int i=tmpRate.length,j=0;j<i;j++){ sb.append(tmpRate[j]+", "); } Log.v("CameraTest",sb.toString()); } List<Size> supportedPreviewSizes=parameters.getSupportedPreviewSizes(); Iterator<Size> supportedPreviewSizesIterator=supportedPreviewSizes.iterator(); while(supportedPreviewSizesIterator.hasNext()){ Size tmpSize=supportedPreviewSizesIterator.next(); Log.v("CameraTest","supportedPreviewSize.width = "+tmpSize.width+"supportedPreviewSize.height = "+tmpSize.height); } mCamera.setParameters(parameters); if (null != mVideoCaptureView) videoCaptureViewHolder = mVideoCaptureView.getHolder(); try { mCamera.setPreviewDisplay(videoCaptureViewHolder); } catch (Throwable t) { } Log.v("CameraTest","Camera PreviewFrameRate = "+mCamera.getParameters().getPreviewFrameRate()); Size previewSize=mCamera.getParameters().getPreviewSize(); 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]); mCamera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() { private long timestamp=0; public synchronized void onPreviewFrame(byte[] data, Camera camera) { Log.v("CameraTest","Time Gap = "+(System.currentTimeMillis()-timestamp)); timestamp=System.currentTimeMillis(); try{ camera.addCallbackBuffer(data); }catch (Exception e) { Log.e("CameraTest", "addCallbackBuffer error"); return; } return; } }); try { mCamera.startPreview(); } catch (Throwable e) { mCamera.release(); mCamera = null; return; } } private void stopVideo() { if(null==mCamera) return; try { mCamera.stopPreview(); mCamera.setPreviewDisplay(null); mCamera.setPreviewCallbackWithBuffer(null); mCamera.release(); } catch (IOException e) { e.printStackTrace(); return; } mCamera = null; } public void finish(){ stopVideo(); super.finish(); }; } в package test.cameratest; import java.io.IOException; import java.util.Iterator; import java.util.List; import android.app.Activity; import android.graphics.ImageFormat; import android.hardware.Camera; import android.hardware.Camera.ErrorCallback; import android.hardware.Camera.Parameters; import android.hardware.Camera.Size; import android.os.Bundle; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.SurfaceHolder.Callback; public class CameraTestActivity extends Activity { SurfaceView mVideoCaptureView; Camera mCamera; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mVideoCaptureView = (SurfaceView) findViewById(R.id.video_capture_surface); SurfaceHolder videoCaptureViewHolder = mVideoCaptureView.getHolder(); videoCaptureViewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); videoCaptureViewHolder.addCallback(new Callback() { public void surfaceDestroyed(SurfaceHolder holder) { } public void surfaceCreated(SurfaceHolder holder) { startVideo(); } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } }); } private void startVideo() { SurfaceHolder videoCaptureViewHolder = null; try { mCamera = Camera.open(); } catch (RuntimeException e) { Log.e("CameraTest", "Camera Open filed"); return; } mCamera.setErrorCallback(new ErrorCallback() { public void onError(int error, Camera camera) { } }); Camera.Parameters parameters = mCamera.getParameters(); parameters.setPreviewFrameRate(30); parameters.setPreviewFpsRange(15000,30000); List<int[]> supportedPreviewFps=parameters.getSupportedPreviewFpsRange(); Iterator<int[]> supportedPreviewFpsIterator=supportedPreviewFps.iterator(); while(supportedPreviewFpsIterator.hasNext()){ int[] tmpRate=supportedPreviewFpsIterator.next(); StringBuffer sb=new StringBuffer(); sb.append("supportedPreviewRate: "); for(int i=tmpRate.length,j=0;j<i;j++){ sb.append(tmpRate[j]+", "); } Log.v("CameraTest",sb.toString()); } List<Size> supportedPreviewSizes=parameters.getSupportedPreviewSizes(); Iterator<Size> supportedPreviewSizesIterator=supportedPreviewSizes.iterator(); while(supportedPreviewSizesIterator.hasNext()){ Size tmpSize=supportedPreviewSizesIterator.next(); Log.v("CameraTest","supportedPreviewSize.width = "+tmpSize.width+"supportedPreviewSize.height = "+tmpSize.height); } mCamera.setParameters(parameters); if (null != mVideoCaptureView) videoCaptureViewHolder = mVideoCaptureView.getHolder(); try { mCamera.setPreviewDisplay(videoCaptureViewHolder); } catch (Throwable t) { } Log.v("CameraTest","Camera PreviewFrameRate = "+mCamera.getParameters().getPreviewFrameRate()); Size previewSize=mCamera.getParameters().getPreviewSize(); 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]); mCamera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() { private long timestamp=0; public synchronized void onPreviewFrame(byte[] data, Camera camera) { Log.v("CameraTest","Time Gap = "+(System.currentTimeMillis()-timestamp)); timestamp=System.currentTimeMillis(); try{ camera.addCallbackBuffer(data); }catch (Exception e) { Log.e("CameraTest", "addCallbackBuffer error"); return; } return; } }); try { mCamera.startPreview(); } catch (Throwable e) { mCamera.release(); mCamera = null; return; } } private void stopVideo() { if(null==mCamera) return; try { mCamera.stopPreview(); mCamera.setPreviewDisplay(null); mCamera.setPreviewCallbackWithBuffer(null); mCamera.release(); } catch (IOException e) { e.printStackTrace(); return; } mCamera = null; } public void finish(){ stopVideo(); super.finish(); }; } в package test.cameratest; import java.io.IOException; import java.util.Iterator; import java.util.List; import android.app.Activity; import android.graphics.ImageFormat; import android.hardware.Camera; import android.hardware.Camera.ErrorCallback; import android.hardware.Camera.Parameters; import android.hardware.Camera.Size; import android.os.Bundle; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.SurfaceHolder.Callback; public class CameraTestActivity extends Activity { SurfaceView mVideoCaptureView; Camera mCamera; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mVideoCaptureView = (SurfaceView) findViewById(R.id.video_capture_surface); SurfaceHolder videoCaptureViewHolder = mVideoCaptureView.getHolder(); videoCaptureViewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); videoCaptureViewHolder.addCallback(new Callback() { public void surfaceDestroyed(SurfaceHolder holder) { } public void surfaceCreated(SurfaceHolder holder) { startVideo(); } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } }); } private void startVideo() { SurfaceHolder videoCaptureViewHolder = null; try { mCamera = Camera.open(); } catch (RuntimeException e) { Log.e("CameraTest", "Camera Open filed"); return; } mCamera.setErrorCallback(new ErrorCallback() { public void onError(int error, Camera camera) { } }); Camera.Parameters parameters = mCamera.getParameters(); parameters.setPreviewFrameRate(30); parameters.setPreviewFpsRange(15000,30000); List<int[]> supportedPreviewFps=parameters.getSupportedPreviewFpsRange(); Iterator<int[]> supportedPreviewFpsIterator=supportedPreviewFps.iterator(); while(supportedPreviewFpsIterator.hasNext()){ int[] tmpRate=supportedPreviewFpsIterator.next(); StringBuffer sb=new StringBuffer(); sb.append("supportedPreviewRate: "); for(int i=tmpRate.length,j=0;j<i;j++){ sb.append(tmpRate[j]+", "); } Log.v("CameraTest",sb.toString()); } List<Size> supportedPreviewSizes=parameters.getSupportedPreviewSizes(); Iterator<Size> supportedPreviewSizesIterator=supportedPreviewSizes.iterator(); while(supportedPreviewSizesIterator.hasNext()){ Size tmpSize=supportedPreviewSizesIterator.next(); Log.v("CameraTest","supportedPreviewSize.width = "+tmpSize.width+"supportedPreviewSize.height = "+tmpSize.height); } mCamera.setParameters(parameters); if (null != mVideoCaptureView) videoCaptureViewHolder = mVideoCaptureView.getHolder(); try { mCamera.setPreviewDisplay(videoCaptureViewHolder); } catch (Throwable t) { } Log.v("CameraTest","Camera PreviewFrameRate = "+mCamera.getParameters().getPreviewFrameRate()); Size previewSize=mCamera.getParameters().getPreviewSize(); 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]); mCamera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() { private long timestamp=0; public synchronized void onPreviewFrame(byte[] data, Camera camera) { Log.v("CameraTest","Time Gap = "+(System.currentTimeMillis()-timestamp)); timestamp=System.currentTimeMillis(); try{ camera.addCallbackBuffer(data); }catch (Exception e) { Log.e("CameraTest", "addCallbackBuffer error"); return; } return; } }); try { mCamera.startPreview(); } catch (Throwable e) { mCamera.release(); mCamera = null; return; } } private void stopVideo() { if(null==mCamera) return; try { mCamera.stopPreview(); mCamera.setPreviewDisplay(null); mCamera.setPreviewCallbackWithBuffer(null); mCamera.release(); } catch (IOException e) { e.printStackTrace(); return; } mCamera = null; } public void finish(){ stopVideo(); super.finish(); }; } 

AndroidManifest.xml

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="test.cameratest" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="10" android:maxSdkVersion="10"/> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/> <uses-permission android:name="android.permission.CALL_PHONE"/> <uses-permission android:name="android.permission.BOOT_COMPLETED"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".CameraTestActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> ? <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="test.cameratest" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="10" android:maxSdkVersion="10"/> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/> <uses-permission android:name="android.permission.CALL_PHONE"/> <uses-permission android:name="android.permission.BOOT_COMPLETED"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".CameraTestActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> 

Solutions Collecting From Web of "Как получить необработанные данные предварительного просмотра с объекта Camera не менее 15 кадров в секунду в Android?"

Я боюсь, вы не можете. Предварительный параметр настройки частоты кадров является подсказкой для приложения камеры (который работает в отдельном процессе) – и он может принимать или молча игнорировать его. Это также не связано с извлечением кадра предварительного просмотра

Когда вы запрашиваете рамку предварительного просмотра, вы просто говорите внешнее приложение, которое вы хотели бы получить. Буфер для него выделяется в приложении камеры, а затем передается в вашу деятельность через сегмент памяти в миллиметрах – это требует времени.

Вы можете получить желаемую производительность на некоторых устройствах, но не обязательно на том, с которым вы играете.

Если вам нужна определенная частота кадров, вам нужно будет захватить видео, а затем проанализировать / распаковать результирующий двоичный поток.

У меня опыт работы с камерой был неудобным и зависящим от оборудования. Поэтому попробуйте запустить его на другом оборудовании, если сможете.

Возможно, стоит попробовать еще несколько настроек камеры.

  • Checkout setRecordingHint (логическая подсказка) .
  • Могли бы даже попробовать FOCUS_MODE .

Благодарим за включение примера кода.

Это не должно быть проблемой. У моего андроанго (на рынке) приложение получило до 30 кадров в секунду (по крайней мере, я применил тормоз скорости, чтобы замедлить его).

Пожалуйста, внимательно проверьте, заполнен ли ваш журнал заявлениями-сборщиками мусора. Это так, если добавлено слишком мало буферов. Это был трюк для меня. По крайней мере, я подошел, чтобы добавить 20! Буферов к камере.

Затем обработка каждого кадра должна выполняться в отдельном потоке. Хотя изображение находится в потоке для обработки, обратный вызов должен пропускать текущий кадр.

По моему мнению, Android не позволяет пользователю устанавливать фиксированную частоту кадров, а также гарантировать, что значение fps, которое вы укажете, будет соблюдаться, связано с временем экспозиции кадра, которое устанавливается аппаратным или программным обеспечением камеры. Частота кадров, которую вы наблюдаете, может быть функцией освещения. Например, определенный телефон может дать вам предварительный просмотр 30 кадров в дневном свете, но только 7 кадров в секунду, если вы снимаете в условиях низкой освещенности.

Обычно я объявляю глобальное логическое значение lockCameraUse. Функция обратного вызова обычно выглядит так.

  public void onPreviewFrame(byte[] data, Camera camera) { if (lockCameraUse) { camera.addCallbackBuffer(data); return; } lockCameraUse = true; // processinng data // done processing data camera.addCallbackBuffer(data); lockCameraUse = false; return; } 

Одна вещь, которая, по-видимому, увеличивает текучесть предварительного просмотра, если не фактический FPS обязательно, устанавливает параметр previewFormat в YV12, если поддерживается. Это меньше байтов для копирования, выравнивание по 16 байт и, возможно, оптимизация другими способами:

  // PREVIEW FORMATS List<Integer> supportedPreviewFormats = parameters.getSupportedPreviewFormats(); Iterator<Integer> supportedPreviewFormatsIterator = supportedPreviewFormats.iterator(); while(supportedPreviewFormatsIterator.hasNext()){ Integer previewFormat =supportedPreviewFormatsIterator.next(); // 16 ~ NV16 ~ YCbCr // 17 ~ NV21 ~ YCbCr ~ DEFAULT // 4 ~ RGB_565 // 256~ JPEG // 20 ~ YUY2 ~ YcbCr ... // 842094169 ~ YV12 ~ 4:2:0 YCrCb comprised of WXH Y plane, W/2xH/2 Cr & Cb. see documentation Log.v("CameraTest","Supported preview format:"+previewFormat); if (previewFormat == ImageFormat.YV12) { parameters.setPreviewFormat(previewFormat); Log.v("CameraTest","SETTING FANCY YV12 FORMAT"); } } в  // PREVIEW FORMATS List<Integer> supportedPreviewFormats = parameters.getSupportedPreviewFormats(); Iterator<Integer> supportedPreviewFormatsIterator = supportedPreviewFormats.iterator(); while(supportedPreviewFormatsIterator.hasNext()){ Integer previewFormat =supportedPreviewFormatsIterator.next(); // 16 ~ NV16 ~ YCbCr // 17 ~ NV21 ~ YCbCr ~ DEFAULT // 4 ~ RGB_565 // 256~ JPEG // 20 ~ YUY2 ~ YcbCr ... // 842094169 ~ YV12 ~ 4:2:0 YCrCb comprised of WXH Y plane, W/2xH/2 Cr & Cb. see documentation Log.v("CameraTest","Supported preview format:"+previewFormat); if (previewFormat == ImageFormat.YV12) { parameters.setPreviewFormat(previewFormat); Log.v("CameraTest","SETTING FANCY YV12 FORMAT"); } } 

http://developer.android.com/reference/android/graphics/ImageFormat.html#YV12 описывает формат. Это плюс несколько запасных буферов дает мне «промежутки времени» всего 80 … что еще не «достаточно хорошо», но … лучше? (На самом деле у меня один на 69 … но на самом деле, они в среднем около 90). Не знаете, сколько рубок замедляет работу?

Установка параметра предварительного просмотра в 320×240 (против 1280×720) снижает скорость до 50-70 мс … так что, возможно, это вам нужно? По общему признанию, эти небольшие данные могут быть намного менее полезными.

// все протестированы на Nexus4