//权限请求和切换摄像头
class CameraActivity : Activity() {
private var surface: CodecSurface? = null
private var btn: Button? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED
) {
initView()
} else {
ActivityCompat.requestPermissions(
this, arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
), 0
)
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
initView()
}
private var curCameraId: Int = 0
private fun initView() {
setContentView(R.layout.activity_codec)
btn = findViewById
//界面刷新和设置渲染模式
public class CodecSurface constructor(context: Context, att: AttributeSet?) :
GLSurfaceView(context, att),SurfaceTexture.OnFrameAvailableListener{
constructor(context: Context) : this(context, null)
private var renderer: CodecRender? = null
init {
setEGLContextClientVersion(2)
renderer = CodecRender(this)
renderer!!.setFrameListener(this)
renderer
preserveEGLContextOnPause=true
setRenderer(renderer)
renderMode = RENDERMODE_WHEN_DIRTY
}
public fun changeCameraId(id: Int) {
renderer!!.setCameraId(id)
}
public fun release() {
renderer!!.release()
}
override fun onFrameAvailable(surfaceTexture: SurfaceTexture?) {
requestRender()
}
}
//camera的选用和绘画操作
class CodecRender(val surface: CodecSurface) : GLSurfaceView.Renderer {
private val TAG: String = "CodecRender"
var textureId: Int = 0;
private var filter: OesFilter? = null
var surfaceTexture: SurfaceTexture? = null
private var cameraId: Int = 0;
private var listener: SurfaceTexture.OnFrameAvailableListener? = null
init {
filter = OesFilter()
}
override fun onDrawFrame(gl: GL10?) {
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f)
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT or GLES20.GL_DEPTH_BUFFER_BIT)
surfaceTexture!!.updateTexImage()
if (cameraUtil!!.isOpenFinish) {
filter!!.drawFrame()
}
}
override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
GLES20.glViewport(0, 0, width, height);
}
override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
textureId = filter!!.createTextureId()
surfaceTexture = SurfaceTexture(textureId)
surfaceTexture!!.setOnFrameAvailableListener {
surface!!.requestRender()
}
cameraUtil!!.setTexture(surfaceTexture!!)
setCameraId(cameraId);
filter!!.setTextureId(textureId)
filter!!.create(cameraId)
}
public fun setCameraId(id: Int) {
cameraId = id;
filter!!.setCoodData(cameraId)
cameraUtil!!.open(cameraId.toString())
}
private var cameraUtil: CameraUtil? = null
public fun release() {
surfaceTexture!!.setOnFrameAvailableListener(null)
surfaceTexture!!.release()
surfaceTexture = null
cameraUtil!!.close()
}
public fun setFrameListener(listener: SurfaceTexture.OnFrameAvailableListener) {
this.listener = listener;
}
init {
cameraUtil = CameraUtil(surface.context)
}
}
//低版本camera
class CameraUtil(val context: Context) : CameraState {
private val TAG: String = "CameraUtil"
private var textureView: SurfaceTexture? = null
private var myCamera: Camera? = null
private var holder: SurfaceHolder? = null
private var isOpenSuccess = true
public fun setTexture(view: SurfaceTexture) {
textureView = view;
}
public fun setDiaPlay(holder: SurfaceHolder) {
this.holder = holder
}
public fun open(cameraId: String) {
try {
isOpenSuccess = false
close()
myCamera = Camera.open(cameraId.toInt())
val mParameters = myCamera!!.getParameters();
//设置将保存的图片旋转90°(竖着拍摄的时候)
var PreviewWidth = 0
var PreviewHeight = 0
val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager;//获取窗口的管理器
val display = wm.defaultDisplay;//获得窗口里面的屏幕
val parameters = myCamera!!.getParameters();
// 选择合适的预览尺寸
val sizeList = mParameters.getSupportedPreviewSizes();
if (sizeList.size > 1) {
val itor= sizeList.iterator();
while (itor.hasNext()) {
val cur = itor.next();
if (cur.width >= PreviewWidth
&& cur.height >= PreviewHeight) {
PreviewWidth = cur.width;
PreviewHeight = cur.height;
break;
}
}
}
LogUtil.e("-->width=$PreviewWidth height=$PreviewHeight")
mParameters.setPreviewSize(PreviewWidth, PreviewHeight); //获得摄像区域的大小
mParameters.set("jpeg-quality", 85);//设置照片质量
mParameters.setRotation(90);
myCamera!!.setParameters(mParameters)//如果出现异常则为参数问题,逐个删减
myCamera!!.setDisplayOrientation(90)
myCamera!!.setPreviewTexture(textureView)
myCamera!!.setPreviewCallback(object : Camera.PreviewCallback {
override fun onPreviewFrame(data: ByteArray?, camera: Camera?) {
try {
isOpenSuccess = true
camera!!.addCallbackBuffer(data)
} catch (e: Exception) {
e.printStackTrace()
}
}
})
myCamera!!.startPreview()
} catch (e: Exception) {
e.printStackTrace()
}
}
public fun close() {
myCamera?.setPreviewCallback(null)
myCamera?.stopPreview()
myCamera?.release()
myCamera = null
}
override fun isOpenFinish(): Boolean {
return isOpenSuccess
}
}
//5.0以上的camear
class Camera2Util constructor(private val context: Context) : CameraState {
private val TAG: String = "CameraUtil"
private var cameraDevice: CameraDevice? = null
private var cameraManager: CameraManager? = null
private var cameraBuild: CaptureRequest.Builder? = null
private var isOpenSuccess = true
private var stateCallback: CameraDevice.StateCallback = object : CameraDevice.StateCallback() {
override fun onOpened(camera: CameraDevice) {
cameraDevice = camera
try {
val surface: Surface = Surface(textureView)
cameraBuild = cameraDevice!!.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
cameraBuild!!.set(
CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH
)
cameraBuild!!.set(
CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE
)
cameraBuild!!.addTarget(surface)
cameraDevice!!.createCaptureSession(listOf(surface), sessionCallback, camearHandler)
} catch (e: Exception) {
e.printStackTrace()
}
}
override fun onDisconnected(camera: CameraDevice) {
}
override fun onError(camera: CameraDevice, error: Int) {
LogUtil.e(TAG, "error=$error")
}
}
private var sessionCallback: CameraCaptureSession.StateCallback = object :
CameraCaptureSession.StateCallback() {
override fun onConfigureFailed(session: CameraCaptureSession) {
}
override fun onConfigured(session: CameraCaptureSession) {
isOpenSuccess = true
session.setRepeatingRequest(cameraBuild!!.build(), captureCallback, camearHandler)
}
}
private var captureCallback: CameraCaptureSession.CaptureCallback = object :
CameraCaptureSession.CaptureCallback() {
override fun onCaptureCompleted(
session: CameraCaptureSession,
request: CaptureRequest,
result: TotalCaptureResult
) {
super.onCaptureCompleted(session, request, result)
}
override fun onCaptureFailed(
session: CameraCaptureSession,
request: CaptureRequest,
failure: CaptureFailure
) {
super.onCaptureFailed(session, request, failure)
}
override fun onCaptureProgressed(
session: CameraCaptureSession,
request: CaptureRequest,
partialResult: CaptureResult
) {
super.onCaptureProgressed(session, request, partialResult)
}
}
private val camearHandler = object : Handler() {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
}
}
init {
cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
}
public fun open(cameraId: String) {
try {
isOpenSuccess = false
if (ActivityCompat.checkSelfPermission(
context,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED
) {
cameraDevice?.close()
cameraManager!!.openCamera(cameraId, stateCallback, camearHandler)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
private var textureView: SurfaceTexture? = null;
public fun setTexture(view: SurfaceTexture) {
textureView = view;
}
public fun close() {
cameraDevice!!.close()
}
override fun isOpenFinish(): Boolean {
return isOpenSuccess
}
}
//预览摄像头数据,后续与其他滤镜混合
class OesFilter {
private val TAG: String = "OesFilter"
private var positionFloat: FloatBuffer? = null
private var coodFloat: FloatBuffer? = null
private var glHPosition: Int = 0
private var glHCoordinate: Int = 0
private var glHTexture: Int = 0
private var mHCoord: Int = 0
private var mHMatrix: Int = 0
private var coordinate: FloatArray? = null
private var textureId: Int = 0
private var programsId: Int = 0
private val vertexPosition = floatArrayOf(
-1.0f, 1.0f,
-1.0f, -1.0f,
1.0f, 1.0f,
1.0f, -1.0f
)
public fun create(cameraId: Int) {
setCoodData(cameraId)
val frag_id = createShader(fragmentShaderCode, GLES20.GL_FRAGMENT_SHADER)
val vertex_id = createShader(vertexShaderCode, GLES20.GL_VERTEX_SHADER)
programsId = GLES20.glCreateProgram();
GLES20.glAttachShader(programsId, frag_id)
GLES20.glAttachShader(programsId, vertex_id)
GLES20.glLinkProgram(programsId)
val linkState = IntArray(1)
GLES20.glGetProgramiv(programsId, GLES20.GL_LINK_STATUS, linkState, 0)
LogUtil.e(TAG, "state=${linkState[0]} programsId=$programsId")
if (linkState[0] == 0) {
LogUtil.e(
TAG,
"Could not link program: "
)
LogUtil.e(
TAG,
GLES20.glGetProgramInfoLog(programsId)
)
GLES20.glDeleteProgram(programsId)
programsId = 0;
}
}
private fun userProgram(programsId: Int) {
GLES20.glUseProgram(programsId)
var bb: ByteBuffer = ByteBuffer.allocateDirect(vertexPosition.size * 4)
bb.order(ByteOrder.nativeOrder())
positionFloat = bb.asFloatBuffer()
positionFloat!!.put(vertexPosition)
positionFloat!!.position(0)
var cbb: ByteBuffer = ByteBuffer.allocateDirect(coordinate!!.size * 4)
cbb.order(ByteOrder.nativeOrder())
coodFloat = cbb.asFloatBuffer()
coodFloat!!.put(coordinate)
coodFloat!!.position(0)
glHPosition = GLES20.glGetAttribLocation(programsId, "vPosition")
glHCoordinate = GLES20.glGetAttribLocation(programsId, "vTextureCoordinate")
glHTexture = GLES20.glGetUniformLocation(programsId, "vTexture")
mHCoord = GLES20.glGetAttribLocation(programsId, "vCoord")
mHMatrix = GLES20.glGetUniformLocation(programsId, "vMatrix")
}
public fun createTextureId(): Int {
val texture = IntArray(1)
GLES20.glGenTextures(1, texture, 0)
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texture[0])
GLES20.glTexParameterf(
GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_MIN_FILTER,
GL10.GL_LINEAR.toFloat()
)
GLES20.glTexParameterf(
GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_MAG_FILTER,
GL10.GL_LINEAR.toFloat()
)
GLES20.glTexParameterf(
GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_WRAP_S,
GL10.GL_CLAMP_TO_EDGE.toFloat()
)
GLES20.glTexParameterf(
GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_WRAP_T,
GL10.GL_CLAMP_TO_EDGE.toFloat()
)
return texture[0]
}
public fun setTextureId(id: Int) {
textureId = id
}
private fun createShader(str: String, style: Int): Int {
val shader: Int = GLES20.glCreateShader(style);
GLES20.glShaderSource(shader, str)
GLES20.glCompileShader(shader)
val state = IntArray(1)
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, state, 0)
if (state[0] == 0) {
LogUtil.e(TAG, "Could not compile shader " + shader + ":");
LogUtil.e(TAG, " " + GLES20.glGetShaderInfoLog(shader));
GLES20.glDeleteShader(shader)
throw IllegalStateException("Could not compile shader")
}
return shader;
}
private val vertexShaderCode = "attribute vec4 vPosition;" +
"attribute vec2 vCoord;" +
"varying vec2 vTextureCoordinate;" +
"uniform mat4 vMatrix;" +
"void main() {" +
" gl_Position = vMatrix*vPosition;" +
"vTextureCoordinate = vCoord;" +
"}"
private val fragmentShaderCode = "#extension GL_OES_EGL_image_external : require" +
"precision mediump float;" +
"varying vec2 vTextureCoordinate;" +
"uniform samplerExternalOES vTexture;" +
"void main() {" +
" gl_FragColor = texture2D(vTexture, vTextureCoordinate);" +
"}"
private val matrix: FloatArray = LogUtil.getOriginalMatrix()
public fun drawFrame() {
userProgram(programsId)
GLES20.glEnableVertexAttribArray(glHPosition)
GLES20.glEnableVertexAttribArray(mHCoord)
GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId)
GLES20.glUniform1i(glHTexture, 0)
GLES20.glVertexAttribPointer(glHPosition, 2, GLES20.GL_FLOAT, false, 0, positionFloat)
GLES20.glVertexAttribPointer(mHCoord, 2, GLES20.GL_FLOAT, false, 0, coodFloat)
GLES20.glUniformMatrix4fv(mHMatrix, 1, false, matrix, 0)
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4)
GLES20.glDisableVertexAttribArray(glHPosition)
GLES20.glDisableVertexAttribArray(mHCoord)
}
public fun setCoodData(cameraId: Int) {
coordinate = if (cameraId == 0) {//后置摄像头
floatArrayOf(
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f
)
} else {//前置摄像头
floatArrayOf(
1.0f, 1.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f
)
}
}
}