您的位置:首页 > 移动开发 > Android开发

android调用jni使用ffmeg把h264转yuv数据

2016-11-06 13:06 447 查看
jni代码部分:

#include <stdio.h>
#include <time.h>
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/log.h"
#include "libavutil/frame.h"

#ifdef ANDROID
#include <jni.h>
#include <android/log.h>
#define LOGE(format, ...)  __android_log_print(ANDROID_LOG_ERROR, "(>_<)", format, ##__VA_ARGS__)
#define LOGI(format, ...)  __android_log_print(ANDROID_LOG_INFO,  "(^_^)", format, ##__VA_ARGS__)
#else
#define LOGE(format, ...)  printf("(>_<) " format "\n", ##__VA_ARGS__)
#define LOGI(format, ...)  printf("(^_^) " format "\n", ##__VA_ARGS__)
#endif

AVFormatContext *pFormatCtx;
int             i, videoindex;
AVCodecContext  *pCodecCtx;
AVCodec         *pCodec;
AVFrame *pFrame;
uint8_t *out_buffer;
AVPacket packet;
int y_size;
int ret, got_picture;
struct SwsContext *img_convert_ctx;
int frame_cnt;
clock_t time_start, time_finish;
double  time_duration = 0.0;

char input_str[500]={0};
char info[1000]={0};
//Output FFmpeg's av_log()
void custom_log(void *ptr, int level, const char* fmt, va_list vl){
FILE *fp=fopen("/storage/emulated/0/av_log.txt","a+");
if(fp){
vfprintf(fp,fmt,vl);
fflush(fp);
fclose(fp);
}
}

JNIEXPORT jint JNICALL Java_com_aac_utils_DecodeYUV_init
(JNIEnv *env, jobject obj)
{
av_log_set_callback(custom_log);
av_register_all();
pCodec = avcodec_find_decoder(AV_CODEC_ID_H264);
pCodecCtx = avcodec_alloc_context3(pCodec);
if(pCodec==NULL){
LOGE("Couldn't find Codec.\n");
return -1;
}
if(avcodec_open2(pCodecCtx, pCodec,NULL)<0){
LOGE("Couldn't open codec.\n");
return -1;
}
pFrame= avcodec_alloc_frame();
pCodecCtx->flags |= CODEC_FLAG_LOW_DELAY;
pCodecCtx->debug |= FF_DEBUG_MMCO;
pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
}

JNIEXPORT jint JNICALL Java_com_aac_utils_DecodeYUV_decode
(JNIEnv *env, jobject obj, jbyteArray jin_packet,jbyteArray jout_packet,jint jwidth,jint jheight)
{
av_init_packet(&packet);
unsigned char  *in_array =(*env)->GetByteArrayElements(env,jin_packet, 0);
jbyte *out_array =(*env)->GetByteArrayElements(env,jout_packet, 0);
jsize  *length = (*env)->GetArrayLength(env,jin_packet);

packet.size = length;
packet.data = in_array;
int width =jwidth;
int height = jheight;

ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, &packet);
av_free_packet(&packet);
if(ret < 0){
LOGE("Decode Error.\n");
return -1;
}

if(got_picture){
y_size=width*height;

unsigned char *buf = (unsigned char *)malloc(y_size*3/2);
memset(buf, 0, y_size*3/2);
memcpy(buf,pFrame->data[0], y_size);
memcpy(buf+y_size,pFrame->data[1], y_size / 4);
memcpy(buf+y_size*5/4,pFrame->data[2], y_size / 4);

jbyte *buff;
buff = (jbyte*)buf;
(*env)->ReleaseByteArrayElements(env,jout_packet, out_array, 0);
(*env)->SetByteArrayRegion(env,jout_packet, 0, y_size*3/2, buff);

free(buf);
}

//flush decoder
//FIX: Flush Frames remained in Codec
return 0;
}
JNIEXPORT jint JNICALL Java_com_aac_utils_DecodeYUV_close
(JNIEnv *env, jobject obj)
{
av_frame_free(&pFrame);
avcodec_close(pCodecCtx);
av_free(pCodecCtx);
}


java调用函数.

public class DecodeYUV {
//JNI
public static native int close();
public static native int init();
public static native int decode(byte[] inarray,byte[] outarray,int width,int height);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android