#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;
+bool FfmpegHelper::isEncoderReady = false;
FfmpegHelper::FfmpegHelper(JavaVM *vm, jclass cls)
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);
}
{
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();
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;
}
//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;
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 -1;
+ }
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;
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;
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);
int FfmpegHelper::close()
{
- if(vStream)
+ if(vStream){
avcodec_close(vStream->codec);
- avio_close(formatCtx->pb);
- avformat_free_context(formatCtx);
+ vStream = NULL;
+ }
+
+ if (formatCtx){
+ avio_close(formatCtx->pb);
+ avformat_free_context(formatCtx);
+ formatCtx = NULL;
+ }
+ 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;