나는 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)