2017-10-10 1 views
0

나는 Camera2Video 예제를 따라 갔고 화면의 미리보기를 위해 SurfaceTexture에 속하는 Surface에서 일부 이미지 처리를 수행하기 위해 일부 JNI 코드를 구현했습니다. 이 잘 작동하지만 녹화 단추를 눌렀을 때 CameraCaptureSession.StateCallback()에서 onConfigureFailed()를 얻을 때 기록에 실패합니다. Android Camera2 JNI 이미지 처리 - JNI에서 표면 잠금 해제되지 않습니까?

내 주요 JNI 기능

은 여기 - 지금

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"); 
} 

나는 JNI 기능, 녹음 버튼 작동에 호출을 제거합니다. 이것은 내가이 JNI 코드 내에서 Surface를 적절하게 공개하지 않는다고 믿게하지만이 문제를 해결하는 방법을 잘 모릅니다.

사전에 많은 조언을 주신 것에 대해 많은 감사드립니다.


편집 - 로그에 다음 메시지가 표시됩니다. 15 :

10-11 10 41.749 8736-8736/com.example.android.camera2video E/BufferQueueProducer [SurfaceTexture-0-8736-0] 연결 : 이미 연결 (현재 REQ = 2 = 4)

답변

0

좋아요, 미리보기 표면이 아직 사용 중임을 알았습니다. 나는 onStartRecording() 내에서 Java 측에서 또 다른 미리보기 화면 변수를 제거함으로써이 문제를 해결했습니다.

관련 문제