概述
最近做项目的时候,领导安排一个任务,让测试一下,用ffmpeg中的yuv转bgr函数的速度。之前编译so库大部分都是用eclipse,本次博主花了两天时间,在Android studio上编译并运行,在此做一下记录。
设置Android Studio ndk
1、打开setings->Tools->External Toos 点击+号新建NDK分组及javah 与ndk-build项。
2、javah 及ndk-build配置如下图
配置完毕后点击apply->Ok,配置完毕后,在项目上点击右键便能看到NDK命令组和javah 及ndk-build命令。
说明:javah 命令使用来生成头文件,ndk-build 命令使用编译原生代码生成so。
新建编译项目并配置Gradle
1、在src main下面新建jni目录,目录如下
2、gradle的android域中配置不使用Android studio自动生成的.mk文件
sourceSets {
main {
//禁用as自动生成mk
jni.srcDirs = []
jniLibs.srcDirs = ['src/main/libs']
}
}
编译生成so
点击项目右键NDK->ndk-build (左键点击)
此时便生成了so 。希望对您有所帮助!
补充:jni目录内容
Android项目测试代码
MainActivity.java
package cm.opengles;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import com.interjoy.skfaceproject_zwc.utils.Utils;
import java.io.IOException;
import java.util.List;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
public class MainActivity extends AppCompatActivity implements Camera.PreviewCallback{
private final String TAG = Main1Activity.class.getSimpleName();
public final static int WIDTH = 1920;
public final static int HEIGHT = 1080;
public final static int SIZE = WIDTH * HEIGHT * 3 / 2;
private static int CAMERA_FACING_BACK_FRONT = 0;//默认是后置camera
private static final boolean DEBUG = false;
public byte[] mData;
private GLSurfaceView view;
private Camera mCamera;
private WakeLock wlock;
private int wView;
private int hView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 采集图像是640*480,所以预览窗口保证4:3
int wScreen = Utils.getScreenWidth(this);
int hScreen = Utils.getScreenHeight(this);
float ratio = 1.0f * wScreen / hScreen;
if (ratio >= 0.75f) {
wView = wScreen;
hView = (int) (0.75f * wScreen + 0.5f);
} else {
hView = hScreen;
wView = (int) (1.25f * hScreen + 0.5f);
}
PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
wlock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "fb");
wlock.acquire();
view = new GLSurfaceView(Main1Activity.this);
view.setEGLContextClientVersion(2);
view.setRenderer(new GLSurfaceView.Renderer() {
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
openCamera(0);
mCamera.startPreview();
CmOpenGLES.init(WIDTH, HEIGHT);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
//CmOpenGLES.changeLayout(width, height);
GLES20.glViewport(0, 0,wView , hView);
}
@Override
public void onDrawFrame(GL10 gl) {
if (mData != null)
{
CmOpenGLES.drawFrame(mData, SIZE);
}
}
});
setContentView(view);
}
/**
* 相机初始化
*/
private void initCamera() {
if (mCamera != null) {
try {
Camera.Parameters params = mCamera.getParameters();
params.setExposureCompensation(0);
if (getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
params.set("orientation", "portrait");
mCamera.setDisplayOrientation(90);
params.setRotation(90);
} else {
params.set("orientation", "landscape");
mCamera.setDisplayOrientation(0);
params.setRotation(0);
}
params.setPreviewSize(WIDTH, HEIGHT);
// 实现自动对焦
List<String> focusModes = params.getSupportedFocusModes();
if (focusModes.contains("continuous-video")) {
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
mCamera.setParameters(params);
mCamera.getParameters().setPreviewFormat(ImageFormat.NV21);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 打开摄像头
*/
public void openCamera(int id) {
int mCameraCount = Camera.getNumberOfCameras();
int curCameraIndex;
if (mCameraCount > 1) {
curCameraIndex = Camera.CameraInfo.CAMERA_FACING_FRONT;
CAMERA_FACING_BACK_FRONT = 1;
} else {
curCameraIndex = Camera.CameraInfo.CAMERA_FACING_BACK;
CAMERA_FACING_BACK_FRONT = 0;
}
mCamera = Camera.open(curCameraIndex);
initCamera();
try {
mCamera.addCallbackBuffer(mData);
mCamera.setPreviewCallback(Main1Activity.this);
mCamera.setPreviewTexture(new SurfaceTexture(10));
} catch (IOException e) {
Log.w(TAG, "setPreviewTexture error e = " + e.getMessage());
}
}
@Override
protected void onResume() {
super.onResume();
view.onResume();
}
@Override
protected void onPause() {
super.onPause();
view.onPause();
mCamera.stopPreview();
wlock.release();
}
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
if (DEBUG)
{
Log.i(TAG, "onPreviewFrame()");
}
mData = data;
camera.addCallbackBuffer(data);
}
}
CmOpenGLES.java
package cm.opengles;
public class CmOpenGLES {
static {
System.loadLibrary("CameraOpenGLES");
}
public static native void init(int width, int height);
public static native void release();
public static native void changeLayout(int width, int height);
public static native void drawFrame(byte[] data, int size);
}