#include "RtspNativeCodecJNI.h" #include #include #include #include #include //#include "looper.h" #include #include #include #include std::stringstream logss; Logger g_logger(logss); class CameraWrapper { public: PipeLine* pipeLine; PL_RTSPClient_Config rtspConfig; PL_AndroidMediaCodecDecoder_Config amcdConfig; jmethodID faceCallback; ANativeWindow* window; pthread_t live_daemon_thid; bool running; CameraWrapper() : pipeLine(nullptr), rtspConfig(), amcdConfig(), faceCallback(0), window(nullptr), live_daemon_thid(0), running(false) { } ~CameraWrapper() { stop(); delete pipeLine; } bool start() { LOG_INFO << "CameraWrapper::start" << LOG_ENDL; running = true; int ret = pthread_create(&live_daemon_thid, NULL, CameraWrapper::live_daemon_thd, this); if(ret != 0) { LOGP(ERROR, "pthread_create: %s/n", strerror(ret)); running = false; return false; } return true; } void stop() { LOG_INFO << "CameraWrapper::stop" << LOG_ENDL; if (!running) return; running = false; pthread_join(live_daemon_thid, NULL); } bool initPl() { PL_RTSPClient* rtspClient = (PL_RTSPClient*)pipeLine->push_elem("PL_RTSPClient"); bool ret = rtspClient->init(&rtspConfig); if (!ret) { LOG_ERROR << "rtspClient.init error" << std::endl; return false; } PL_AndroidMediaCodecDecoder* amcDecoder = (PL_AndroidMediaCodecDecoder*)pipeLine->push_elem("PL_AndroidMediaCodecDecoder"); ret = amcDecoder->init(&amcdConfig); if (!ret) { LOG_ERROR << "amcDecoder.init error" << std::endl; return false; } return true; } static void* live_daemon_thd(void* arg) { LOG_INFO << "CameraWrapper::live_daemon_thd start" << LOG_ENDL; CameraWrapper& cameraWrapper = *(CameraWrapper*)arg; while(cameraWrapper.running) { PipeLineElem* last = cameraWrapper.pipeLine->pipe(); bool ret = cameraWrapper.pipeLine->check_pipe_complete(last); LOG_DEBUG << "pipe ret=" << ret << LOG_ENDL; if (ret) { PipeMaterial pm; last->gain(pm); } } LOG_INFO << "CameraWrapper::live_daemon_thd stop, ret=" << LOG_ENDL; } }; CameraWrapper g_CameraWrappers[CAMERA_COUNT]; extern "C" { void Java_com_example_nativecodec_NativeCodec_init(JNIEnv *env, jclass clazz) { g_logger.set_level(VERBOSE); PipeLine::register_global_elem_creator("PL_RTSPClient", create_PL_RTSPClient); PipeLine::register_global_elem_creator("PL_AndroidMediaCodecDecoder", create_PL_AndroidMediaCodecDecoder); for (size_t i = 0; i < CAMERA_COUNT; i++) { g_CameraWrappers[i].pipeLine = new PipeLine; PipeLine& pipeLine(*(g_CameraWrappers[i].pipeLine)); } } // set the surface void Java_com_example_nativecodec_NativeCodec_setSurface(JNIEnv *env, jclass clazz, jint cameraIdx, jobject surface) { LOG_DEBUG << "@@@ Java_com_example_nativecodec_NativeCodec_setSurface" << LOG_ENDL; assert(cameraIdx <= CAMERA_COUNT); cameraIdx -= 1; CameraWrapper& cameraWrapper(g_CameraWrappers[cameraIdx]); // obtain a native window from a Java surface if (cameraWrapper.window) { ANativeWindow_release((ANativeWindow*)(cameraWrapper.window)); cameraWrapper.window = NULL; } cameraWrapper.window = ANativeWindow_fromSurface(env, surface); LOGP(DEBUG, "@@@ setsurface %p", cameraWrapper.window); } jboolean Java_com_example_nativecodec_NativeCodec_createPlayer(JNIEnv* env, jclass clazz, jint cameraIdx, jstring uri) { LOG_DEBUG << "@@@ Java_com_example_nativecodec_NativeCodec_createPlayer" << LOG_ENDL; assert(cameraIdx <= CAMERA_COUNT); cameraIdx -= 1; CameraWrapper& cameraWrapper(g_CameraWrappers[cameraIdx]); { const char *utf8Uri = env->GetStringUTFChars(uri, NULL); cameraWrapper.rtspConfig.rtspURL = utf8Uri; env->ReleaseStringUTFChars(uri, utf8Uri); cameraWrapper.rtspConfig.progName = "RtspNativeCodec"; cameraWrapper.rtspConfig.aux = true; // ffmpeg need aux, but live555 not cameraWrapper.rtspConfig.verbosityLevel = 1; cameraWrapper.rtspConfig.tunnelOverHTTPPortNum = 0; cameraWrapper.rtspConfig.args = nullptr; } { cameraWrapper.amcdConfig.ak_mime = "video/avc"; cameraWrapper.amcdConfig.ak_width = 1920; cameraWrapper.amcdConfig.ak_height = 1080; cameraWrapper.amcdConfig.windowSurface = cameraWrapper.window; cameraWrapper.amcdConfig.releaseOutputBuffIdx = true; } bool ret = cameraWrapper.initPl(); if (ret) return (cameraWrapper.start() ? JNI_TRUE : JNI_FALSE); else return JNI_FALSE; } // shut down the native media system void Java_com_example_nativecodec_NativeCodec_shutdown(JNIEnv* env, jclass clazz, jint cameraIdx) { LOG_DEBUG << "@@@ Java_com_example_nativecodec_NativeCodec_shutdown" << LOG_ENDL; assert(cameraIdx <= CAMERA_COUNT); cameraIdx -= 1; CameraWrapper& cameraWrapper(g_CameraWrappers[cameraIdx]); cameraWrapper.stop(); } jboolean Java_com_example_nativecodec_NativeCodec_setFaceCallback(JNIEnv* env, jclass clazz, jint cameraIdx, jstring func) { LOG_DEBUG << "@@@ Java_com_example_nativecodec_NativeCodec_setFaceCallback" << LOG_ENDL; assert(cameraIdx <= CAMERA_COUNT); cameraIdx -= 1; CameraWrapper& cameraWrapper(g_CameraWrappers[cameraIdx]); jclass cls = env->GetObjectClass(clazz); const char *utfFunc = env->GetStringUTFChars(func, NULL); cameraWrapper.faceCallback = env->GetMethodID(cls, utfFunc, "(II)V"); // Java_FaceCallback_func env->ReleaseStringUTFChars(func, utfFunc); // call: //env->CallVoidMethod(obj, callback, 5 , 10); } void Java_com_example_nativecodec_NativeCodec_lockFace(JNIEnv* env, jclass clazz, jint cameraIdx) { assert(cameraIdx <= CAMERA_COUNT); cameraIdx -= 1; } void Java_com_example_nativecodec_NativeCodec_releaseFace(JNIEnv* env, jclass clazz, jint cameraIdx) { assert(cameraIdx <= CAMERA_COUNT); cameraIdx -= 1; } jboolean Java_com_example_nativecodec_NativeCodec_getFaceList(JNIEnv* env, jclass clazz, jint cameraIdx, jbyteArray faceListPb) { assert(cameraIdx <= CAMERA_COUNT); cameraIdx -= 1; } jboolean Java_com_example_nativecodec_NativeCodec_getFaceImages(JNIEnv* env, jclass clazz, jint cameraIdx, jbyteArray faceImagesIdx, jbyteArray faceImages) { assert(cameraIdx <= CAMERA_COUNT); cameraIdx -= 1; } }