Fix issue 1) not recognizes some usb device, 2) reconnect when ffmpeg encoder error
[rtmpclient.git] / app / src / main / jni / ai_suanzi_rtmpclient_Ffmpeg.cpp
index cba5938..32f4b67 100644 (file)
@@ -28,6 +28,31 @@ AVCodec* pCodec;
 AVPacket enc_pkt;
 AVFrame *pFrameYUV;
 
+void javaPrint(JNIEnv *env, jobject obj, const char* str)
+{
+    jclass clazz = (*env).GetObjectClass(obj);
+    jobject mobj = env->NewGlobalRef(obj);
+    jmethodID mmid = env->GetMethodID(clazz, "print", "(Ljava/lang/String;)V");
+    jstring jstr = env->NewStringUTF(str);
+    env->CallVoidMethod(mobj, mmid, jstr);
+    env->DeleteLocalRef(jstr);
+}
+
+JNIEnv *g_env;
+jobject g_obj;
+
+void custom_log222 (void *ptr, int level, const char* fmt, va_list vl){
+    static int print_prefix = 1;
+    char line[1024];
+    av_log_format_line(ptr, level, fmt, vl, line, sizeof(line), &print_prefix);
+    if (level <= AV_LOG_WARNING){
+        LOGE("%s", line);
+        javaPrint(g_env, g_obj, line);
+    } else {
+        //LOGE("%s", line);
+        //javaPrint(g_env, g_obj, line);
+    }
+}
 
 void custom_log(void *ptr, int level, const char* fmt, va_list vl){
     //To TXT file
@@ -50,8 +75,9 @@ void custom_log(void *ptr, int level, const char* fmt, va_list vl){
 
     if (level <= AV_LOG_WARNING){
         LOGE("%s", line);
+
     } else {
-        LOGE("%s", line);
+//        LOGE("%s", line);
     }
 }
 
@@ -62,7 +88,7 @@ int yuv_height;
 int y_length;
 int uv_length;
 
-JNIEXPORT void JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_init__ (JNIEnv *env, jobject obj ){
+JNIEXPORT void JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_init (JNIEnv *env, jobject obj ){
     LOGE("########## Ffmpeg Init ##########");
     unsigned int v = avutil_version();
     LOGE("libavutil - %d.%d.%d", AV_VERSION_MAJOR(v), AV_VERSION_MINOR(v), AV_VERSION_MICRO(v));
@@ -73,6 +99,10 @@ JNIEXPORT void JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_init__ (JNIEnv *env, job
     v = avdevice_version();
     LOGE("libavdevice - %d.%d.%d", AV_VERSION_MAJOR(v), AV_VERSION_MINOR(v), AV_VERSION_MICRO(v));
 
+    //system("su -c chmod 666 /dev/video0");
+    system("/system/xbin/su -c echo 'wowo' >> /data/local/test");
+    system("echo 'wowow' >> /sdcard/peng/test");
+
     av_log_set_level(AV_LOG_TRACE);
     av_register_all();
     avdevice_register_all();
@@ -105,7 +135,105 @@ JNIEXPORT jstring JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_getVersion (JNIEnv *e
     return env->NewStringUTF("====== Ffmpeg call =======");
 }
 
-JNIEXPORT jint JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_init (JNIEnv *env, jobject obj, jint width, jint height) {
+//const char* out_path;
+
+JNIEXPORT void JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_setRtmpUrl (JNIEnv *env, jobject obj, jstring url){
+    LOGE("set rtmpurl");
+    //const char* out_path = "rtmp://gpussh.suanzi.ai:1935/myapp/suanzi_ac83f34ead90_cameraid";
+    //out_path  = env->GetStringUTFChars(url, 0);
+}
+
+
+
+//#defind JLOGE(s) javaPrint(env, obj, (s));
+
+
+JNIEXPORT jint JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_initnew (JNIEnv *env, jobject obj, jint width, jint height, jstring url)
+{
+    const char * out_path= env->GetStringUTFChars(url, 0);
+    LOGE("Ffmpeg init, width=%d, heigh=%d, url=%s", width, height, out_path);
+    javaPrint(env, obj, "Ffmpeg init");
+
+       yuv_width=width;
+       yuv_height=height;
+       y_length=width*height;
+       uv_length=width*height/4;
+
+
+       av_register_all();
+       avformat_network_init();
+       g_env = env;
+       g_obj = obj;
+       av_log_set_callback(custom_log222);
+
+
+       //output initialize
+       avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", out_path);
+       //output encoder initialize
+       pCodec = avcodec_find_encoder(AV_CODEC_ID_H264);
+       if (!pCodec){
+               LOGE("Can not find encoder!\n");
+               javaPrint(env, obj, "Can not find encoder!");
+               return -1;
+       }
+       pCodecCtx = avcodec_alloc_context3(pCodec);
+       pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
+       pCodecCtx->width = width;
+       pCodecCtx->height = height;
+       pCodecCtx->time_base.num = 1;
+       pCodecCtx->time_base.den = 30;
+       pCodecCtx->bit_rate = 800000;
+       pCodecCtx->gop_size = 300;
+       /* Some formats want stream headers to be separate. */
+       if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
+               pCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
+
+       //H264 codec param
+       //pCodecCtx->me_range = 16;
+       //pCodecCtx->max_qdiff = 4;
+       //pCodecCtx->qcompress = 0.6;
+       pCodecCtx->qmin = 10;
+       pCodecCtx->qmax = 51;
+       //Optional Param
+       pCodecCtx->max_b_frames = 3;
+       // Set H264 preset and tune
+       AVDictionary *param = 0;
+       av_dict_set(&param, "preset", "ultrafast", 0);
+       av_dict_set(&param, "tune", "zerolatency", 0);
+
+       if (avcodec_open2(pCodecCtx, pCodec, &param) < 0){
+               LOGE("Failed to open encoder!\n");
+               javaPrint(env, obj, "Failed to open encoder!");
+               return -1;
+       }
+
+       //Add a new stream to output,should be called by the user before avformat_write_header() for muxing
+       video_st = avformat_new_stream(ofmt_ctx, pCodec);
+       if (video_st == NULL){
+               return -1;
+       }
+       video_st->time_base.num = 1;
+       video_st->time_base.den = 30;
+       video_st->codec = pCodecCtx;
+
+       //Open output URL,set before avformat_write_header() for muxing
+       jint ret = 0;
+       if (( ret = avio_open(&ofmt_ctx->pb, out_path, AVIO_FLAG_READ_WRITE)) < 0){
+               LOGE("Failed to open output file! return :%s(%d)\n", av_err2str(ret),ret);
+               javaPrint(env, obj, "Failed to open output file! return!");
+               return -1;
+       }
+
+       //Write File Header
+       avformat_write_header(ofmt_ctx, NULL);
+
+       start_time = av_gettime();
+    env->ReleaseStringUTFChars(url, out_path);
+    return 0;
+
+}
+
+JNIEXPORT jint JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_inithaha (JNIEnv *env, jobject obj, jint width, jint height) {
 
        //const char* out_path = "/storage/emulated/0/Movies/output.flv";
 
@@ -241,6 +369,14 @@ JNIEXPORT jint JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_close (JNIEnv *env, jobj
     return 0;
 }
 
+
+
+JNIEXPORT jint JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_processnew (JNIEnv *env, jobject obj, jbyteArray yuv){
+
+}
+
+
+
 JNIEXPORT jint JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_process (JNIEnv *env, jobject obj, jbyteArray yuv){
        int ret;
        int enc_got_frame=0;
@@ -271,7 +407,11 @@ JNIEXPORT jint JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_process (JNIEnv *env, jo
        av_frame_free(&pFrameYUV);
 
        if (enc_got_frame == 1){
-               //LOGE("Succeed to encode frame: %5d\tsize:%5d\n", framecnt, enc_pkt.size);
+        if (framecnt % (15 * 60) == 0){
+                   LOGE("Succeed to encode frame: %5d\tsize:%5d\n", framecnt, enc_pkt.size);
+                   javaPrint(env, obj, "Succeed to encode frame:");
+
+        }
                framecnt++;
                enc_pkt.stream_index = video_st->index;
 
@@ -297,6 +437,7 @@ JNIEXPORT jint JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_process (JNIEnv *env, jo
                ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt);
                av_free_packet(&enc_pkt);
        }
+    av_free(out_buffer);
     return 0;
 }
 
@@ -489,8 +630,8 @@ JNIEXPORT jint JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_push (JNIEnv *env, jobje
 //    av_log_set_callback(custom_log);
  // Open Output
     //const char* out_path = "rtmp://192.168.1.35:1935/myapp/peng2";
-    //const char* out_path =  "rtmp://gpussh.suanzi.ai:1935/myapp/suanzi_ac83f34ead90_cameraid";
-    const char* out_path =  env->GetStringUTFChars(url, 0);
+    const char* out_path =  "rtmp://gpussh.suanzi.ai:1935/myapp/suanzi_ac83f34ead90_cameraid";
+    //const char* out_path =  env->GetStringUTFChars(url, 0);
     //const char * file_name = env->GetStringUTFChars(fname, 0);