#include <string.h> #include <android/log.h> #include <assert.h> #include <jni.h> #include <stdio.h> #include <stdint.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/socket.h> #include <sys/un.h> #include <errno.h> #include "include/libyuv.h" #define LOG_TAG "kylin_yuv_format" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) void yuv_rotate_90(uint8* des,uint8* src,int width,int height) { int n = 0; int hw = width / 2; int hh = height / 2; //copy y for(int j = 0; j < width;j++) { for(int i = height - 1; i >= 0; i--) { des[n++] = src[width * i + j]; } } //copy u uint8 *ptemp = src + width * height; for(int j = 0;j < hw;j++) { for(int i = hh - 1;i >= 0;i--) { des[n++] = ptemp[ hw*i + j ]; } } //copy v ptemp += width * height / 4; for(int j = 0; j < hw; j++) { for(int i = hh - 1;i >= 0;i--) { des[n++] = ptemp[hw*i + j]; } } } void yuv_rotate_180(uint8* des,uint8* src,int width,int height) { int n = 0; int hw = width / 2; int hh = height / 2; //copy y for(int j = height - 1; j >= 0; j--) { for(int i = width; i > 0; i--) { des[n++] = src[width*j + i]; } } //copy u uint8 *ptemp = src + width * height; for(int j = hh - 1;j >= 0; j--) { for(int i = hw; i > 0; i--) { des[n++] = ptemp[hw * j + i]; } } //copy v ptemp += width * height / 4; for(int j = hh - 1;j >= 0; j--) { for(int i = hw; i > 0; i--) { des[n++] = ptemp[hw * j + i]; } } } void yuv_rotate_270(uint8* des,uint8* src,int width,int height) { int n = 0; int hw = width / 2; int hh = height / 2; //copy y for(int j = width; j > 0; j--) { for(int i = 0; i < height;i++) { des[n++] = src[width*i + j]; } } //copy u uint8 *ptemp = src + width * height; for(int j = hw; j > 0;j--) { for(int i = 0; i < hh;i++) { des[n++] = ptemp[hw * i + j]; } } //copy v ptemp += width * height / 4; for(int j = hw; j > 0;j--) { for(int i = 0; i < hh;i++) { des[n++] = ptemp[hw * i + j]; } } } /* * Class: package_path/class_name * Method: native_rotate * Signature: ([BI[BIIII)I */ JNIEXPORT jint JNICALL native_rotate (JNIEnv *env, jobject obj, jbyteArray src,jbyteArray dst,jint src_width, jint src_height, jint mode) { LOGI("native_rotate %d",mode); jbyte* src_data = env->GetByteArrayElements( src, JNI_FALSE); LOGD("rotate src_data[0-7]=%d %d %d %d %d %d %d %d",src_data[0],src_data[1],src_data[2],src_data[3],src_data[4],src_data[5],src_data[6],src_data[7]); int src_len = env->GetArrayLength(src); LOGI("src_len:%d",src_len); jbyte *dst_data = env->GetByteArrayElements(dst, JNI_FALSE); int dst_len = env->GetArrayLength(dst); LOGI("dst_len:%d",dst_len); memset(dst_data,0,dst_len); if(mode ==90){ yuv_rotate_90((uint8 *)dst_data,(uint8 *)src_data,src_width,src_height); }else if(mode ==180){ yuv_rotate_180((uint8 *)dst_data,(uint8 *)src_data,src_width,src_height); }else if(mode ==270){ yuv_rotate_270((uint8 *)dst_data,(uint8 *)src_data,src_width,src_height); }else{ LOGE("Not support degree!!!"); } LOGD("rotate dst_data[0-7]=%d %d %d %d %d %d %d %d",dst_data[0],dst_data[1],dst_data[2],dst_data[3],dst_data[4],dst_data[5],dst_data[6],dst_data[7]); env->ReleaseByteArrayElements(src,src_data,0); env->ReleaseByteArrayElements(dst,dst_data,0); LOGI("native_rotate 2"); return 1; } jboolean _initialize(JNIEnv* env, jobject thiz, jobject weak_thiz) { return JNI_TRUE; } static JNINativeMethod gMethods[] = { {"native_rotate", "([B[BIII)I", (void*)native_rotate}, }; static int registerNativeMethods(JNIEnv* env , const char* className , JNINativeMethod* gMethods, int numMethods) { jclass clazz; clazz = env->FindClass(className); if (clazz == NULL) { return JNI_FALSE; } if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) { return JNI_FALSE; } return JNI_TRUE; } static int registerNatives(JNIEnv* env) { const char* kClassName = "com/package_path/class_name"; return registerNativeMethods(env, kClassName, gMethods, sizeof(gMethods) / sizeof(gMethods[0])); } JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; jint result = -1; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { return -1; } assert(env != NULL); if (!registerNatives(env)) { return -1; } result = JNI_VERSION_1_4; return result; }
该算法为Y、U、V三个分量拷贝方式做旋转,可作为验证或演示两种用途,不能满足性能要求。yuv数据算法可参照安卓源码库中的external\libyuv以及开源库ffmpeg。