java yuv编码为_Android中使用FFMPEG将yuv420p编码为h264

JNIEXPORT jbyteArray JNICALL

Java_com_uestc_smileteeth_view_recordvideo_RecordVideoLib_encodeVideoFrame(JNIEnv *env, jclass type,

jstring path1_,

jstring path2_,

jint frameNum,

jint width, jint height,

jintArray pts_) {

const char *path1 = (*env)->GetStringUTFChars(env, path1_, 0);

const char *path2 = (*env)->GetStringUTFChars(env, path2_, 0);

jint *pts = (*env)->GetIntArrayElements(env, pts_, NULL);

AVFormatContext *pFormatCtx;

AVOutputFormat *fmt;

AVStream *video_st;

AVCodecContext *pCodecCtx;

AVCodec *pCodec;

AVPacket pkt;

uint8_t *picture_buf;

AVFrame *pFrame;

int picture_size;

int y_size;

int framecnt = 0;

//FILE *in_file = fopen("src01_480x272.yuv", "rb"); //Input raw YUV data

FILE *in_file = fopen(path1, "rb"); //Input raw YUV data

int in_w = width, in_h = height; //Input data's width and height

//总帧数;

int framenum = frameNum; //Frames to encode

//输出路径;

const char *out_file = path2;

av_register_all();

//Method1.

pFormatCtx = avformat_alloc_context();

//Guess Format

fmt = av_guess_format(NULL, out_file, NULL);

pFormatCtx->oformat = fmt;

//Method 2.

//avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, out_file);

//fmt = pFormatCtx->oformat;

//Open output URL

if (avio_open(&pFormatCtx->pb, out_file, AVIO_FLAG_READ_WRITE) < 0) {

LOGI("Failed to open output file! ");

}

video_st = avformat_new_stream(pFormatCtx, 0);

//video_st->time_base.num = 1;

//video_st->time_base.den = 25;

if (video_st == NULL) {

}

//Param that must set

pCodecCtx = video_st->codec;

//pCodecCtx->codec_id =AV_CODEC_ID_HEVC;

pCodecCtx->codec_id = fmt->video_codec;

pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;

pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;

pCodecCtx->width = in_w;

pCodecCtx->height = in_h;

pCodecCtx->bit_rate = 30000000;

pCodecCtx->gop_size = 5;

pCodecCtx->time_base.num = 1;

pCodecCtx->time_base.den = 25;

//H264

pCodecCtx->me_range = 32;

//pCodecCtx->max_qdiff = 4;

//pCodecCtx->qcompress = 0.6;

pCodecCtx->qmin = 10;

pCodecCtx->qmax = 40;

//Optional Param

pCodecCtx->max_b_frames = 0;

// Set Option

AVDictionary *param = 0;

//H.264

if (pCodecCtx->codec_id == AV_CODEC_ID_H264) {

av_dict_set(&param, "preset", "slow", 0);

av_dict_set(&param, "tune", "zerolatency", 0);

//av_dict_set(&param, "profile", "main", 0);

}

//H.265

if (pCodecCtx->codec_id == AV_CODEC_ID_H265) {

av_dict_set(&param, "preset", "ultrafast", 0);

av_dict_set(&param, "tune", "zero-latency", 0);

}

//Show some Information

av_dump_format(pFormatCtx, 0, out_file, 1);

pCodec = avcodec_find_encoder(pCodecCtx->codec_id);

if (!pCodec) {

LOGI("Can not find encoder! ");

}

if (avcodec_open2(pCodecCtx, pCodec, &param) < 0) {

LOGI("Failed to open encoder! ");

}

pFrame = av_frame_alloc();

picture_size = avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);

picture_buf = (uint8_t *) av_malloc(picture_size);

avpicture_fill((AVPicture *) pFrame, picture_buf, pCodecCtx->pix_fmt, pCodecCtx->width,

pCodecCtx->height);

//Write File Header

avformat_write_header(pFormatCtx, NULL);

av_new_packet(&pkt, picture_size);

y_size = pCodecCtx->width * pCodecCtx->height;

for (int i = 0; i < framenum; i++) {

LOGI("完整视频正在编码第%d帧", i + 1);

//Read raw YUV data

if (fread(picture_buf, 1, y_size * 3 / 2, in_file) <= 0) {

LOGI("Failed to read raw data! ");

} else if (feof(in_file)) {

break;

}

pFrame->data[0] = picture_buf; // Y

pFrame->data[1] = picture_buf + y_size; // U

pFrame->data[2] = picture_buf + y_size * 5 / 4; // V

//PTS

pFrame->pts = pts[i];

LOGI("pts %"

PRId64

"\n", pFrame->pts);

int got_picture = 0;

//Encode

int ret = avcodec_encode_video2(pCodecCtx, &pkt, pFrame, &got_picture);

if (ret < 0) {

LOGI("Failed to encode! ");

}

if (got_picture == 1) {

framecnt++;

LOGI("Succeed to encode frame: %5d\tsize:%5d", framecnt, pkt.size);

pkt.stream_index = video_st->index;

ret = av_write_frame(pFormatCtx, &pkt);

av_free_packet(&pkt);

}

}

//Flush Encoder

int ret = flush_encoder(pFormatCtx, 0);

if (ret < 0) {

LOGI("Flushing encoder failed!");

}

//Write file trailer

av_write_trailer(pFormatCtx);

//Clean

if (video_st) {

avcodec_close(video_st->codec);

av_free(pFrame);

av_free(picture_buf);

}

avio_close(pFormatCtx->pb);

avformat_free_context(pFormatCtx);

fclose(in_file);

(*env)->ReleaseStringUTFChars(env, path1_, path1);

(*env)->ReleaseStringUTFChars(env, path2_, path2);

(*env)->ReleaseIntArrayElements(env, pts_, pts, 0);

}

int flush_encoder(AVFormatContext *fmt_ctx, unsigned int stream_index) {

int ret;

int got_frame;

AVPacket enc_pkt;

if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &

CODEC_CAP_DELAY))

return 0;

while (1) {

enc_pkt.data = NULL;

enc_pkt.size = 0;

av_init_packet(&enc_pkt);

ret = avcodec_encode_video2(fmt_ctx->streams[stream_index]->codec, &enc_pkt,

NULL, &got_frame);

av_frame_free(NULL);

if (ret < 0)

break;

if (!got_frame) {

ret = 0;

break;

}

LOGI("Flush Encoder: Succeed to encode 1 frame!\tsize:%5d", enc_pkt.size);

/* mux encoded frame */

ret = av_write_frame(fmt_ctx, &enc_pkt);

if (ret < 0)

break;

}

return ret;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值