Je teste avec le nouvel Android camera2 API et je veux contrôler chaque image de la caméra. Ce que je fais pour cela est de créer un ImageReader et de configurer la résolution et le format d'image.
ImageReader imageReader = ImageReader.newInstance(1280,720,ImageFormat.YUV_420_888,1);
imageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireLatestImage();
Log.i(MainActivity.LOG_TAG,"imageReader: "+System.currentTimeMillis());
image.close();
}
},null);
Après cela, je crée un nouveau CaptureRequest avec le paramètre TEMPLATE_PREVIEW et lui ajoute la cible imageReader
. Pour cameraCaptureSession je crée un nouveau setRepeatingRequest avec cette demande
try {
final CaptureRequest.Builder builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
builder.addTarget(imageReader.getSurface());
mCameraDevice.createCaptureSession(
Arrays.asList(imageReader.getSurface()),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession session) {
mSession = session;
try {
mSession.setRepeatingRequest(builder.build(),null,null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(CameraCaptureSession session) {
}
},
null
);
} catch (CameraAccessException e) {
e.printStackTrace();
}
Lorsque j'ouvre la caméra et commence à voir ce que j'ai avec aperçu, je reçois une exception. Mais avant exception, j’ai eu un aperçu d’image et après cela, j’ai fait exception
10-30 16:00:32.850 1390-1894/.camera2tutorial E/BufferQueueProducer﹕ [unnamed-1390-1] dequeueBuffer: BufferQueue has been abandoned
10-30 16:00:32.850 1390-1894/.camera2tutorial E/Legacy-CameraDevice-JNI﹕ LegacyCameraDevice_nativeProduceFrame: Error while producing frame No such device (-19).
10-30 16:00:32.850 1390-1894/.camera2tutorial W/SurfaceTextureRenderer﹕ Surface abandoned, dropping frame.
Android.hardware.camera2.legacy.LegacyExceptionUtils$BufferQueueAbandonedException
at Android.hardware.camera2.legacy.LegacyExceptionUtils.throwOnError(LegacyExceptionUtils.Java:64)
at Android.hardware.camera2.legacy.LegacyCameraDevice.produceFrame(LegacyCameraDevice.Java:516)
at Android.hardware.camera2.legacy.SurfaceTextureRenderer.drawIntoSurfaces(SurfaceTextureRenderer.Java:699)
at Android.hardware.camera2.legacy.GLThreadManager$1.handleMessage(GLThreadManager.Java:103)
at Android.os.Handler.dispatchMessage(Handler.Java:98)
at Android.os.Looper.loop(Looper.Java:145)
at Android.os.HandlerThread.run(HandlerThread.Java:61)
Comment puis-je réparer cela??
J'utilise un Samsung Galaxy S5 et une API Android 21
Assurez-vous de conserver une référence à ImageReader que vous créez, probablement où que vous ayez défini mSession.
La surface obtenue à partir d'ImageReader est à peu près équivalente à un pointeur faible. Cela n'empêchera pas ImageReader de récupérer des déchets. Il est donc probable (en fonction de votre nom) que ImageReader soit détruit et que l'erreur d'abandon se produise.
J'ai eu le même problème lors de la commutation entre les activités de mon application et c'était après avoir appelé onSurfaceTextureDestroyed()
qui ne renvoyait que faux, mais ce que j'ai fait est que je l'ai changé en
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
Log.e(TAG, "onSurfaceTextureDestroyed");
if(cameraDevice != null){
closeCamera();
cameraDevice = null;
}
return false;
}
et cela a fonctionné pour moi.
j'ai trouvé une solution, cela a fonctionné pour moi, l'erreur d'infecter est de choisir la taille correcte, donc lors de l'utilisation de MediaRecorder.setVideoSize (), utilisez cette méthode pour choisir la taille optimale
private static Size chooseOptimalSize(Size[] choices, int width, int height) {
Size bigEnough = null;
int minAreaDiff = Integer.MAX_VALUE;
for (Size option : choices) {
int diff = (width*height)-(option.getWidth()*option.getHeight()) ;
if (diff >=0 && diff < minAreaDiff &&
option.getWidth() <= width &&
option.getHeight() <= height) {
minAreaDiff = diff;
bigEnough = option;
}
}
if (bigEnough != null) {
return bigEnough;
} else {
Arrays.sort(choices,new CompareSizeByArea());
return choices[0];
}
}