android照片美颜项目_《Android 美颜类相机开发汇总》第一章 Android OpenGLES 相机预览...

SurfaceView + OpenGLES 预览相机

使用OpenGLES 预览相机,我们可以通过GLSurfaceView 来预览相机。GLSurfaceView封装了EGLContext。关于GLSurfaceView的源码里面,GLThread作为单独的线程处理OpenGL的绘制操作,但是这里有个问题,我们可以看看GLThread里面的循环:

while (true) {

synchronized (sGLThreadManager) {

while (true) {

... // 处理是否需要刷新

sGLThreadManager.wait();

}

} // end of synchronized(sGLThreadManager)

if (event != null) {

event.run();

event = null;

continue;

}

...

}

内循环是用来判断是否需要走绘制循环。当使用RENDERMODE_WHEN_DIRTY而非RENDERMODE_CONTINUOUSLY时,如果我们不主动调用requestRender绘制的话,它会一直在内部等待。然后另外一点就是,当我们调用queueEvent方法过多的时候,会导致event事件过多,然后需要不断地循环处理event事件,最终并没有走到刷新画面的流程。也就是说,为了保证得到更高的fps,我们需要解决这个问题。还有另外一个问题就是GLSurfaceView 中的EGL环境有可能会丢失重建的情况,对后续利用SharedContext做录制处理有影响。

因此,我没有使用GLSurfaceView来做绘制操作,用另外一个Looper线程单独处理OpenGLES 的纹理资源加载、渲染等操作。放弃使用GLSurfaceView 的另外一大原因是,为了利用SharedContext实现无丢帧录制视频的功能,GLSurfaceView 有可能会在中途释放并重新创建EGLContext,导致SharedContext失效,录制失败的情况。关于这个的话,可以参考grafika,里面有issue讨论过这个问题。

关于SurfaceView + OpenGLES 预览相机,可以参考本人的文章:

Android Camera SurfaceView OpenGLES 预览

这篇文章是很久之前写的,现在CainCamera开源项目已经发生了比较大的改变。这里还是重新介绍一遍吧。不过这次应该是最后一次大改动了,相机部分的功能基本已经完成,只剩一些小功能没有实现而已,而且暂时也不会再更新相机部分的功能了。

渲染线程 —— HandlerThread

通过HandlerThread 创建EGLContext绑定的渲染线程,如下:

class RenderThread extends HandlerThread implements SurfaceTexture.OnFrameAvailableListener,

Camera.PreviewCallback {

private static final String TAG = "RenderThread";

private static final boolean VERBOSE = false;

// 操作锁

private final Object mSynOperation = new Object();

// 更新帧的锁

private final Object mSyncFrameNum = new Object();

private final Object mSyncFence = new Object();

private boolean isPreviewing = false; // 是否预览状态

private boolean isRecording = false; // 是否录制状态

private boolean isRecordingPause = false; // 是否处于暂停录制状态

// EGL共享上下文

private EglCore mEglCore;

// 预览用的EGLSurface

private WindowSurface mDisplaySurface;

private int mInputTexture;

private int mCurrentTexture;

private SurfaceTexture mSurfaceTexture;

// 矩阵

private final float[] mMatrix = new float[16];

// 预览回调

private byte[] mPreviewBuffer;

// 输入图像大小

private int mTextureWidth, mTextureHeight;

// 可用帧

private int mFrameNum = 0;

// 渲染Handler回调

private RenderHandler mRenderHandler;

// 计算帧率

private FrameRateMeter mFrameRateMeter;

// 上下文

private Context mContext;

// 正在拍照

private volatile boolean mTakingPicture;

// 预览参数

private CameraParam mCameraParam;

// 渲染管理器

private RenderManager mRenderManager;

public RenderThread(Context context, String name) {

super(name);

mContext = context;

mCameraParam = CameraParam.getInstance();

mRenderManager = RenderManager.getInstance();

mFrameRateMeter = new FrameRateMeter();

}

/**

* 设置预览Handler回调

* @param handler

*/

public void setRenderHandler(RenderHandler handler) {

mRenderHandler = handler;

}

@Override

public void onFrameAvailable(SurfaceTexture surfaceTexture) {

}

private long time = 0;

@Override

public void onPreviewFrame(byte[] data, Camera camera) {

synchronized (mSynOperation) {

if (isPreviewing || isRecording) {

mRenderHandler.sendMessage(mRenderHandler

.obtainMessage(RenderHandler.MSG_PREVIEW_CALLBACK, data));

}

}

if (mPreviewBuffer != null) {

camera.addCallbackBuffer(mPreviewBuffer);

}

// 计算fps

if (mRenderHandler != null && mCameraParam.showFps) {

mRenderHandler.sendEmptyMessage(RenderHandler.MSG_CALCULATE_FPS);

}

if (VERBOSE) {

Log.d("onPreviewFrame", "update time = " + (System.currentTimeMillis() - time));

time = System.currentTimeMillis();

}

}

/**

* 预览回调

* @param data

*/

void onPreviewCallback(byte[] data) {

if (mCameraParam.cameraCallback != null) {

mCameraParam.cameraCallback.onPreviewCallback(data);

}

}

/**

* Surface创建

* @param holder

*/

void surfaceCreated(SurfaceHolder holder) {

mEglCore = new EglCore(null, EglCore.FLAG_RECORDABLE);

mDisplaySurface = new WindowSurface(mEglCore, holder.getSurface(), false);

mDisplaySurface.makeCurrent();

GLES30.glDisable(GLES30.GL_DEPTH_TEST);

GLES30.glDisable(GLES30.GL_CULL_FACE);

// 渲染器初始化

mRenderManager.init(mContext);

mInputTexture = OpenGLUtils.createOESTexture();

mSurfaceTexture = new SurfaceTexture(mInputTexture);

mSurfaceTexture.setOnFrameAvailableListener(this);

// 打开相机

openCamera();

}

/**

* Surface改变

* @param width

* @param height

*/

void surfaceChanged(int width, int height) {

mRenderManager.setDisplaySize(width, height);

startPreview();

}

/**

* Surface销毁

*/

void surfaceDestroyed() {

mTakingPicture = false;

mRenderManager.release();

releaseCamera();

if (mSurfaceTexture != null) {

mSurfaceTexture.release();

mSurfaceTexture = null;

}

if (mDisplaySurface != null) {

mDisplaySurface.release();

mDisplaySurface = null;

}

if (mEglCore != null) {

mEglCore.release();

mEglCore = null;

}

}

/**

* 绘制帧

*/

void drawFrame() {

// 如果存在新的帧,则更新帧

synchronized (mSyncFrameNum) {

synchronized (mSyncFence) {

if (mSurfaceTexture != null) {

while (mFrameNum != 0) {

mSurfaceTexture.updateTexImage();

--mFrameNum;

}

} else {

return;

}

}

}

// 切换渲染上下文

mDisplaySurface.makeCurrent();

mSurfaceTexture.getTransformMatrix(mMatrix);

// 绘制渲染

mCurrentTexture = mRenderManager.drawFrame(mInputTexture, mMatrix);

// 是否绘制人脸关键点

mRenderManager.drawFacePoint(mCurrentTexture);

// 显示到屏幕

mDisplaySurface.swapBuffers();

// 执行拍照

if (mCameraParam.isTakePicture && !mTakingPicture) {

synchronized (mSyncFence) {

mTakingPicture = true;

mRenderHandler.sendEmptyMessage(RenderHandler.MSG_TAKE_PICTURE);

}

}

// 是否处于录制状态

if (isRecording && !isRecordingPause) {

HardcodeEncoder.getInstance().frameAvailable();

HardcodeEncoder.getInstance()

.drawRecorderFrame(mCurrentTexture, mSurfaceTexture.getTimestamp());

}

}

/**

* 拍照

*/

void takePicture() {

synchronized (mSyncFence) {

ByteBuffer buffer = mDisplaySurface.getCurrentFrame();

mCameraParam.captureCallback.onCapture(buffer,

mDisplaySurface.getWidth(), mDisplaySurface.getHeight());

mTakingPicture = false;

mCameraParam.isTakePicture = false;

}

}

/**

* 计算fps

*/

void calculateFps() {

// 帧率回调

if ((mCameraParam).fpsCallback != null) {

mFrameRateMeter.drawFrameCount();

(mCameraParam).fpsCallback.onFpsCallback(mFrameRateMeter.getFPS());

}

}

/**

* 计算imageView 的宽高

*/

private void calculateImageSize() {

if (mCameraParam.orientation == 90 || mCameraParam.orientation == 270) {

mTextureWidth = mCameraParam.previewHeight;

mTextureHeight = mCameraParam.previewWidth;

} else {

mTextureWidth = mCameraParam.previewWidth;

mTextureHeight = mCameraParam.previewHeight;

}

mRenderManager.setTextureSize(mTextureWidth, mTextureHeight);

}

/**

* 切换边框模糊

* @param en

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值