X-Git-Url: http://47.100.26.94:8080/?a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjni%2FFfmpegHelper.cpp;h=3bd2f1016686a654cdff864d31fac2c49978bd00;hb=410441c06aa4257d7d9dcb1b581abb4017c67c50;hp=279341b346966156cbd9e4c8dd28c046a8103428;hpb=7a99b2b0d2cf8048e1d9dd7fae5ccf984a865b1e;p=rtmpclient.git diff --git a/app/src/main/jni/FfmpegHelper.cpp b/app/src/main/jni/FfmpegHelper.cpp index 279341b..3bd2f10 100644 --- a/app/src/main/jni/FfmpegHelper.cpp +++ b/app/src/main/jni/FfmpegHelper.cpp @@ -3,10 +3,11 @@ #include #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; +bool FfmpegHelper::isEncoderReady = false; FfmpegHelper::FfmpegHelper(JavaVM *vm, jclass cls) @@ -37,22 +38,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(&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 +63,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(); @@ -77,12 +80,14 @@ void FfmpegHelper::init() FLOGE("avformat_network_init, error:%s(%d)", av_err2str(ret), ret); } isInit = true; + isEncoderReady = false; } 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 +128,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 +147,38 @@ int FfmpegHelper::initEncoder(int width, int height, const char* outpath) return -1; } startTime = av_gettime(); + frameCnt = 0; + isEncoderReady = true; return 0; } + int FfmpegHelper::processFrame(uint8_t* data) { + if(!isEncoderReady){ + FLOGE("processFrame - isEncoderReady is false."); + return 0; + } 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 +186,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 +224,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 +238,17 @@ 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 "); + isEncoderReady = false; 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;