2017-10-10 8 views
0

J'ai suivi l'exemple de Camera2Video et j'ai également implémenté du code JNI pour faire un traitement d'image sur la Surface appartenant à SurfaceTexture pour l'aperçu sur l'écran. Cela fonctionne très bien mais quand j'appuie sur le bouton d'enregistrement, il ne parvient pas à enregistrer car j'obtiens un onConfigureFailed() de la CameraCaptureSession.StateCallback().Android Camera2 Traitement d'image JNI - La surface n'est pas déverrouillée de JNI?

Ma principale fonction JNI est ici -

extern "C" 
jstring 
Java_com_example_android_camera2video_Camera2VideoFragment_someImageProcessingJNI(
     JNIEnv *env, 
     jobject, /* this */ 
     jint srcWidth, 
     jint srcHeight, 
     jobject y_srcBuffer, 
     jobject u_srcBuffer, 
     jobject v_srcBuffer, 
     jobject dstSurface) { 

    // Get pointers to the 3 planes (YUV) of the source (Image from ImageReader). 

    uint8_t *srcLumaPtr = reinterpret_cast<uint8_t *>(env->GetDirectBufferAddress(y_srcBuffer)); 
    if (srcLumaPtr == NULL) { 
     return NULL; 
    } 

    uint8_t *srcUPtr = reinterpret_cast<uint8_t *>(env->GetDirectBufferAddress(u_srcBuffer)); 
    if (srcUPtr == NULL) { 
     return NULL; 
    } 

    uint8_t *srcVPtr = reinterpret_cast<uint8_t *>(env->GetDirectBufferAddress(v_srcBuffer)); 
    if (srcVPtr == NULL) { 
     return NULL; 
    } 

    // Destination setup. 
    // YUV - NV21 

    int dstWidth; 
    int dstHeight; 

    // Get a ptr to the destination window - don't forget to release it. 
    ANativeWindow *dstWin = ANativeWindow_fromSurface(env, dstSurface); 

    // Acquire a reference on the given ANativeWindow object. This prevents the object from being 
    // deleted until the reference is removed. 
    ANativeWindow_acquire(dstWin); 

    // Swapping due to the rotation. 
    dstWidth = srcHeight; 
    dstHeight = srcWidth; 

    // Change the format and size of the window buffers. 
    int32_t setBufferGeometryRet = ANativeWindow_setBuffersGeometry(dstWin, dstWidth, dstHeight, 
                    0 /*format unchanged*/); 

    // Struct that represents a windows buffer. 
    ANativeWindow_Buffer dstBuf; 

    // Lock the window's next drawing surface for writing. 
    if (int32_t err = ANativeWindow_lock(dstWin, &dstBuf, NULL)) { 
     ANativeWindow_release(dstWin); 
     return NULL; 
    } 

    // uint8_t* dstLumaPtr = reinterpret_cast<uint8_t*>(dstBuf.bits); 
    // If we want to write as 32-bit. 
    uint32_t *dstLumaPtr = reinterpret_cast<uint32_t *>(dstBuf.bits); 
    uint32_t *dstLumaPtr_orig = dstLumaPtr; 

    // Buffer 
    int32_t ANativeWindow_Buffer_Width = dstBuf.width; 
    int32_t ANativeWindow_Buffer_Height = dstBuf.height; 
    int32_t ANativeWindow_Buffer_Stride = dstBuf.stride; 

    // Window 
    int32_t dstNativeWinWidth = ANativeWindow_getWidth(dstWin); 
    int32_t dstNativeWinHeight = ANativeWindow_getHeight(dstWin); 
    int32_t dstNativeWinFormat = ANativeWindow_getFormat(dstWin); 

    // Read from the YUV source which needs the 90 deg clockwise rotation. 
    for (int srcCol = 0; srcCol < srcWidth; srcCol++) { 
     for (int srcRow = srcHeight - 1; srcRow >= 0; srcRow--) { 

      // packRGBA() just converts YUV to RGB. 
      *dstLumaPtr = packRGBA(srcLumaPtr[srcRow * srcWidth + srcCol], 
            srcUPtr[((srcRow/2) * srcWidth) + (srcCol - (srcCol % 2))], 
            srcVPtr[((srcRow/2) * srcWidth) + (srcCol - (srcCol % 2))]); 
      dstLumaPtr++; 

      // We cannot simple write to destination pixels sequentially because of the 
      // stride. Stride is the actual memory buffer width, while the image width is only 
      // the wdith of valid pixels. 
      // If we reach the end of a source row, we need to advance our destination 
      // pointer to skip the padding cells. 
      if (srcRow == 0) 
       dstLumaPtr += (ANativeWindow_Buffer_Stride - ANativeWindow_Buffer_Width); 

     } 
    } 

    // ---------------------------------------------------------------------- 
    // Some image processing done here... 
    // -------------------------------------------------------------------- 

    ANativeWindow_unlockAndPost(dstWin); 
    ANativeWindow_release(dstWin); 

    return env->NewStringUTF("Return from JNI"); 
} 

Maintenant, si je supprime l'appel à la fonction JNI, les œuvres de bouton d'enregistrement. Cela me fait croire que je ne libère pas la surface correctement dans ce code JNI mais je ne suis pas sûr de savoir comment procéder pour résoudre ce problème.

Merci d'avance pour tout conseil.


Modifier - Je reçois le message suivant dans les journaux.

10-11 10: 15: 41,749 8736-8736/com.example.android.camera2video E/BufferQueueProducer: [SurfaceTexture-0-8736-0] connecter: déjà connecté (cur = 2 req = 4)

Répondre

0

D'accord, j'ai découvert que la surface d'aperçu était toujours utilisée. J'ai corrigé ceci en supprimant l'ajout d'une autre variable de surface de prévisualisation du côté Java dans onStartRecording().