Compare commits

...

4 Commits

Author SHA1 Message Date
liuguijing bff3e7ad0f Camera2 修改屏幕角度 8 months ago
liuguijing 11f8cfdbdd Camera2 修改屏幕角度 8 months ago
liuguijing eaeab28829 Camera2改写 8 months ago
liuguijing b1190cd970 Camera2改写 8 months ago

@ -30,6 +30,9 @@ android {
signingConfig signingConfigs.config
}
}
buildFeatures {
viewBinding true
}
}

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xypower.mplive">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
@ -8,7 +9,9 @@
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<uses-feature
android:glEsVersion="0x00020000"
android:required="true" />
<application
android:allowBackup="true"
@ -16,6 +19,10 @@
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".TESTActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:exported="false" />
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize">

@ -17,7 +17,6 @@ import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
@ -26,8 +25,8 @@ import android.widget.Toast;
import com.dev.devapi.api.SysApi;
import com.github.faucamp.simplertmp.RtmpHandler;
import com.seu.magicfilter.utils.MagicFilterType;
import net.ossrs.yasea.CameraItemData;
import net.ossrs.yasea.SrsCameraView;
import net.ossrs.yasea.SrsEncodeHandler;
import net.ossrs.yasea.SrsPublisher;
@ -35,6 +34,7 @@ import net.ossrs.yasea.SrsRecordHandler;
import java.io.IOException;
import java.net.SocketException;
import java.util.List;
import java.util.Random;
public class MainActivity extends AppCompatActivity implements RtmpHandler.RtmpListener,
@ -50,7 +50,8 @@ public class MainActivity extends AppCompatActivity implements RtmpHandler.RtmpL
private Button btnPause;
private SharedPreferences sp;
private String rtmpUrl = "rtmp://192.168.50.250/live/0";
// private String rtmpUrl = "rtmp://192.168.50.250/live/0";
private String rtmpUrl = "rtmp://61.169.135.146/live/abcd";
private String recPath = Environment.getExternalStorageDirectory().getPath() + "/test.mp4";
private SrsPublisher mPublisher;
@ -61,22 +62,19 @@ public class MainActivity extends AppCompatActivity implements RtmpHandler.RtmpL
private boolean isPermissionGranted = false;
private Handler mHandler;
private int cameraId = 0;
private List<CameraItemData> cameraData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new Handler();
SysApi.setCam3V3Enable(true);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
setContentView(R.layout.activity_main);
// response screen rotation event
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
requestPermission();
}
@ -89,7 +87,7 @@ public class MainActivity extends AppCompatActivity implements RtmpHandler.RtmpL
//2. 权限没有开启,请求权限
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE}, RC_CAMERA);
}else{
} else {
//权限已经开启,做相应事情
isPermissionGranted = true;
try {
@ -137,40 +135,69 @@ public class MainActivity extends AppCompatActivity implements RtmpHandler.RtmpL
btnPause.setEnabled(false);
Intent intent = getIntent();
String url = intent.getStringExtra("url");
if (!TextUtils.isEmpty(url)) {
rtmpUrl = url;
}
mCameraView = (SrsCameraView) findViewById(R.id.glsurfaceview_camera);
// mCameraView.getHolder().addCallback(new SurfaceHolder.Callback() {
// @Override
// public void surfaceCreated(SurfaceHolder holder) {
// Canvas canvas = holder.lockCanvas();
// if (canvas != null) {
// canvas.drawColor(Color.WHITE);
// canvas.rotate(45, canvas.getWidth() / 2, canvas.getHeight() / 2);
// // 在旋转后的Canvas上绘制内容
// holder.unlockCanvasAndPost(canvas);
// }
// }
//
// @Override
// public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
//
// }
//
// @Override
// public void surfaceDestroyed(SurfaceHolder holder) {
//
// }
// });
int rotation = intent.getIntExtra("rotation", -1);
if (rotation != -1) {
//设置图像显示方向
mCameraView.setPreviewOrientation(rotation);
}
cameraData = mCameraView.getCameraData();
mPublisher = new SrsPublisher(mCameraView);
String url = intent.getStringExtra("url");
if (!TextUtils.isEmpty(url)) {
rtmpUrl = url;
int size = cameraData.size();
if (size == 0) {
Toast.makeText(getApplicationContext(), "没有查询到摄像头", Toast.LENGTH_SHORT).show();
}
mPublisher = new SrsPublisher(mCameraView);
mPublisher.setEncodeHandler(new SrsEncodeHandler(this));
mPublisher.setRtmpHandler(new RtmpHandler(this));
mPublisher.setRecordHandler(new SrsRecordHandler(this));
mPublisher.setPreviewResolution(mWidth, mHeight);
mPublisher.setPreviewResolution(mWidth, mHeight);//设置预览宽高
mPublisher.setOutputResolution(mHeight, mWidth); // 这里要和preview反过来
mPublisher.setVideoHDMode();
if (intent.hasExtra("cameraId")) {
int cameraId = intent.getIntExtra("cameraId", 0);
cameraId = intent.getIntExtra("cameraId", 0);
mPublisher.switchCameraFace(cameraId);
}
mPublisher.startCamera();
mCameraView.setCameraCallbacksHandler(new SrsCameraView.CameraCallbacksHandler(){
mCameraView.setCameraCallbacksHandler(new SrsCameraView.CameraCallbacksHandler() {
@Override
public void onCameraParameters(Camera.Parameters params) {
//params.setFocusMode("custom-focus");
//params.setWhiteBalance("custom-balance");
//etc...
Log.e("fsfs", "fsdf");
}
});
@ -229,10 +256,10 @@ public class MainActivity extends AppCompatActivity implements RtmpHandler.RtmpL
btnPause.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(btnPause.getText().toString().equals("Pause")){
if (btnPause.getText().toString().equals("Pause")) {
mPublisher.pausePublish();
btnPause.setText("resume");
}else{
} else {
mPublisher.resumePublish();
btnPause.setText("Pause");
}
@ -242,7 +269,14 @@ public class MainActivity extends AppCompatActivity implements RtmpHandler.RtmpL
btnSwitchCamera.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPublisher.switchCameraFace((mPublisher.getCameraId() + 1) % Camera.getNumberOfCameras());
int size = cameraData.size();
if (size > 0) {
int i = (++cameraId) % size;
mPublisher.switchCameraFace(i);
}
}
});
@ -284,78 +318,13 @@ public class MainActivity extends AppCompatActivity implements RtmpHandler.RtmpL
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
} else {
switch (id) {
case R.id.cool_filter:
mPublisher.switchCameraFilter(MagicFilterType.COOL);
break;
case R.id.beauty_filter:
mPublisher.switchCameraFilter(MagicFilterType.BEAUTY);
break;
case R.id.early_bird_filter:
mPublisher.switchCameraFilter(MagicFilterType.EARLYBIRD);
break;
case R.id.evergreen_filter:
mPublisher.switchCameraFilter(MagicFilterType.EVERGREEN);
break;
case R.id.n1977_filter:
mPublisher.switchCameraFilter(MagicFilterType.N1977);
break;
case R.id.nostalgia_filter:
mPublisher.switchCameraFilter(MagicFilterType.NOSTALGIA);
break;
case R.id.romance_filter:
mPublisher.switchCameraFilter(MagicFilterType.ROMANCE);
break;
case R.id.sunrise_filter:
mPublisher.switchCameraFilter(MagicFilterType.SUNRISE);
break;
case R.id.sunset_filter:
mPublisher.switchCameraFilter(MagicFilterType.SUNSET);
break;
case R.id.tender_filter:
mPublisher.switchCameraFilter(MagicFilterType.TENDER);
break;
case R.id.toast_filter:
mPublisher.switchCameraFilter(MagicFilterType.TOASTER2);
break;
case R.id.valencia_filter:
mPublisher.switchCameraFilter(MagicFilterType.VALENCIA);
break;
case R.id.walden_filter:
mPublisher.switchCameraFilter(MagicFilterType.WALDEN);
break;
case R.id.warm_filter:
mPublisher.switchCameraFilter(MagicFilterType.WARM);
break;
case R.id.original_filter:
default:
mPublisher.switchCameraFilter(MagicFilterType.NONE);
break;
}
}
setTitle(item.getTitle());
return super.onOptionsItemSelected(item);
}
@Override
protected void onStart() {
super.onStart();
if(mPublisher.getCamera() == null && isPermissionGranted){
//if the camera was busy and available again
mPublisher.startCamera();
}
// if(mPublisher.getCamera() == null && isPermissionGranted){
// //if the camera was busy and available again
// mPublisher.startCamera();
// }
}
@Override

@ -0,0 +1,232 @@
package com.xypower.mplive;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.widget.Toast;
import java.util.Arrays;
public class TESTActivity extends AppCompatActivity {
private static final String TAG = "Camera2Demo";
private TextureView textureView;
private CameraDevice mCameraDevice;
private Size imageDimension;
private CaptureRequest.Builder captureRequestBuilder;
private CameraCaptureSession cameraCaptureSession;
private ImageReader imageReader;
private CaptureRequest captureRequest;
@SuppressLint("MissingInflatedId")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setContentView(R.layout.activity_fullscreen);
initPermission(); //权限申请
textureView = findViewById(R.id.texture_view);
textureView.setSurfaceTextureListener(textureListener);
final CameraCaptureSession.CaptureCallback CaptureCallback
= new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request,
@NonNull TotalCaptureResult result) {
//点击拍照后调用此回调 此处弹出提示
Toast.makeText(TESTActivity.this,"Saved:xx/xx/xx/xx.jpg",Toast.LENGTH_SHORT).show();
}
};
findViewById(R.id.picture).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
//创建了一个拍照的请求
final CaptureRequest.Builder captureBuilder =
mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
//与imageReader关联当点击拍照获取到可用图片时会触发ImageReader的回调可在ImageReader的回调中对图片进行保存等处理
captureBuilder.addTarget(imageReader.getSurface());
cameraCaptureSession.capture(captureBuilder.build(),CaptureCallback,null);
} catch (CameraAccessException e) {
throw new RuntimeException(e);
}
}
});
}
private final TextureView.SurfaceTextureListener textureListener =
new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
Log.e(TAG, "onSurfaceTextureAvailable");
openCamera();
}
@Override
public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) {
Log.e(TAG, "onSurfaceTextureSizeChanged");
}
@Override
public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
Log.e(TAG, "onSurfaceTextureDestroyed");
return false;
}
@Override
public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {
Log.e(TAG, "onSurfaceTextureUpdated");
}
};
//相机状态变化时会调用这里的回调函数
private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
//相机打开时执行
Log.e(TAG, "onOpened");
mCameraDevice=camera;
//创建相机预览会话
createCameraPreviewSession();
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
//相机链接断开
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
}
};
private void openCamera() {
CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
//通过cameraId获取Camera参数
String cameraId = cameraManager.getCameraIdList()[2];
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
imageDimension=map.getOutputSizes(SurfaceTexture.class)[0];
imageReader=ImageReader.newInstance(640,480, ImageFormat.YUV_420_888,10);
// imageReader.setOnImageAvailableListener(onImageAvailableListener,null);
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
cameraManager.openCamera(cameraId, stateCallback, null);
} catch (CameraAccessException e) {
throw new RuntimeException(e);
}
}
private boolean initPermission(){
ActivityCompat.requestPermissions(TESTActivity.this, new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE, android.Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.CAMERA}, 1);
// 高版本Android SDK时使用如下代码
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// if(!Environment.isExternalStorageManager()){
// Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
// startActivity(intent);
// return false;
// }
// }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[] {Manifest.permission.CAMERA}, 1);
return false;
}
}
return true;
}
private void createCameraPreviewSession(){
SurfaceTexture surfaceTexture=textureView.getSurfaceTexture();
assert surfaceTexture!=null;
surfaceTexture.setDefaultBufferSize(imageDimension.getWidth(),imageDimension.getHeight());
//预览的输出画面
Surface surface=new Surface(surfaceTexture);
try {
//预览请求
captureRequestBuilder=mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
mCameraDevice.createCaptureSession(Arrays.asList(surface, imageReader.getSurface()),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
if (mCameraDevice == null) {
return;
}
cameraCaptureSession = session;
updatePreview();
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
Toast.makeText(TESTActivity.this, "Configuration change", Toast.LENGTH_SHORT).show();
}
}, null);
} catch (CameraAccessException e) {
throw new RuntimeException(e);
}
}
private void updatePreview(){
captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
captureRequest = captureRequestBuilder.build();
try {
cameraCaptureSession.setRepeatingRequest(captureRequest,null,null);
} catch (CameraAccessException e) {
throw new RuntimeException(e);
}
}
private final ImageReader.OnImageAvailableListener onImageAvailableListener=
new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image=null;
image=reader.acquireLatestImage();
Log.e("lkx","1");
//此处可对图片进行处理 比如保存到本地
image.close();
}
};
}

@ -0,0 +1,21 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".TESTActivity">
<TextureView
android:id="@+id/texture_view"
android:layout_width="match_parent"
android:layout_height="588dp"></TextureView>
<Button
android:id="@+id/picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="take_photo" />
</LinearLayout>

@ -15,6 +15,17 @@
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
<!-- <net.ossrs.yasea.CameraView-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent"-->
<!-- android:id="@+id/glsurfaceview_camera"-->
<!-- android:layout_alignParentBottom="true"-->
<!-- android:layout_alignParentLeft="true"-->
<!-- android:layout_alignParentStart="true"-->
<!-- android:layout_alignParentTop="true"-->
<!-- android:layout_alignParentRight="true"-->
<!-- android:layout_alignParentEnd="true" />-->
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"

@ -0,0 +1,7 @@
<resources>
<style name="ThemeOverlay.MpLive.FullscreenContainer" parent="">
<item name="fullscreenBackgroundColor">@color/light_blue_900</item>
<item name="fullscreenTextColor">@color/light_blue_A400</item>
</style>
</resources>

@ -0,0 +1,6 @@
<resources>
<declare-styleable name="FullscreenAttrs">
<attr name="fullscreenBackgroundColor" format="color" />
<attr name="fullscreenTextColor" format="color" />
</declare-styleable>
</resources>

@ -3,4 +3,9 @@
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
<color name="light_blue_600">#FF039BE5</color>
<color name="light_blue_900">#FF01579B</color>
<color name="light_blue_A200">#FF40C4FF</color>
<color name="light_blue_A400">#FF00B0FF</color>
<color name="black_overlay">#66000000</color>
</resources>

@ -1,3 +1,7 @@
<resources>
<string name="app_name">欣影视频流</string>
<string name="title_activity_fullscreen">FullscreenActivity</string>
<string name="dummy_button">Dummy Button</string>
<string name="dummy_content">DUMMY\nCONTENT</string>
<string name="title_activity_fullscreen2">FullscreenActivity2</string>
</resources>

@ -8,4 +8,13 @@
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="Widget.AppTheme.ActionBar.Fullscreen" parent="Widget.AppCompat.ActionBar">
<item name="android:background">@color/black_overlay</item>
</style>
<style name="Widget.AppTheme.ButtonBar.Fullscreen" parent="">
<item name="android:background">@color/black_overlay</item>
<item name="android:buttonBarStyle">?android:attr/buttonBarStyle</item>
</style>
</resources>

@ -0,0 +1,13 @@
<resources>
<style name="AppTheme.Fullscreen" parent="AppTheme">
<item name="android:actionBarStyle">@style/Widget.AppTheme.ActionBar.Fullscreen</item>
<item name="android:windowActionBarOverlay">true</item>
<item name="android:windowBackground">@null</item>
</style>
<style name="ThemeOverlay.MpLive.FullscreenContainer" parent="">
<item name="fullscreenBackgroundColor">@color/light_blue_600</item>
<item name="fullscreenTextColor">@color/light_blue_A200</item>
</style>
</resources>

@ -1,6 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.ossrs.yasea">
<uses-permission android:name="android.permission.CAMERA" />
<application android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true">

@ -2,12 +2,12 @@ package com.seu.magicfilter.advanced;
import android.opengl.GLES20;
import com.seu.magicfilter.utils.MagicFilterType;
import net.ossrs.yasea.R;
import com.seu.magicfilter.base.gpuimage.GPUImageFilter;
import com.seu.magicfilter.utils.MagicFilterType;
import com.seu.magicfilter.utils.OpenGLUtils;
import net.ossrs.yasea.R;
public class MagicAmaroFilter extends GPUImageFilter{
private int[] inputTextureHandles = {-1,-1,-1};
private int[] inputTextureUniformLocations = {-1,-1,-1};

@ -1,14 +1,14 @@
package com.seu.magicfilter.base;
import java.nio.FloatBuffer;
import java.util.List;
import android.content.Context;
import android.opengl.GLES20;
import com.seu.magicfilter.base.gpuimage.GPUImageFilter;
import com.seu.magicfilter.utils.OpenGLUtils;
import android.content.Context;
import android.opengl.GLES20;
import java.nio.FloatBuffer;
import java.util.List;
public class MagicBaseGroupFilter extends GPUImageFilter {
@ -31,9 +31,9 @@ public class MagicBaseGroupFilter extends GPUImageFilter {
}
@Override
public void init(Context context) {
public void init(Context context, int cameraid) {
for (GPUImageFilter filter : filters) {
filter.init(context);
filter.init(context, cameraid);
}
}

@ -61,6 +61,8 @@ public class GPUImageFilter {
private int[] mGLFboId;
private int[] mGLFboTexId;
private IntBuffer mGLFboBuffer;
private float[] TEX_COORD;
private int curCameraid;
public GPUImageFilter() {
this(MagicFilterType.NONE);
@ -81,8 +83,9 @@ public class GPUImageFilter {
mFragmentShaderId = fragmentShaderId;
}
public void init(Context context) {
public void init(Context context, int cameraid) {
mContext = context;
curCameraid = cameraid;
onInit();
onInitialized();
}
@ -122,26 +125,20 @@ public class GPUImageFilter {
mGLProgId = OpenGLUtils.loadProgram(OpenGLUtils.readShaderFromRawResource(getContext(), mVertexShaderId),
OpenGLUtils.readShaderFromRawResource(getContext(), mFragmentShaderId));
mGLPositionIndex = GLES20.glGetAttribLocation(mGLProgId, "position");
mGLTextureCoordinateIndex = GLES20.glGetAttribLocation(mGLProgId,"inputTextureCoordinate");
mGLTextureCoordinateIndex = GLES20.glGetAttribLocation(mGLProgId, "inputTextureCoordinate");
mGLTextureTransformIndex = GLES20.glGetUniformLocation(mGLProgId, "textureTransform");
mGLInputImageTextureIndex = GLES20.glGetUniformLocation(mGLProgId, "inputImageTexture");
}
private void initVbo() {
public void initVbo() {
final float VEX_CUBE[] = {
//初始化 顶点着色器
-1.0f, -1.0f, // Bottom left.
1.0f, -1.0f, // Bottom right.
-1.0f, 1.0f, // Top left.
1.0f, 1.0f, // Top right.
};
final float TEX_COORD[] = {
0.0f, 0.0f, // Bottom left.
1.0f, 0.0f, // Bottom right.
0.0f, 1.0f, // Top left.
1.0f, 1.0f // Top right.
};
setOrtation(curCameraid);
mGLCubeBuffer = ByteBuffer.allocateDirect(VEX_CUBE.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mGLCubeBuffer.put(VEX_CUBE).position(0);
@ -162,6 +159,12 @@ public class GPUImageFilter {
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, mGLTextureBuffer.capacity() * 4, mGLTextureBuffer, GLES20.GL_STATIC_DRAW);
}
public void initTExt(int i) {
setOrtation(i);
// GLES20.glGenBuffers(1, mGLTextureCoordinateId, 0);
// GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mGLTextureCoordinateId[0]);
// GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, mGLTextureBuffer.capacity() * 4, mGLTextureBuffer, GLES20.GL_STATIC_DRAW);
}
private void destoryVbo() {
if (mGLCubeId != null) {
GLES20.glDeleteBuffers(1, mGLCubeId, 0);
@ -251,10 +254,19 @@ public class GPUImageFilter {
GLES20.glUseProgram(mGLProgId);
runPendingOnDrawTasks();
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mGLCubeId[0]);
GLES20.glEnableVertexAttribArray(mGLPositionIndex);
GLES20.glVertexAttribPointer(mGLPositionIndex, 2, GLES20.GL_FLOAT, false, 4 * 2, 0);
mGLTextureBuffer = ByteBuffer.allocateDirect(TEX_COORD.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mGLTextureBuffer.put(TEX_COORD).position(0);
GLES20.glGenBuffers(1, mGLTextureCoordinateId, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mGLTextureCoordinateId[0]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, mGLTextureBuffer.capacity() * 4, mGLTextureBuffer, GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mGLTextureCoordinateId[0]);
GLES20.glEnableVertexAttribArray(mGLTextureCoordinateIndex);
GLES20.glVertexAttribPointer(mGLTextureCoordinateIndex, 2, GLES20.GL_FLOAT, false, 4 * 2, 0);
@ -288,9 +300,11 @@ public class GPUImageFilter {
return mGLFboTexId[0];
}
protected void onDrawArraysPre() {}
protected void onDrawArraysPre() {
}
protected void onDrawArraysAfter() {}
protected void onDrawArraysAfter() {
}
private void runPendingOnDrawTasks() {
while (!mRunOnDraw.isEmpty()) {
@ -314,7 +328,7 @@ public class GPUImageFilter {
return mType;
}
public void setTextureTransformMatrix(float[] mtx){
public void setTextureTransformMatrix(float[] mtx) {
mGLTextureTransformMatrix = mtx;
}
@ -410,5 +424,54 @@ public class GPUImageFilter {
mRunOnDraw.addLast(runnable);
}
}
//设置纹理旋转角度
public void setOrtation(int i) {
//纹理坐标
TEX_COORD = new float[]{
0.0f, 0.0f, // Bottom left.
1.0f, 0.0f, // Bottom right.
0.0f, 1.0f, // Top left.
1.0f, 1.0f // Top right.
};
final float TEX_COORD_270[] = {
0.0f, 0.0f, // Bottom left.
1.0f, 0.0f, // Bottom right.
0.0f, 1.0f, // Top left.
1.0f, 1.0f // Top right.
};
final float TEX_COORD0[] = {
//1号摄像头 正
0.0f, 1.0f, // Bottom left.
0.0f, 0.0f, // Bottom right.
1.0f, 1.0f, // Top left.
1.0f, 0.0f // Top right.
};
final float TEX_COORD_90[] = {
//二号摄像头正
1.0f, 1.0f, // Bottom left.
0.0f, 1.0f, // Bottom right.
1.0f, 0.0f, // Top left.
0.0f, 0.0f // Top right.
};
final float TEX_COORD_180[] = {
//三号摄像头正
1.0f, 0.0f, // Bottom left.
1.0f, 1.0f, // Bottom right.
0.0f, 0.0f, // Top left.
0.0f, 1.0f // Top right.
};
if (i == 0) {
TEX_COORD = TEX_COORD0;
} else if (i == 1) {
TEX_COORD = TEX_COORD_90;
} else if (i == 2) {
TEX_COORD = TEX_COORD_180;
} else if (i == 3) {
TEX_COORD = TEX_COORD_270;
}
}
}

@ -0,0 +1,63 @@
package net.ossrs.yasea;
import android.util.Range;
import java.util.List;
//摄像头对象类
public class CameraItemData {
public String id;//摄像头编号
public int sensorOrientation;//摄像头朝向
public Range<Integer>[] FPS_RANGES;//FPS
public Long MAX_FRAME_DURATION;//最大帧率
public int LENS_FACING;//前置后置
public List supportedSizes;//支持处理的分辨率
public List getSupportedSizes() {
return supportedSizes;
}
public void setSupportedSizes(List supportedSizes) {
this.supportedSizes = supportedSizes;
}
public int getLENS_FACING() {
return LENS_FACING;
}
public void setLENS_FACING(int LENS_FACING) {
this.LENS_FACING = LENS_FACING;
}
public Long getMAX_FRAME_DURATION() {
return MAX_FRAME_DURATION;
}
public void setMAX_FRAME_DURATION(Long MAX_FRAME_DURATION) {
this.MAX_FRAME_DURATION = MAX_FRAME_DURATION;
}
public Range<Integer>[] getFPS_RANGES() {
return FPS_RANGES;
}
public void setFPS_RANGES(Range<Integer>[] FPS_RANGES) {
this.FPS_RANGES = FPS_RANGES;
}
public int getSensorOrientation() {
return sensorOrientation;
}
public void setSensorOrientation(int sensorOrientation) {
this.sensorOrientation = sensorOrientation;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}

@ -0,0 +1,258 @@
package net.ossrs.yasea;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
/**
* :
* <p>
* 1,,{@link CameraView#initCamera()}
* 2,,{@link CameraView#onRequestPermissionsResult(int, String[], int[])}
* 3,,{@link CameraView#onPause()}
*
* @author koko 2023/10/12 11:38
*/
public class CameraView extends SurfaceView {
private static final String TAG = "CameraView";
private static final int CAMERA_PERMISSION_REQUEST_CODE = 22;
private CameraDevice mCameraDevice;
private CameraCaptureSession mCaptureSession;
private CaptureRequest.Builder mPreviewBuilder;
public CameraView(Context context) {
super(context);
initView();
}
public CameraView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public CameraView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
public CameraView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initView();
}
private void initView() {
SurfaceHolder surfaceHolder = getHolder();
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.e(TAG, "surfaceCreated: ");
// 初始化相机
// 在需要使用相机的地方进行权限检查
if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
// 如果权限未被授予,则请求相机权限
ActivityCompat.requestPermissions((Activity) getContext(),
new String[]{Manifest.permission.CAMERA},
CAMERA_PERMISSION_REQUEST_CODE);
} else {
// 如果权限已被授予,则直接打开相机
openCamera();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.e(TAG, "surfaceChanged: ");
// 更新相机预览尺寸
updatePreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.e(TAG, "surfaceDestroyed: ");
// 释放相机资源
closeCamera();
}
});
}
/**
*
*/
public void initCamera() {
changeCameraOri(getResources().getConfiguration().orientation);
}
// 处理权限请求的回调
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == CAMERA_PERMISSION_REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 相机权限已被授予,打开相机
openCamera();
} else {
// 相机权限被拒绝,显示一个提示消息或执行其他操作
}
}
}
/**
*
*/
protected void onPause() {
closeCamera();
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
changeCameraOri(newConfig.orientation);
}
/**
*
* @param orientation
*/
private void changeCameraOri(int orientation) {
float ratioScreen = 0.28f;
float ratioCamera = 16 / 9f;
//以窄边为标准
//竖屏
// int screenWidthPortrait = (int) (com.smart.camera2.PhoneHelper.getScreenWidthReal(getContext()) * ratioScreen);
int screenWidthPortrait = (int) 1080;
int screenHeightPortrait = (int) (screenWidthPortrait * ratioCamera);
//横屏
// int screenHeightLandScape = (int) (com.smart.camera2.PhoneHelper.getScreenHeightReal(getContext()) * ratioScreen);
int screenHeightLandScape = (int) 1920;
int screenWidthLandScape = (int) (screenHeightLandScape * ratioCamera);
ViewGroup.LayoutParams layoutParams = getLayoutParams();
if (layoutParams == null) {
return;
}
switch (orientation) {
case Configuration.ORIENTATION_PORTRAIT:
Log.i(TAG, "onConfigurationChanged: " + "竖屏");
// 竖屏1080-1920
layoutParams.width = screenWidthPortrait;
layoutParams.height = screenHeightPortrait;
break;
case Configuration.ORIENTATION_LANDSCAPE:
Log.i(TAG, "onConfigurationChanged: " + "横屏");
// 横屏1920-1080
layoutParams.width = screenWidthLandScape;
layoutParams.height = screenHeightLandScape;
break;
}
setLayoutParams(layoutParams);
}
/**
*
*/
private void openCamera() {
CameraManager cameraManager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE);
getHolder().setFixedSize(9999, 9999);
try {
String cameraId = getFrontCameraId(cameraManager);
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
return;
}
cameraManager.openCamera(cameraId, new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice camera) {
mCameraDevice = camera;
Log.e(TAG, "onOpened: ");
createCaptureSession();
}
@Override
public void onDisconnected(CameraDevice camera) {
Log.e(TAG, "onDisconnected: ");
}
@Override
public void onError(CameraDevice camera, int error) {
Log.e(TAG, "onError: ");
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
/**
*
*/
private void closeCamera() {
Log.e(TAG, "closeCamera: ");
if (mCaptureSession != null) {
mCaptureSession.close();
mCaptureSession = null;
}
if (mCameraDevice != null) {
mCameraDevice.close();
mCameraDevice = null;
}
}
/**
*
*/
private void updatePreview() {
if (mCameraDevice == null) {
return;
}
if (mCaptureSession == null) {
return;
}
try {
mCaptureSession.setRepeatingRequest(mPreviewBuilder.build(), null, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
/**
*
* @param cameraManager cameraManager
* @return id
* @throws CameraAccessException
*/
private String getFrontCameraId(CameraManager cameraManager) throws CameraAccessException {
String[] cameraIds = cameraManager.getCameraIdList();
for (String cameraId : cameraIds) {
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) {
return cameraId;
}
}
return cameraIds[0];
}
/**
* CaptureSession
*/
private void createCaptureSession() {
try {
SurfaceHolder surfaceHolder = getHolder();
surfaceHolder.setFixedSize(getWidth(), getHeight());
List<Surface> surfaces = new ArrayList<>();
surfaces.add(surfaceHolder.getSurface());
mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewBuilder.addTarget(surfaceHolder.getSurface());
mCameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession session) {
mCaptureSession = session;
Log.e(TAG, "onConfigured: ");
updatePreview();
}
@Override
public void onConfigureFailed(CameraCaptureSession session) {
// 配置会话失败
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}

@ -0,0 +1,19 @@
package net.ossrs.yasea;
import java.util.LinkedList;
public class PendingThreadAider {
LinkedList<Runnable> mRunOnDraw = new LinkedList<Runnable>();
public void runPendings() {
while (!mRunOnDraw.isEmpty()) {
mRunOnDraw.removeFirst().run();
}
}
public void addToPending(final Runnable runnable) {
synchronized (mRunOnDraw) {
mRunOnDraw.addLast(runnable);
}
}
}

@ -2,15 +2,29 @@ package net.ossrs.yasea;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.ImageReader;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Range;
import android.util.Size;
import android.view.Surface;
import com.seu.magicfilter.base.gpuimage.GPUImageFilter;
@ -18,9 +32,10 @@ import com.seu.magicfilter.utils.MagicFilterFactory;
import com.seu.magicfilter.utils.MagicFilterType;
import com.seu.magicfilter.utils.OpenGLUtils;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
@ -48,7 +63,6 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
private float[] mSurfaceMatrix = new float[16];
private float[] mTransformMatrix = new float[16];
private Camera mCamera;
private ByteBuffer mGLPreviewBuffer;
private int mCamId = -1;
private int mPreviewRotation = 90;
@ -59,6 +73,18 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
private ConcurrentLinkedQueue<IntBuffer> mGLIntBufferCache = new ConcurrentLinkedQueue<>();
private PreviewCallback mPrevCb;
private CameraCallbacksHandler cameraCallbacksHandler = new CameraCallbacksHandler();
private CameraDevice mCameraDevice;//摄像头设备
private Size imageDimension;
private ImageReader imageReader;
private CaptureRequest.Builder captureRequestBuilder;
private CameraCaptureSession cameraCaptureSession;
private CameraManager cameraManager;//摄像头管理类
private String[] cameraNames;//摄像头名称列表
private CameraItemData curItem;//当前选中的摄像头参数
private ArrayList<CameraItemData> itemlist = new ArrayList<>();
private float[] rotationMatrix = new float[16];
private float[] vPMatrix = new float[16];
;
public SrsCameraView(Context context) {
this(context, null);
@ -69,16 +95,24 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
setEGLContextClientVersion(2);
setRenderer(this);
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
initCameraData();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
int cameraid = 0;
GLES20.glDisable(GL10.GL_DITHER);
GLES20.glClearColor(0, 0, 0, 0);
String id = curItem.getId();
magicFilter = new GPUImageFilter(MagicFilterType.NONE);
magicFilter.init(getContext().getApplicationContext());
try {
cameraid = Integer.parseInt(id);
} catch (Exception e) {
cameraid = 0;
}
// magicFilter.setOrtation(cameraid);
magicFilter.init(getContext().getApplicationContext(),cameraid);
magicFilter.onInputSizeChanged(mPreviewWidth, mPreviewHeight);
mOESTextureId = OpenGLUtils.getExternalOESTextureID();
@ -89,15 +123,7 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
requestRender();
}
});
// For camera preview on activity creation
if (mCamera != null) {
try {
mCamera.setPreviewTexture(surfaceTexture);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
@Override
@ -107,7 +133,6 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
mSurfaceHeight = height;
magicFilter.onDisplaySizeChanged(width, height);
magicFilter.onInputSizeChanged(mPreviewWidth, mPreviewHeight);
mOutputAspectRatio = width > height ? (float) width / height : (float) height / width;
float aspectRatio = mOutputAspectRatio / mInputAspectRatio;
if (width > height) {
@ -119,72 +144,104 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
@Override
public void onDrawFrame(GL10 gl) {
if(mSurfaceWidth != mPreviewWidth || mSurfaceHeight != mPreviewHeight){
//May be a buffer overflow in enableEncoding()
//mPreviewWidth changed but onSurfaceCreated fired after enable encoding (mIsEncoding == true)
//could be calling magicFilter.onInputSizeChanged(width, height) in setPreviewResolution() after changing mGLPreviewBuffer?
//or start the encoder only after onSurfaceCreated ...
if (mSurfaceWidth != mPreviewWidth || mSurfaceHeight != mPreviewHeight) {
Log.e(TAG, String.format("Surface dimensions differ from Preview. May be a buffer overflow. Surface: %dx%d, Preview: %dx%d ", mSurfaceWidth, mSurfaceHeight, mPreviewWidth, mPreviewHeight));
return;
}
//清除屏幕颜色缓冲区
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
surfaceTexture.updateTexImage();
surfaceTexture.getTransformMatrix(mSurfaceMatrix);
Matrix.multiplyMM(mTransformMatrix, 0, mSurfaceMatrix, 0, mProjectionMatrix, 0);
magicFilter.setTextureTransformMatrix(mTransformMatrix);
magicFilter.onDrawFrame(mOESTextureId);
if (mIsEncoding) {
mGLIntBufferCache.add(magicFilter.getGLFboBuffer());
synchronized (writeLock) {
writeLock.notifyAll();
}
}
}
public int computeRelativeRotation(CameraCharacteristics characteristics, int surfaceRotationDegrees) {
Integer sensorOrientationDegrees = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
// Reverse device orientation for back-facing cameras.
int sign = characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT ? 1 : -1;
// Calculate desired orientation relative to camera orientation to make
// the image upright relative to the device orientation.
return (sensorOrientationDegrees - surfaceRotationDegrees * sign + 360) % 360;
}
public void setPreviewCallback(PreviewCallback cb) {
mPrevCb = cb;
}
public Camera getCamera(){
return this.mCamera;
//选择sizeMap中大于并且接近width和height的size
private Size getOptimalSize(Size[] outputSizes, int width, int height) {
Size tempSize = new Size(width, height);
List<Size> sizes = new ArrayList<>();
for (Size outputSize : outputSizes) {
if (width > height) {
//横屏的时候
if (outputSize.getHeight() > height && outputSize.getWidth() > width) {
sizes.add(outputSize);
}
} else {
//竖屏的时候
if (outputSize.getWidth() > height && outputSize.getHeight() > width) {
sizes.add(outputSize);
}
}
}
if (sizes.size() > 0) {
//如果有多个符合条件找到一个差距最小的,最接近预览分辨率的
tempSize = sizes.get(0);
int minnum = 999999;
for (Size size : sizes) {
int num = size.getHeight() * size.getHeight() - width * height;
if (num < minnum) {
minnum = num;
tempSize = size;
}
public void setPreviewCallback(Camera.PreviewCallback previewCallback){
this.mCamera.setPreviewCallback(previewCallback);
}
}
return tempSize;
/*if (sizes.size() > 0) {
return Collections.min(sizes, new Comparator<Size>() {
@Override
public int compare(Size size, Size t1) {
return Long.signum(size.getWidth() * size.getHeight() - t1.getWidth() * t1.getHeight());
}
});
}
return outputSizes[0];*/
public int[] setPreviewResolution(int width, int height) {
mCamera = openCamera();
}
public int[] setPreviewResolution(int width, int height) {
mPreviewWidth = width;
mPreviewHeight = height;
Camera.Size rs = adaptPreviewResolution(mCamera.new Size(width, height));
if (rs != null) {
mPreviewWidth = rs.width;
mPreviewHeight = rs.height;
}
// Camera.Size rs = adaptPreviewResolution(mCamera.new Size(width, height));
// if (rs != null) {
// mPreviewWidth = rs.width;
// mPreviewHeight = rs.height;
// }
getHolder().setFixedSize(mPreviewWidth, mPreviewHeight);
mCamera.getParameters().setPreviewSize(mPreviewWidth, mPreviewHeight);
// mCamera.getParameters().setPreviewSize(mPreviewWidth, mPreviewHeight);
mGLPreviewBuffer = ByteBuffer.allocate(mPreviewWidth * mPreviewHeight * 4);
mInputAspectRatio = mPreviewWidth > mPreviewHeight ?
(float) mPreviewWidth / mPreviewHeight : (float) mPreviewHeight / mPreviewWidth;
return new int[] { mPreviewWidth, mPreviewHeight };
mInputAspectRatio = mPreviewWidth > mPreviewHeight ? (float) mPreviewWidth / mPreviewHeight : (float) mPreviewHeight / mPreviewWidth;
return new int[]{mPreviewWidth, mPreviewHeight};
}
public boolean setFilter(final MagicFilterType type) {
if (mCamera == null) {
return false;
}
public boolean setFilter(final MagicFilterType type, final int cameraid) {
queueEvent(new Runnable() {
@Override
@ -194,7 +251,7 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
}
magicFilter = MagicFilterFactory.initFilters(type);
if (magicFilter != null) {
magicFilter.init(getContext().getApplicationContext());
magicFilter.init(getContext().getApplicationContext(), cameraid);
magicFilter.onInputSizeChanged(mPreviewWidth, mPreviewHeight);
magicFilter.onDisplaySizeChanged(mSurfaceWidth, mSurfaceHeight);
}
@ -209,16 +266,16 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
queueEvent(new Runnable() {
@Override
public void run() {
GLES20.glDeleteTextures(1, new int[]{ mOESTextureId }, 0);
GLES20.glDeleteTextures(1, new int[]{mOESTextureId}, 0);
mOESTextureId = OpenGLUtils.NO_TEXTURE;
}
});
}
}
public void setCameraId(int id) {
public void setCameraId(CameraItemData item) {
stopTorch();
mCamId = id;
curItem = item;
setPreviewOrientation(mPreviewOrientation);
}
@ -235,7 +292,7 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
case Surface.ROTATION_270:
return 270;
}
}catch (Exception e){
} catch (Exception e) {
e.printStackTrace();
}
@ -244,31 +301,6 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
public void setPreviewOrientation(int orientation) {
mPreviewOrientation = orientation;
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(mCamId, info);
int rotateDeg = getRotateDeg();
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
mPreviewRotation = info.orientation % 360;
mPreviewRotation = (360 - mPreviewRotation) % 360; // compensate the mirror
} else {
mPreviewRotation = (info.orientation + 360) % 360;
}
} else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
mPreviewRotation = (info.orientation - 90) % 360;
mPreviewRotation = (360 - mPreviewRotation) % 360; // compensate the mirror
} else {
mPreviewRotation = (info.orientation + 90) % 360;
}
}
if(rotateDeg > 0){
mPreviewRotation = mPreviewRotation % rotateDeg;
}
}
public int getCameraId() {
@ -285,7 +317,7 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
IntBuffer picture = mGLIntBufferCache.poll();
mGLPreviewBuffer.asIntBuffer().put(picture.array());
mPrevCb.onGetRgbaFrame(mGLPreviewBuffer.array(), mPreviewWidth, mPreviewHeight);
}catch (Exception e){
} catch (Exception e) {
cameraCallbacksHandler.onError(e);
e.printStackTrace();
worker.interrupt();
@ -328,133 +360,170 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
}
}
public boolean startCamera() {
if (mCamera == null) {
mCamera = openCamera();
if (mCamera == null) {
return false;
}
//相机状态变化时会调用这里的回调函数
private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
//相机打开时执行
Log.e(TAG, "onOpened");
mCameraDevice = camera;
//创建相机预览会话
createCameraPreviewSession();
}
Camera.Parameters params = mCamera.getParameters();
//params.setPictureSize(mPreviewWidth, mPreviewHeight);
params.setPreviewSize(mPreviewWidth, mPreviewHeight);
int[] range = adaptFpsRange(SrsEncoder.VFPS, params.getSupportedPreviewFpsRange());
params.setPreviewFpsRange(range[0], range[1]);
params.setPreviewFormat(ImageFormat.NV21);
params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
params.setSceneMode(Camera.Parameters.SCENE_MODE_AUTO);
params.setRecordingHint(true);
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
//相机链接断开
Log.e("dsdsfd", "fdsdf");
List<String> supportedFocusModes = params.getSupportedFocusModes();
if (supportedFocusModes != null && !supportedFocusModes.isEmpty()) {
if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
} else if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
mCamera.autoFocus(null);
} else {
params.setFocusMode(supportedFocusModes.get(0));
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
Log.e("dsdsfd", "fdsdf");
}
};
private void createCameraPreviewSession() {
// SurfaceTexture surfaceTexture=new SurfaceTexture();
// assert surfaceTexture!=null;
//
surfaceTexture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
//预览的输出画面
Surface surface = new Surface(surfaceTexture);
try {
//预览请求
captureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
mCameraDevice.createCaptureSession(Arrays.asList(surface, imageReader.getSurface()), new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
if (mCameraDevice == null) {
return;
}
cameraCaptureSession = session;
updatePreview();
}
List<String> supportedFlashModes = params.getSupportedFlashModes();
if (supportedFlashModes != null && !supportedFlashModes.isEmpty()) {
if (supportedFlashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)) {
if (mIsTorchOn) {
params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
Log.e("dkkd", "fdsa");
}
} else {
params.setFlashMode(supportedFlashModes.get(0));
}, null);
} catch (CameraAccessException e) {
throw new RuntimeException(e);
}
}
cameraCallbacksHandler.onCameraParameters(params);
mCamera.setParameters(params);
private void updatePreview() {
captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
CaptureRequest captureRequest = captureRequestBuilder.build();
mCamera.setDisplayOrientation(mPreviewRotation);
try {
cameraCaptureSession.setRepeatingRequest(captureRequest, null, null);
} catch (CameraAccessException e) {
throw new RuntimeException(e);
}
}
public void startCamera() {
try {
mCamera.setPreviewTexture(surfaceTexture);
} catch (IOException e) {
e.printStackTrace();
if (curItem == null) {
curItem = itemlist.get(0);
}
mCamera.startPreview();
//通过cameraId获取Camera参数
String cameraId = curItem.getId();
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
imageDimension = map.getOutputSizes(SurfaceTexture.class)[0];
imageReader = ImageReader.newInstance(640, 480, ImageFormat.JPEG, 10);
// imageReader.setOnImageAvailableListener(onImageAvailableListener,null);
if (ActivityCompat.checkSelfPermission(getContext(), android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
}
cameraManager.openCamera(cameraId, stateCallback, null);
return true;
} catch (CameraAccessException e) {
throw new RuntimeException(e);
}
}
public void stopCamera() {
disableEncoding();
stopTorch();
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
protected Camera openCamera() {
Camera camera = null;
if (mCamId < 0) {
Camera.CameraInfo info = new Camera.CameraInfo();
int numCameras = Camera.getNumberOfCameras();
int frontCamId = -1;
int backCamId = -1;
for (int i = 0; i < numCameras; i++) {
Camera.getCameraInfo(i, info);
if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
backCamId = i;
} else if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
frontCamId = i;
break;
}
if (cameraCaptureSession != null) {
cameraCaptureSession.close();
cameraCaptureSession = null;
}
if (frontCamId != -1) {
mCamId = frontCamId;
} else if (backCamId != -1) {
mCamId = backCamId;
} else {
mCamId = 0;
if (mCameraDevice != null) {
mCameraDevice.close();
mCameraDevice = null;
}
}
public List<CameraItemData> initCameraData() {
itemlist = new ArrayList();
cameraManager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE);//获取摄像头管理类
try {
camera = Camera.open(mCamId);
camera.setErrorCallback(new Camera.ErrorCallback(){
@Override
public void onError(int error, Camera camera) {
//may be Camera.CAMERA_ERROR_EVICTED - Camera was disconnected due to use by higher priority user
stopCamera();
cameraNames = cameraManager.getCameraIdList();//获取摄像头名称列表
} catch (CameraAccessException e) {
throw new RuntimeException(e);
}
});
}catch (Exception e){
e.printStackTrace();
for (String cameraName : cameraNames) {
CameraItemData itemData = new CameraItemData();
itemData.setId(cameraName);//摄像头编号
CameraCharacteristics characteristics = null;
try {
characteristics = cameraManager.getCameraCharacteristics(cameraName);//获取摄像头各种特性
} catch (CameraAccessException e) {
throw new RuntimeException(e);
}
int sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
itemData.setSensorOrientation(sensorOrientation);//摄像头朝向
Range<Integer>[] ranges = characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
itemData.setFPS_RANGES(ranges);//
Long aLong = characteristics.get(CameraCharacteristics.SENSOR_INFO_MAX_FRAME_DURATION);
itemData.setMAX_FRAME_DURATION(aLong);
return camera;
int lensFacing = characteristics.get(CameraCharacteristics.LENS_FACING);
itemData.setLENS_FACING(lensFacing);
switch (lensFacing) {
case CameraMetadata.LENS_FACING_FRONT:
Log.e("lensFacing(前后摄):", "front");
break;
case CameraMetadata.LENS_FACING_BACK:
Log.e("lensFacing(前后摄):", "back");
break;
case CameraMetadata.LENS_FACING_EXTERNAL:
Log.e("lensFacing(前后摄):", "external");
break;
}
private Camera.Size adaptPreviewResolution(Camera.Size resolution) {
float diff = 100f;
float xdy = (float) resolution.width / (float) resolution.height;
Camera.Size best = null;
for (Camera.Size size : mCamera.getParameters().getSupportedPreviewSizes()) {
if (size.equals(resolution)) {
return size;
List<int[]> list = new ArrayList<>();
Size[] supportedSizes = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(ImageFormat.YUV_420_888);
for (Size size : supportedSizes) {
int width = size.getWidth();
int height = size.getHeight();
// 在这里处理支持的分辨率格式
int[] temp = {width, height};
list.add(temp);
}
float tmp = Math.abs(((float) size.width / (float) size.height) - xdy);
if (tmp < diff) {
diff = tmp;
best = size;
itemData.setSupportedSizes(list);//摄像头输出格式
itemlist.add(itemData);
}
return itemlist;
}
return best;
public List<CameraItemData> getCameraData() {
return itemlist;
}
private int[] adaptFpsRange(int expectedFps, List<int[]> fpsRanges) {
@ -472,40 +541,33 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
}
return closestRange;
}
public void setOrtation(int cameraid) {
// magicFilter.setOrtation(cameraid);
// magicFilter.initTex();
// setFilter(MagicFilterType.NONE,cameraid);
magicFilter.initTExt(cameraid);
public boolean startTorch() {
if (mCamera != null) {
Camera.Parameters params = mCamera.getParameters();
List<String> supportedFlashModes = params.getSupportedFlashModes();
if (supportedFlashModes != null && !supportedFlashModes.isEmpty()) {
if (supportedFlashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)) {
params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(params);
return true;
}
}
}
return false;
}
public void stopTorch() {
if (mCamera != null) {
try {
Camera.Parameters params = mCamera.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
mCamera.setParameters(params);
}catch (Exception e){
e.printStackTrace();
}
}
// if (mCamera != null) {
// try {
// Camera.Parameters params = mCamera.getParameters();
// params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
// mCamera.setParameters(params);
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
}
public interface PreviewCallback {
void onGetRgbaFrame(byte[] data, int width, int height);
}
static public class CameraCallbacksHandler implements CameraCallbacks{
static public class CameraCallbacksHandler implements CameraCallbacks {
@Override
public void onCameraParameters(Camera.Parameters params) {
@ -521,6 +583,7 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
public interface CameraCallbacks {
void onCameraParameters(Camera.Parameters params);
void onError(Exception e);
}

@ -1,14 +1,13 @@
package net.ossrs.yasea;
import android.hardware.Camera;
import android.media.AudioRecord;
import android.media.audiofx.AcousticEchoCanceler;
import android.media.audiofx.AutomaticGainControl;
import com.github.faucamp.simplertmp.RtmpHandler;
import com.seu.magicfilter.utils.MagicFilterType;
import java.io.File;
import java.util.List;
/**
* Created by Leo Ma on 2016/7/25.
@ -160,11 +159,13 @@ public class SrsPublisher {
stopCamera();
mEncoder.stop();
}
public void pauseEncode(){
public void pauseEncode() {
stopAudio();
mCameraView.disableEncoding();
mCameraView.stopTorch();
}
private void resumeEncode() {
startAudio();
mCameraView.enableEncoding();
@ -177,8 +178,9 @@ public class SrsPublisher {
startEncode();
}
}
public void resumePublish(){
if(mFlvMuxer != null) {
public void resumePublish() {
if (mFlvMuxer != null) {
mEncoder.resume();
resumeEncode();
}
@ -191,12 +193,13 @@ public class SrsPublisher {
}
}
public void pausePublish(){
public void pausePublish() {
if (mFlvMuxer != null) {
mEncoder.pause();
pauseEncode();
}
}
public boolean startRecord(String recPath) {
return mMp4Muxer != null && mMp4Muxer.record(new File(recPath));
}
@ -219,12 +222,12 @@ public class SrsPublisher {
}
}
public boolean isAllFramesUploaded(){
public boolean isAllFramesUploaded() {
return mFlvMuxer.getVideoFrameCacheNumber().get() == 0;
}
public int getVideoFrameCacheCount(){
if(mFlvMuxer != null) {
public int getVideoFrameCacheCount() {
if (mFlvMuxer != null) {
return mFlvMuxer.getVideoFrameCacheNumber().get();
}
return 0;
@ -258,9 +261,6 @@ public class SrsPublisher {
return mCameraView.getCameraId();
}
public Camera getCamera() {
return mCameraView.getCamera();
}
public void setPreviewResolution(int width, int height) {
int resolution[] = mCameraView.setPreviewResolution(width, height);
@ -304,19 +304,24 @@ public class SrsPublisher {
sendAudioOnly = flag;
}
public boolean switchCameraFilter(MagicFilterType type) {
return mCameraView.setFilter(type);
}
public void switchCameraFace(int id) {
List<CameraItemData> cameraData = mCameraView.getCameraData();
CameraItemData item = cameraData.get(id);
int cameraid = 0;
try {
cameraid = Integer.parseInt( item.getId());
} catch (Exception e) {
cameraid = 0;
}
mCameraView.setOrtation(cameraid);
if (mEncoder != null && mEncoder.isEnabled()) {
mEncoder.pause();
}
mCameraView.stopCamera();
mCameraView.setCameraId(id);
if (id == 0) {
mCameraView.setCameraId(item);
if (item.getLENS_FACING() == 0) {
mEncoder.setCameraBackFace();
} else {
mEncoder.setCameraFrontFace();

@ -1 +1,27 @@
//pluginManagement {
// repositories {
// maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
// maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter' }
// maven { url 'https://maven.aliyun.com/nexus/content/repositories/google' }
// maven { url 'https://maven.aliyun.com/nexus/content/repositories/gradle-plugin' }
// maven { url 'https://developer.huawei.com/repo/' }
// maven { url "https://jitpack.io" }
// google()
// mavenCentral()
// gradlePluginPortal()
// }
//}
//dependencyResolutionManagement {
// repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
// repositories {
// maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
// maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter' }
// maven { url 'https://maven.aliyun.com/nexus/content/repositories/google' }
// maven { url 'https://maven.aliyun.com/nexus/content/repositories/gradle-plugin' }
// maven { url 'https://developer.huawei.com/repo/' }
// maven { url "https://jitpack.io" }
// google()
// mavenCentral()
// }
//}
include ':app', ':library'

Loading…
Cancel
Save