Commit b97bd49c authored by 马乐's avatar 马乐

融合图全屏

parent 59027733
......@@ -38,7 +38,8 @@
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
android:exported="true"
android:screenOrientation="landscape">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
......@@ -47,7 +48,8 @@
</activity>
<service android:name=".presentation.MultiScreenService"
android:enabled="true"
android:exported="true"/>
android:exported="true"
android:screenOrientation="landscape"/>
</application>
</manifest>
\ No newline at end of file
......@@ -12,6 +12,8 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.arcsoft.imageutil.ArcSoftImageFormat
import com.arcsoft.imageutil.ArcSoftImageUtil
import com.arcsoft.visdrive.avmsdk.ArcErrorInfo
import com.arcsoft.visdrive.avmsdk.ArcVisDriveAVMEngine
import com.arcsoft.visdrive.avmsdk.constant.avm.ArcAVMType
......@@ -21,6 +23,7 @@ import com.arcsoft.visdrive.avmsdk.model.avm.ArcAVMLookupTable
import com.arcsoft.visdrive.avmsdk.model.avm.ArcAVMOutputImage
import com.arcsoft.visdrive.avmsdk.model.common.ArcActiveEnvParam
import com.blankj.utilcode.util.FileUtils
import com.blankj.utilcode.util.ImageUtils
import com.blankj.utilcode.util.LogUtils
import com.intergration.avm.databinding.ActivityMainBinding
import com.intergration.avm.utils.ArcAVMInputImageFactory
......@@ -212,14 +215,13 @@ class MainActivity : AppCompatActivity() {
}
avmPlayJob = avmStartScope?.launch {
try {
val frontScope = CoroutineScope(Dispatchers.Default)
avmFrontCamera.startPictureSequence(
PictureSequenceSource.GENERAL_CAMERA,
configCameraSequence(avmDir.absolutePath) { _, _, status, data, _ ->
if (status == SpmCameraDevice.ImageDataCallback.IMAGE_STATUS_SUCCEEDED) {
ArcAVMInputImageFactory.ofFront(data).also {
avmInputImages[0] = it
frontScope.launch {
launch {
ensureActive()
channel.send(true)
}
......@@ -227,14 +229,13 @@ class MainActivity : AppCompatActivity() {
}
}
)
val rightScope = CoroutineScope(Dispatchers.Default)
avmRightCamera.startPictureSequence(
PictureSequenceSource.GENERAL_CAMERA,
configCameraSequence(avmDir.absolutePath) { _, _, status, data, _ ->
if (status == SpmCameraDevice.ImageDataCallback.IMAGE_STATUS_SUCCEEDED) {
ArcAVMInputImageFactory.ofRight(data).also {
avmInputImages[1] = it
rightScope.launch {
launch {
ensureActive()
channel.send(true)
}
......@@ -242,14 +243,13 @@ class MainActivity : AppCompatActivity() {
}
}
)
val backScope = CoroutineScope(Dispatchers.Default)
avmBackCamera.startPictureSequence(
PictureSequenceSource.GENERAL_CAMERA,
configCameraSequence(avmDir.absolutePath) { _, _, status, data, _ ->
if (status == SpmCameraDevice.ImageDataCallback.IMAGE_STATUS_SUCCEEDED) {
ArcAVMInputImageFactory.ofBack(data).also {
avmInputImages[2] = it
backScope.launch {
launch {
ensureActive()
channel.send(true)
}
......@@ -257,14 +257,13 @@ class MainActivity : AppCompatActivity() {
}
}
)
val leftScope = CoroutineScope(Dispatchers.Default)
avmLeftCamera.startPictureSequence(
PictureSequenceSource.GENERAL_CAMERA,
configCameraSequence(avmDir.absolutePath) { _, _, status, data, _ ->
if (status == SpmCameraDevice.ImageDataCallback.IMAGE_STATUS_SUCCEEDED) {
ArcAVMInputImageFactory.ofLeft(data).also {
avmInputImages[3] = it
leftScope.launch {
launch {
ensureActive()
channel.send(true)
}
......@@ -287,7 +286,7 @@ class MainActivity : AppCompatActivity() {
)
if (result == ArcErrorInfo.ARC_ERROR_OK) {
if (outputImageList.isNotEmpty()) {
feedData(outputImageList[0].imageData)
feedData(outputImageList[0].imageData,outputImageList[0].width,outputImageList[0].height)
}
}
}
......@@ -351,12 +350,10 @@ class MainActivity : AppCompatActivity() {
override fun onDestroy() {
super.onDestroy()
SmartPlatformManager.get().run {
closeCameraDevice(avmFrontCamera)
closeCameraDevice(avmBackCamera)
closeCameraDevice(avmLeftCamera)
closeCameraDevice(avmRightCamera)
}
smartPlatformManager.closeCameraDevice(avmFrontCamera)
smartPlatformManager.closeCameraDevice(avmBackCamera)
smartPlatformManager.closeCameraDevice(avmLeftCamera)
smartPlatformManager.closeCameraDevice(avmRightCamera)
job?.cancel(CancellationException("MainActivity Destroyed"))
}
......
......@@ -104,8 +104,8 @@ fun ArcVisDriveAVMEngine.initializeAvmParams(calibResultPath:File,lookupPath:Fil
calibInfo.singleImageWidth = IMAGE_WIDTH
calibInfo.singleImageHeight = IMAGE_HEIGHT
val carInfo = ArcAVMCarInfo()
carInfo.width = 590
carInfo.length = 1800
carInfo.width = 600
carInfo.length = 1200
carInfo.blinkAreaFront = 0
carInfo.blinkAreaRight = 0
carInfo.blinkAreaBack = 0
......@@ -133,10 +133,10 @@ fun ArcVisDriveAVMEngine.initializeAvmParams(calibResultPath:File,lookupPath:Fil
fun ArcVisDriveAVMEngine.autoCalib(calibResultPath:File,lookupPath:File):Int{
val clothInfo = ArcAVMClothInfo()
clothInfo.d1 = 120
clothInfo.d3 = 690
clothInfo.d4 = 690
clothInfo.d5 = 690
clothInfo.d6 = 690
clothInfo.d3 = 590
clothInfo.d4 = 590
clothInfo.d5 = 550
clothInfo.d6 = 550
val chessInfoFront = ArcAVMChessInfo(ArcAVMCameraPosType.TYPE_FRONT)
val chessInfoRight = ArcAVMChessInfo(ArcAVMCameraPosType.TYPE_RIGHT)
val chessInfoBack = ArcAVMChessInfo(ArcAVMCameraPosType.TYPE_BACK)
......
package com.intergration.avm.glsurface;
import android.content.Context;
import android.graphics.Outline;
import android.graphics.Rect;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewOutlineProvider;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
public class CameraGLSurfaceView extends GLSurfaceView {
private static final String TAG = "CameraGLSurfaceView";
// 源视频帧宽/高
private int frameWidth, frameHeight;
private boolean isMirror;
private int rotateDegree = 0;
// 用于判断preview数据是否被传入,避免在初始化时有一段时间的绿色背景(y、u、v均全为0)
private boolean dataInput = false;
// 圆角半径
private int radius = 0;
private ByteBuffer yBuf = null, uBuf = null, vBuf = null;
// 纹理id
private int[] yTexture = new int[1];
private int[] uTexture = new int[1];
private int[] vTexture = new int[1];
//YUV分量
private byte[] yArray;
private byte[] uArray;
private byte[] vArray;
private static final int FLOAT_SIZE_BYTES = 4;
//片段着色器的效果
private String fragmentShaderCode = GLUtils.FRAG_SHADER_NORMAL;
private FloatBuffer squareVertices = null;
private FloatBuffer coordVertices = null;
private boolean rendererReady = false;
private float[] coordVertice = null;
private int lastWidth;
private int lastHeight;
public CameraGLSurfaceView(Context context) {
this(context, null);
}
public CameraGLSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
setEGLContextClientVersion(2);
//设置Renderer到GLSurfaceView
setRenderer(new YUVRenderer());
// 只有在绘制数据改变时才绘制view
setRenderMode(RENDERMODE_WHEN_DIRTY);
setOutlineProvider(new ViewOutlineProvider() {
@Override
public void getOutline(View view, Outline outline) {
Rect rect = new Rect(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
outline.setRoundRect(rect, radius);
}
});
setClipToOutline(true);
}
public void turnRound() {
invalidateOutline();
}
public int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
/**
* 设置不同的片段着色器代码以达到不同的预览效果
*
* @param fragmentShaderCode 片段着色器代码
*/
public void setFragmentShaderCode(String fragmentShaderCode) {
this.fragmentShaderCode = fragmentShaderCode;
}
public void init(boolean isMirror, int rotateDegree, int frameWidth, int frameHeight) {
if (this.frameWidth == frameWidth
&& this.frameHeight == frameHeight
&& this.rotateDegree == rotateDegree
&& this.isMirror == isMirror) {
return;
}
dataInput = false;
this.frameWidth = frameWidth;
this.frameHeight = frameHeight;
this.rotateDegree = rotateDegree;
this.isMirror = isMirror;
yArray = new byte[this.frameWidth * this.frameHeight];
uArray = new byte[this.frameWidth * this.frameHeight / 4];
vArray = new byte[this.frameWidth * this.frameHeight / 4];
int yFrameSize = this.frameHeight * this.frameWidth;
int uvFrameSize = yFrameSize >> 2;
yBuf = ByteBuffer.allocateDirect(yFrameSize);
yBuf.order(ByteOrder.nativeOrder()).position(0);
uBuf = ByteBuffer.allocateDirect(uvFrameSize);
uBuf.order(ByteOrder.nativeOrder()).position(0);
vBuf = ByteBuffer.allocateDirect(uvFrameSize);
vBuf.order(ByteOrder.nativeOrder()).position(0);
// 顶点坐标
squareVertices = ByteBuffer
.allocateDirect(GLUtils.SQUARE_VERTICES.length * FLOAT_SIZE_BYTES)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
squareVertices.put(GLUtils.SQUARE_VERTICES).position(0);
//纹理坐标
if (isMirror) {
switch (rotateDegree) {
case 0:
coordVertice = GLUtils.MIRROR_COORD_VERTICES;
break;
case 90:
coordVertice = GLUtils.ROTATE_90_MIRROR_COORD_VERTICES;
break;
case 180:
coordVertice = GLUtils.ROTATE_180_MIRROR_COORD_VERTICES;
break;
case 270:
coordVertice = GLUtils.ROTATE_270_MIRROR_COORD_VERTICES;
break;
default:
break;
}
} else {
switch (rotateDegree) {
case 0:
coordVertice = GLUtils.COORD_VERTICES;
break;
case 90:
coordVertice = GLUtils.ROTATE_90_COORD_VERTICES;
break;
case 180:
coordVertice = GLUtils.ROTATE_180_COORD_VERTICES;
break;
case 270:
coordVertice = GLUtils.ROTATE_270_COORD_VERTICES;
break;
default:
break;
}
}
coordVertices = ByteBuffer.allocateDirect(coordVertice.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
coordVertices.put(coordVertice).position(0);
}
/**
* 创建OpenGL Program并关联GLSL中的变量
*
* @param fragmentShaderCode 片段着色器代码
*/
private void createGLProgram(String fragmentShaderCode) {
int programHandleMain = GLUtils.createShaderProgram(fragmentShaderCode);
if (programHandleMain != -1) {
// 使用着色器程序
GLES20.glUseProgram(programHandleMain);
// 获取顶点着色器变量
int glPosition = GLES20.glGetAttribLocation(programHandleMain, "attr_position");
int textureCoord = GLES20.glGetAttribLocation(programHandleMain, "attr_tc");
// 获取片段着色器变量
int ySampler = GLES20.glGetUniformLocation(programHandleMain, "ySampler");
int uSampler = GLES20.glGetUniformLocation(programHandleMain, "uSampler");
int vSampler = GLES20.glGetUniformLocation(programHandleMain, "vSampler");
//给变量赋值
/*
* GLES20.GL_TEXTURE0 和 ySampler 绑定
* GLES20.GL_TEXTURE1 和 uSampler 绑定
* GLES20.GL_TEXTURE2 和 vSampler 绑定
*
* 也就是说 glUniform1i的第二个参数代表图层序号
*/
GLES20.glUniform1i(ySampler, 0);
GLES20.glUniform1i(uSampler, 1);
GLES20.glUniform1i(vSampler, 2);
GLES20.glEnableVertexAttribArray(glPosition);
GLES20.glEnableVertexAttribArray(textureCoord);
/*
* 设置Vertex Shader数据
*/
if (squareVertices == null) {
squareVertices = ByteBuffer
.allocateDirect(GLUtils.SQUARE_VERTICES.length * FLOAT_SIZE_BYTES)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
squareVertices.put(GLUtils.SQUARE_VERTICES).position(0);
}
squareVertices.position(0);
GLES20.glVertexAttribPointer(glPosition, GLUtils.COUNT_PER_SQUARE_VERTICE, GLES20.GL_FLOAT, false, 8, squareVertices);
if (coordVertices == null) {
coordVertices = ByteBuffer.allocateDirect(coordVertice.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
coordVertices.put(GLUtils.MIRROR_COORD_VERTICES).position(0);
}
coordVertices.position(0);
GLES20.glVertexAttribPointer(textureCoord, GLUtils.COUNT_PER_COORD_VERTICES, GLES20.GL_FLOAT, false, 8, coordVertices);
}
}
public class YUVRenderer implements Renderer {
private void initRenderer() {
rendererReady = false;
createGLProgram(fragmentShaderCode);
//启用纹理
GLES20.glEnable(GLES20.GL_TEXTURE_2D);
//创建纹理
createTexture(frameWidth, frameHeight, GLES20.GL_LUMINANCE, yTexture);
createTexture(frameWidth / 2, frameHeight / 2, GLES20.GL_LUMINANCE, uTexture);
createTexture(frameWidth / 2, frameHeight / 2, GLES20.GL_LUMINANCE, vTexture);
rendererReady = true;
}
@Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
initRenderer();
}
// 根据宽高和格式创建纹理
private void createTexture(int width, int height, int format, int[] textureId) {
//创建纹理
GLES20.glGenTextures(1, textureId, 0);
//绑定纹理
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId[0]);
/**
* {@link GLES20#GL_TEXTURE_WRAP_S}代表左右方向的纹理环绕模式
* {@link GLES20#GL_TEXTURE_WRAP_T}代表上下方向的纹理环绕模式
*
* {@link GLES20#GL_REPEAT}:重复
* {@link GLES20#GL_MIRRORED_REPEAT}:镜像重复
* {@link GLES20#GL_CLAMP_TO_EDGE}:忽略边框截取
*
* 例如我们使用{@link GLES20#GL_REPEAT}:
*
* squareVertices coordVertices
* -1.0f, -1.0f, 1.0f, 1.0f,
* 1.0f, -1.0f, 1.0f, 0.0f, -> 和textureView预览相同
* -1.0f, 1.0f, 0.0f, 1.0f,
* 1.0f, 1.0f 0.0f, 0.0f
*
* squareVertices coordVertices
* -1.0f, -1.0f, 2.0f, 2.0f,
* 1.0f, -1.0f, 2.0f, 0.0f, -> 和textureView预览相比,分割成了4 块相同的预览(左下,右下,左上,右上)
* -1.0f, 1.0f, 0.0f, 2.0f,
* 1.0f, 1.0f 0.0f, 0.0f
*/
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
/**
* {@link GLES20#GL_TEXTURE_MIN_FILTER}代表所显示的纹理比加载进来的纹理小时的情况
* {@link GLES20#GL_TEXTURE_MAG_FILTER}代表所显示的纹理比加载进来的纹理大时的情况
*
* {@link GLES20#GL_NEAREST}:使用纹理中坐标最接近的一个像素的颜色作为需要绘制的像素颜色
* {@link GLES20#GL_LINEAR}:使用纹理中坐标最接近的若干个颜色,通过加权平均算法得到需要绘制的像素颜色
*/
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, format, width, height, 0, format, GLES20.GL_UNSIGNED_BYTE, null);
}
@Override
public void onDrawFrame(GL10 gl) {
// 分别对每个纹理做激活、绑定、设置数据操作
if (dataInput) {
//y
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, yTexture[0]);
GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D,
0,
0,
0,
frameWidth,
frameHeight,
GLES20.GL_LUMINANCE,
GLES20.GL_UNSIGNED_BYTE,
yBuf);
//u
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, uTexture[0]);
GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D,
0,
0,
0,
frameWidth >> 1,
frameHeight >> 1,
GLES20.GL_LUMINANCE,
GLES20.GL_UNSIGNED_BYTE,
uBuf);
//v
GLES20.glActiveTexture(GLES20.GL_TEXTURE2);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, vTexture[0]);
GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D,
0,
0,
0,
frameWidth >> 1,
frameHeight >> 1,
GLES20.GL_LUMINANCE,
GLES20.GL_UNSIGNED_BYTE,
vBuf);
//在数据绑定完成后进行绘制
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
}
}
@Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
}
}
/**
* 传入NV21刷新帧
*
* @param data NV21数据
*/
public void refreshFrameNV21(byte[] data) {
if (rendererReady) {
yBuf.clear();
uBuf.clear();
vBuf.clear();
putNV21(data, frameWidth, frameHeight);
dataInput = true;
requestRender();
}
}
/**
* 传入YV12数据刷新帧
*
* @param data YV12数据
*/
public void refreshFrameYV12(byte[] data) {
if (rendererReady) {
yBuf.clear();
uBuf.clear();
vBuf.clear();
putYV12(data, frameWidth, frameHeight);
dataInput = true;
requestRender();
}
}
/**
* 将NV21数据的Y、U、V分量取出
*
* @param src nv21帧数据
* @param width 宽度
* @param height 高度
*/
private void putNV21(byte[] src, int width, int height) {
int ySize = width * height;
int frameSize = ySize * 3 / 2;
//取分量y值
System.arraycopy(src, 0, yArray, 0, ySize);
int k = 0;
//取分量uv值
int index = ySize;
while (index < frameSize) {
vArray[k] = src[index++];
uArray[k++] = src[index++];
}
yBuf.put(yArray).position(0);
uBuf.put(vArray).position(0);
vBuf.put(uArray).position(0);
}
/**
* 将YV12数据的Y、U、V分量取出
*
* @param src YV12帧数据
* @param width 宽度
* @param height 高度
*/
private void putYV12(byte[] src, int width, int height) {
int ySize = width * height;
int frameSize = ySize * 3 / 2;
//取分量y值
System.arraycopy(src, 0, yArray, 0, ySize);
int k = 0;
//取分量uv值
int index = ySize;
while (index < frameSize) {
vArray[k] = src[index++];
uArray[k++] = src[index++];
}
yBuf.put(yArray).position(0);
uBuf.put(uArray).position(0);
vBuf.put(vArray).position(0);
}
}
package com.intergration.avm.glsurface;
import android.opengl.GLES20;
import java.nio.IntBuffer;
public class GLUtils {
private static final String TAG = "GLUtils";
/**
* 顶点着色器
*/
private static String VERTEX_SHADER =
" attribute vec4 attr_position;\n" +
" attribute vec2 attr_tc;\n" +
" varying vec2 tc;\n" +
" void main() {\n" +
" gl_Position = attr_position;\n" +
" tc = attr_tc;\n" +
" }";
/**
* 片段着色器,正常效果
*/
public static String FRAG_SHADER_NORMAL =
"precision mediump float;\n" +
" varying vec2 tc;\n" +
" uniform sampler2D ySampler;\n" +
" uniform sampler2D uSampler;\n" +
" uniform sampler2D vSampler;\n" +
" const mat3 convertMat = mat3(1.0, 1.0, 1.0, 0, -0.344, 1.77, 1.403, -0.714,0);\n" +
" void main()\n" +
" {\n" +
" vec3 yuv;\n" +
" yuv.x = texture2D(ySampler, tc).r;\n" +
" yuv.y = texture2D(vSampler, tc).r - 0.5;\n" +
" yuv.z = texture2D(uSampler, tc).r - 0.5;\n" +
" gl_FragColor = vec4(convertMat * yuv, 1.0);\n" +
" }";
/**
* 片段着色器,灰度效果。不需要 U V 数据(Java代码中可以做对应修改,仅需拷贝NV21数据中的Y分量即可)
*/
public static String FRAG_SHADER_GRAY =
"precision mediump float;\n" +
" varying vec2 tc;\n" +
" uniform sampler2D ySampler;\n" +
" void main()\n" +
" {\n" +
" vec3 yuv;\n" +
" yuv.x = texture2D(ySampler, tc).r;\n" +
" gl_FragColor = vec4(vec3(yuv.x), 1.0);\n" +
" }";
/**
* 片段着色器,浮雕效果。不需要 U V 数据(Java代码中可以做对应修改,仅需拷贝NV21数据中的Y分量即可)
*/
public static String FRAG_SHADER_SCULPTURE =
"precision mediump float;\n" +
"varying vec2 tc;\n" +
" uniform sampler2D ySampler;\n" +
" const vec2 texSize = vec2(100.0, 100.0);\n" +
" const vec4 sculptureColor = vec4(0.5, 0.5, 0.5, 1.0);\n" +
"\n" +
"void main()\n" +
"{\n" +
" vec2 upLeftCoord = vec2(tc.x-1.0/texSize.x, tc.y-1.0/texSize.y);\n" +
" vec4 curColor = texture2D(ySampler, tc);\n" +
" vec4 upLeftColor = texture2D(ySampler, upLeftCoord);\n" +
" vec4 delColor = curColor - upLeftColor;\n" +
" gl_FragColor = vec4(vec3(delColor), 0.0) + sculptureColor;\n" +
"}";
//SQUARE_VERTICES每2个值作为一个顶点
static final int COUNT_PER_SQUARE_VERTICE = 2;
//COORD_VERTICES每2个值作为一个顶点
static final int COUNT_PER_COORD_VERTICES = 2;
/**
* 显示的顶点
*/
static final float[] SQUARE_VERTICES = {
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f
};
/**
* 原数据显示
* 0,1***********1,1
* * *
* * *
* * *
* * *
* * *
* 0,0***********1,0
*/
static final float[] COORD_VERTICES = {
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f
};
/**
* 逆时针旋转90度显示
* 1,1***********1,0
* * *
* * *
* * *
* * *
* * *
* 0,1***********0,0
*/
static final float[] ROTATE_90_COORD_VERTICES = {
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
0.0f, 0.0f
};
/**
* 逆时针旋转180度显示
* 0,1***********1,1
* * *
* * *
* * *
* * *
* * *
* 0,0***********1,0
*/
static final float[] ROTATE_180_COORD_VERTICES = {
1.0f, 0.0f,
0.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f
};
/**
* 逆时针旋转270度显示
* 0,1***********1,1
* * *
* * *
* * *
* * *
* * *
* 0,0***********1,0
*/
static final float[] ROTATE_270_COORD_VERTICES = {
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f
};
/**
* 镜像显示
* 1,1***********0,1
* * *
* * *
* * *
* * *
* * *
* 1,0***********0,0
*/
static final float[] MIRROR_COORD_VERTICES = {
1.0f, 1.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f
};
/**
* 镜像并逆时针旋转90度显示
* 0,1***********0,0
* * *
* * *
* * *
* * *
* * *
* 1,1***********1,0
*/
static final float[] ROTATE_90_MIRROR_COORD_VERTICES = {
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 1.0f,
1.0f, 0.0f
};
/**
* 镜像并逆时针旋转180度显示
* 1,0***********0,0
* * *
* * *
* * *
* * *
* * *
* 1,1***********0,1
*/
static final float[] ROTATE_180_MIRROR_COORD_VERTICES = {
1.0f, 0.0f,
0.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f
};
/**
* 镜像并逆时针旋转270度显示
* 1,0***********1,1
* * *
* * *
* * *
* * *
* * *
* 0,0***********0,1
*/
static final float[] ROTATE_270_MIRROR_COORD_VERTICES = {
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 0.0f,
0.0f, 1.0f
};
/**
* 创建OpenGL Program,并链接
*
* @param fragmentShaderCode 片段着色器代码
* @return OpenGL Program对象的引用
*/
static int createShaderProgram(String fragmentShaderCode) {
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, VERTEX_SHADER);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
// 创建一个空的OpenGL ES Program
int mProgram = GLES20.glCreateProgram();
// 将vertex shader添加到program
GLES20.glAttachShader(mProgram, vertexShader);
// 将fragment shader添加到program
GLES20.glAttachShader(mProgram, fragmentShader);
// 链接创建好的 OpenGL ES program
GLES20.glLinkProgram(mProgram);
// 检查链接状态
IntBuffer linked = IntBuffer.allocate(1);
GLES20.glGetProgramiv(mProgram, GLES20.GL_LINK_STATUS, linked);
if (linked.get(0) == 0) {
return -1;
}
return mProgram;
}
/**
* 加载着色器
*
* @param type 着色器类型,可以是片段着色器{@link GLES20#GL_FRAGMENT_SHADER}或顶点着色器{@link GLES20#GL_VERTEX_SHADER}
* @param shaderCode 着色器代码
* @return 着色器对象的引用
*/
private static int loadShader(int type, String shaderCode) {
//创建空的shader
int shader = GLES20.glCreateShader(type);
//加载shader代码
GLES20.glShaderSource(shader, shaderCode);
//编译shader
GLES20.glCompileShader(shader);
//检查编译是否成功
IntBuffer compiled = IntBuffer.allocate(1);
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled);
if (compiled.get(0) == 0) {
return 0;
}
return shader;
}
}
......@@ -6,10 +6,12 @@ import android.os.Bundle
import android.view.Display
import android.widget.FrameLayout
import com.intergration.avm.R
import com.intergration.avm.glsurface.CameraGLSurfaceView
import com.intergration.avm.glsurface.GLUtils
import com.intergration.avm.glsurface.MyGLSurfaceView
import com.intergration.avm.utils.IMAGE_HEIGHT
import com.intergration.avm.utils.IMAGE_WIDTH
import com.mediatek.smartplatform.PictureConfiguration
import com.intergration.avm.glsurface.MyGLSurfaceView
class AuxiliaryScreenPresentation(outerContext: Context, display: Display) :
Presentation(outerContext, display) {
......@@ -18,15 +20,15 @@ class AuxiliaryScreenPresentation(outerContext: Context, display: Display) :
lateinit var frameLayout: FrameLayout
private lateinit var rendererView: MyGLSurfaceView
private lateinit var rendererView: CameraGLSurfaceView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
frameLayout = layoutInflater.inflate(R.layout.layout_presentation,null) as FrameLayout
setContentView(frameLayout)
rendererView = frameLayout.findViewById<MyGLSurfaceView?>(R.id.rendererView).also {
it.setYuvDataSize(IMAGE_HEIGHT,IMAGE_WIDTH)
}
rendererView = frameLayout.findViewById(R.id.rendererView)
rendererView.setFragmentShaderCode(GLUtils.FRAG_SHADER_NORMAL)
rendererView.init(true,0,IMAGE_HEIGHT,IMAGE_WIDTH)
}
/**
......@@ -59,17 +61,17 @@ class AuxiliaryScreenPresentation(outerContext: Context, display: Display) :
fun feedData(data:ByteArray){
rendererView.feedData(data,2)
rendererView.refreshFrameNV21(data)
}
@Synchronized
fun setDisplayOrientation(degree:Int){
rendererView.setDisplayOrientation(degree)
}
// @Synchronized
// fun setDisplayOrientation(degree:Int){
// rendererView.setDisplayOrientation(degree)
// }
@Synchronized
fun setYuvDataSize(width:Int,height:Int){
rendererView.setYuvDataSize(width,height)
}
// @Synchronized
// fun setYuvDataSize(width:Int,height:Int){
// rendererView.setYuvDataSize(width,height)
// }
}
\ No newline at end of file
......@@ -69,13 +69,13 @@ class MultiScreenService : Service() {
presentation?.feedData(data)
}
fun setDisplayOrientation(degree:Int){
presentation?.setDisplayOrientation(270)
}
fun setYuvDataSize(width:Int,height:Int){
presentation?.setYuvDataSize(width,height)
}
// fun setDisplayOrientation(degree:Int){
// presentation?.setDisplayOrientation(270)
// }
//
// fun setYuvDataSize(width:Int,height:Int){
// presentation?.setYuvDataSize(width,height)
// }
inner class MultiScreenBinder : Binder() {
fun getService(): MultiScreenService {
......
......@@ -5,6 +5,7 @@ import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.IBinder
import android.text.style.LineHeightSpan
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.SPUtils
import com.intergration.avm.presentation.MultiScreenService
......@@ -61,7 +62,8 @@ fun Context.closeAuxiliaryPresentation(){
}
}
fun feedData(data: ByteArray){
fun feedData(data: ByteArray,width:Int = 0,height:Int = 0){
// multiScreenService?.setYuvDataSize(width = width,height = height)
multiScreenService?.feedNv21Data(data)
}
......@@ -9,8 +9,8 @@
android:textSize="24sp"
android:textColor="@android:color/holo_blue_light"
android:layout_gravity="center_horizontal|top"/>
<com.intergration.avm.glsurface.MyGLSurfaceView
<com.intergration.avm.glsurface.CameraGLSurfaceView
android:id="@+id/rendererView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
android:layout_height="match_parent" />
</FrameLayout>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment