Add NetworkMonitor
[rtmpclient.git] / app / src / main / jni / FfmpegHelper.cpp
index 279341b..1df52e5 100644 (file)
@@ -3,7 +3,7 @@
 #include <string>
 
 #define FLOGE(...) av_log(NULL, AV_LOG_ERROR, __VA_ARGS__)
-#define FLOGD(...) av_log(NULL, AV_LOG_DEBUG, __VA_ARGS__)
+#define FLOGD(...) av_log(NULL, AV_LOG_INFO, __VA_ARGS__)
 
 FfmpegHelper* FfmpegHelper::singleton = NULL;
 bool FfmpegHelper::isInit = false;
@@ -37,22 +37,24 @@ void FfmpegHelper::av_log_cb (void *ptr, int level, const char* fmt, va_list vl)
     av_log_format_line(ptr, level, fmt, vl, line, sizeof(line), &print_prefix);
 
     if (level <= AV_LOG_WARNING){
-        if (singleton) singleton->javaPrint(line);
+        if (singleton) singleton->javaPrint(line, 1);
+    } else if(level <= AV_LOG_INFO){
+        if (singleton) singleton->javaPrint(line, 0);
+        // LOGE("%s", line);
     } else {
-        if (singleton) singleton->javaPrint(line);
-        //LOGE("%s", line);
+
     }
 }
 
-void FfmpegHelper::javaPrint(const char* str)
+void FfmpegHelper::javaPrint(const char* str, int level)
 {
     JNIEnv* env = 0;
     if(this->jvm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK){
         return;
     }
-    jmethodID mid = env->GetStaticMethodID(ai_suanzi_rtmpclient_FfmpegHelper, "javaPrint", "(Ljava/lang/String;)V");
+    jmethodID mid = env->GetStaticMethodID(ai_suanzi_rtmpclient_FfmpegHelper, "javaPrint", "(Ljava/lang/String;I)V");
     jstring jstr = env->NewStringUTF(str);
-    env->CallStaticVoidMethod(ai_suanzi_rtmpclient_FfmpegHelper, mid, jstr);
+    env->CallStaticVoidMethod(ai_suanzi_rtmpclient_FfmpegHelper, mid, jstr, level);
     env->DeleteLocalRef(jstr);
 }
 
@@ -60,15 +62,15 @@ void FfmpegHelper::init()
 {    
     av_log_set_callback(av_log_cb);
     av_log_set_level(AV_LOG_DEBUG);
-    FLOGE("########## Ffmpeg Init ##########");
+    FLOGD("########## Ffmpeg Init ##########");
     unsigned int v = avutil_version();
-    FLOGE("libavutil - %d.%d.%d", AV_VERSION_MAJOR(v), AV_VERSION_MINOR(v), AV_VERSION_MICRO(v));
+    FLOGD("libavutil - %d.%d.%d", AV_VERSION_MAJOR(v), AV_VERSION_MINOR(v), AV_VERSION_MICRO(v));
     v = avcodec_version();
-    FLOGE("libavcodec - %d.%d.%d", AV_VERSION_MAJOR(v), AV_VERSION_MINOR(v), AV_VERSION_MICRO(v));
+    FLOGD("libavcodec - %d.%d.%d", AV_VERSION_MAJOR(v), AV_VERSION_MINOR(v), AV_VERSION_MICRO(v));
     v = avformat_version();
-    FLOGE("libavformat - %d.%d.%d", AV_VERSION_MAJOR(v), AV_VERSION_MINOR(v), AV_VERSION_MICRO(v));
+    FLOGD("libavformat - %d.%d.%d", AV_VERSION_MAJOR(v), AV_VERSION_MINOR(v), AV_VERSION_MICRO(v));
     v = avdevice_version();
-    FLOGE("libavdevice - %d.%d.%d", AV_VERSION_MAJOR(v), AV_VERSION_MINOR(v), AV_VERSION_MICRO(v));
+    FLOGD("libavdevice - %d.%d.%d", AV_VERSION_MAJOR(v), AV_VERSION_MINOR(v), AV_VERSION_MICRO(v));
 
     av_register_all();
     //avdevice_register_all();
@@ -82,7 +84,8 @@ void FfmpegHelper::init()
 int FfmpegHelper::initEncoder(int width, int height, const char* outpath)
 {
     if(!isInit) init();
-    FLOGE("initEncoder - width=%d, height=%d, url=%s", width, height, outpath);
+    FLOGE("-----------> FfmpegHelper::initEncoder");
+    FLOGD("initEncoder - width=%d, height=%d, url=%s", width, height, outpath);
 
     pWidth = width;
     pHeight = height;
@@ -123,7 +126,6 @@ int FfmpegHelper::initEncoder(int width, int height, const char* outpath)
        }
 
        //Add a new stream to output,should be called by the user before avformat_write_header() for muxing
-       AVStream* vStream;
     if ((vStream = avformat_new_stream(formatCtx, codec)) == NULL){
         FLOGE("avformat_new_stream - error");
         return -1;
@@ -143,22 +145,33 @@ int FfmpegHelper::initEncoder(int width, int height, const char* outpath)
         return -1;
     }
     startTime = av_gettime();
+    frameCnt = 0;
     return 0;
 }
 
+
 int FfmpegHelper::processFrame(uint8_t* data)
 {
     int ret = 0;
-    AVFrame *pFrame, *pFrameYUV;
-    pFrameYUV = av_frame_alloc();
     int y_length = pWidth * pHeight;
+    pFrameYUV = av_frame_alloc();
     uint8_t *outBuf = (uint8_t *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, codecCtx->width, codecCtx->height, 1));
-    av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, outBuf, AV_PIX_FMT_YUV420P, codecCtx->width, codecCtx->height, 1);
+    if(outBuf == NULL) {
+        FLOGE("av_malloc, error");
+        av_frame_free(&pFrameYUV);
+        return -1;
+    }
+    if((ret = av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, outBuf, AV_PIX_FMT_YUV420P, codecCtx->width, codecCtx->height, 1)) < 0){
+        FLOGE("av_image_fill_arrays - error: %s(%d).", av_err2str(ret), ret);
+        av_frame_free(&pFrameYUV);
+        return -1;
+    }
 
+    // NV21 to YUV420P
        memcpy(pFrameYUV->data[0], data, y_length);
     for (int i = 0; i < y_length / 4; i++){
-        *(pFrameYUV->data[2] + i) = *(data + y_length * 2);
-        *(pFrameYUV->data[1] + i) = *(data + y_length * 2 + 1);
+        *(pFrameYUV->data[2] + i) = *(data + y_length  + i * 2);
+        *(pFrameYUV->data[1] + i) = *(data + y_length  + i * 2 + 1);
     }
 
        pFrameYUV->format = AV_PIX_FMT_YUV420P;
@@ -166,18 +179,21 @@ int FfmpegHelper::processFrame(uint8_t* data)
        pFrameYUV->height = pHeight;
 
 
-    AVPacket encPkt;
     encPkt.data = NULL;
     encPkt.size = 0;
     av_init_packet(&encPkt);
     int got_frame = 0;
 
-       avcodec_encode_video2(codecCtx, &encPkt, pFrameYUV, &got_frame);
+       if((ret = avcodec_encode_video2(codecCtx, &encPkt, pFrameYUV, &got_frame)) < 0){
+        FLOGE("avcodec_encode_video2 - error: %s(%d).", av_err2str(ret), ret);
+        av_frame_free(&pFrameYUV);
+        return -1;
+    }
     av_frame_free(&pFrameYUV);
 
     if(got_frame == 1){
         if (frameCnt % (15 * 60) == 0){
-                   FLOGE("Succeed to encode frame: %5d\tsize:%5d\n", frameCnt, encPkt.size);
+                   FLOGD("Succeed to encode frame: %5d\tsize:%5d\n", frameCnt, encPkt.size);
         }
         frameCnt++;
                encPkt.stream_index = vStream->index;
@@ -201,7 +217,10 @@ int FfmpegHelper::processFrame(uint8_t* data)
                if (pts_time > now_time)
                        av_usleep(pts_time - now_time);
 
-               ret = av_interleaved_write_frame(formatCtx, &encPkt);
+               if((ret = av_interleaved_write_frame(formatCtx, &encPkt)) < 0){
+            FLOGE("av_interleaved_write_frame - error: %s(%d)", av_err2str(ret), ret);
+            return -1;
+        }
                av_packet_unref(&encPkt);
     }
     av_free(outBuf);
@@ -212,13 +231,16 @@ int FfmpegHelper::close()
 {
     if(vStream)
         avcodec_close(vStream->codec);
-    avio_close(formatCtx->pb);
-    avformat_free_context(formatCtx);
+    if (formatCtx){
+        avio_close(formatCtx->pb);
+        avformat_free_context(formatCtx);
+    }
+    FLOGE("<----------- FfmpegHelper::close ");
     return 0;
 }
 
 
-jint FfmpegHelper::nativeInitialEncoder(JNIEnv *env, jclass cls, jint width, jint height, jstring url)
+jint FfmpegHelper::nativeInitEncoder(JNIEnv *env, jclass cls, jint width, jint height, jstring url)
 {
     const char* output = env->GetStringUTFChars(url, 0);
     int ret = 0;