android jni h264编码,Android使用FFMPEG将H264解码为yuv420p

JNIEXPORT jbyteArray JNICALL

Java_com_uestc_smileteeth_view_recordvideo_RecordVideoLib_decodeVideo(JNIEnv *env, jclass type,

jstring input_,

jstring output_

) {

const char *input = (*env)->GetStringUTFChars(env, input_, 0);

const char *output = (*env)->GetStringUTFChars(env, output_, 0);

AVFormatContext *pFormatCtx;

int i, videoindex;

AVCodecContext *pCodecCtx;

AVCodec *pCodec;

AVFrame *pFrame, *pFrameYUV;

uint8_t *out_buffer;

AVPacket *packet;

int y_size;

int ret, got_picture;

struct SwsContext *img_convert_ctx;

FILE *fp_yuv;

int frame_cnt;

clock_t time_start, time_finish;

double time_duration = 0.0;

char info[1000] = {0};

av_register_all();

avformat_network_init();

pFormatCtx = avformat_alloc_context();

if (avformat_open_input(&pFormatCtx, input, NULL, NULL) != 0) {

LOGI("Couldn't open input stream.\n");

return -1;

}

if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {

LOGI("Couldn't find stream information.\n");

return -1;

}

videoindex = -1;

for (i = 0; i < pFormatCtx->nb_streams; i++)

if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {

videoindex = i;

break;

}

if (videoindex == -1) {

LOGI("Couldn't find a video stream.\n");

return -1;

}

pCodecCtx = pFormatCtx->streams[videoindex]->codec;

pCodec = avcodec_find_decoder(pCodecCtx->codec_id);

if (pCodec == NULL) {

LOGI("Couldn't find Codec.\n");

return -1;

}

if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {

LOGI("Couldn't open codec.\n");

return -1;

}

pFrame = av_frame_alloc();

pFrameYUV = av_frame_alloc();

out_buffer = (unsigned char *) av_malloc(

av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1));

av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, out_buffer,

AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1);

packet = (AVPacket *) av_malloc(sizeof(AVPacket));

img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,

pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P,

SWS_BICUBIC, NULL, NULL, NULL);

sprintf(info, "[Input ]%s\n", input);

sprintf(info, "%s[Output ]%s\n", info, output);

sprintf(info, "%s[Format ]%s\n", info, pFormatCtx->iformat->name);

sprintf(info, "%s[Codec ]%s\n", info, pCodecCtx->codec->name);

sprintf(info, "%s[Resolution]%dx%d\n", info, pCodecCtx->width, pCodecCtx->height);

fp_yuv = fopen(output, "wb+");

if (fp_yuv == NULL) {

printf("Cannot open output file.\n");

return -1;

}

frame_cnt = 0;

time_start = clock();

while (av_read_frame(pFormatCtx, packet) >= 0) {

if (packet->stream_index == videoindex) {

ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);

if (ret < 0) {

LOGI("Decode Error.\n");

return -1;

}

if (got_picture) {

sws_scale(img_convert_ctx, (const uint8_t *const *) pFrame->data, pFrame->linesize,

0, pCodecCtx->height,

pFrameYUV->data, pFrameYUV->linesize);

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

fwrite(pFrameYUV->data[0], 1, y_size, fp_yuv); //Y

fwrite(pFrameYUV->data[1], 1, y_size / 4, fp_yuv); //U

fwrite(pFrameYUV->data[2], 1, y_size / 4, fp_yuv); //V

//Output info

char pictype_str[10] = {0};

switch (pFrame->pict_type) {

case AV_PICTURE_TYPE_I:

sprintf(pictype_str, "I");

break;

case AV_PICTURE_TYPE_P:

sprintf(pictype_str, "P");

break;

case AV_PICTURE_TYPE_B:

sprintf(pictype_str, "B");

break;

default:

sprintf(pictype_str, "Other");

break;

}

LOGI("Frame Index: %5d. Type:%s", frame_cnt, pictype_str);

frame_cnt++;

}

}

av_free_packet(packet);

}

//flush decoder

//FIX: Flush Frames remained in Codec

while (1) {

ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);

if (ret < 0)

break;

if (!got_picture)

break;

sws_scale(img_convert_ctx, (const uint8_t *const *) pFrame->data, pFrame->linesize, 0,

pCodecCtx->height,

pFrameYUV->data, pFrameYUV->linesize);

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

fwrite(pFrameYUV->data[0], 1, y_size, fp_yuv); //Y

fwrite(pFrameYUV->data[1], 1, y_size / 4, fp_yuv); //U

fwrite(pFrameYUV->data[2], 1, y_size / 4, fp_yuv); //V

//Output info

char pictype_str[10] = {0};

switch (pFrame->pict_type) {

case AV_PICTURE_TYPE_I:

sprintf(pictype_str, "I");

break;

case AV_PICTURE_TYPE_P:

sprintf(pictype_str, "P");

break;

case AV_PICTURE_TYPE_B:

sprintf(pictype_str, "B");

break;

default:

sprintf(pictype_str, "Other");

break;

}

LOGI("Frame Index: %5d. Type:%s", frame_cnt, pictype_str);

frame_cnt++;

}

time_finish = clock();

time_duration = (double) (time_finish - time_start);

sprintf(info, "%s[Time ]%fms\n", info, time_duration);

sprintf(info, "%s[Count ]%d\n", info, frame_cnt);

sws_freeContext(img_convert_ctx);

fclose(fp_yuv);

av_frame_free(&pFrameYUV);

av_frame_free(&pFrame);

avcodec_close(pCodecCtx);

avformat_close_input(&pFormatCtx);

(*env)->ReleaseStringUTFChars(env, input_, input);

(*env)->ReleaseStringUTFChars(env, output_, output);

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值