合并camera2代码

master
Matthew 8 months ago
parent 8cf7934629
commit 13a9f9458f

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

@ -28,6 +28,7 @@ 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,10 +36,11 @@ 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,
SrsRecordHandler.SrsRecordListener, SrsEncodeHandler.SrsEncodeListener {
SrsRecordHandler.SrsRecordListener, SrsEncodeHandler.SrsEncodeListener {
private static final String TAG = "MpLive";
public final static int RC_CAMERA = 100;
@ -50,7 +52,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 +64,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 +89,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 +137,44 @@ 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);
int rotation = intent.getIntExtra("rotation", -1);
if (rotation != -1) {
//设置图像显示方向
mCameraView.setPreviewOrientation(rotation);
}
mPublisher = new SrsPublisher(mCameraView);
String url = intent.getStringExtra("url");
if (!TextUtils.isEmpty(url)) {
rtmpUrl = url;
cameraData = mCameraView.getCameraData();
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 +233,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 +246,11 @@ 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);
}
}
});
@ -352,10 +360,10 @@ public class MainActivity extends AppCompatActivity implements RtmpHandler.RtmpL
@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

@ -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,10 @@
<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>
</resources>

@ -4,6 +4,7 @@ buildscript {
repositories {
jcenter()
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.1'
@ -17,6 +18,7 @@ allprojects {
repositories {
jcenter()
google()
mavenCentral()
}
}

@ -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">

@ -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();
}
}
}

@ -2,15 +2,27 @@ 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.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 +30,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;
@ -47,8 +60,6 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
private float[] mProjectionMatrix = new float[16];
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 +70,15 @@ 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<>();
public SrsCameraView(Context context) {
this(context, null);
@ -70,6 +90,7 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
setEGLContextClientVersion(2);
setRenderer(this);
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
initCameraData();
}
@Override
@ -89,15 +110,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
@ -121,7 +134,7 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
public void onDrawFrame(GL10 gl) {
if(mSurfaceWidth != mPreviewWidth || mSurfaceHeight != mPreviewHeight){
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?
@ -152,39 +165,73 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
mPrevCb = cb;
}
public Camera getCamera(){
return this.mCamera;
}
public void setPreviewCallback(Camera.PreviewCallback previewCallback){
this.mCamera.setPreviewCallback(previewCallback);
//选择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;
}
}
}
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();
// mCamera = openCamera();
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;
mInputAspectRatio = mPreviewWidth > mPreviewHeight ? (float) mPreviewWidth / mPreviewHeight : (float) mPreviewHeight / mPreviewWidth;
return new int[] { mPreviewWidth, mPreviewHeight };
return new int[]{mPreviewWidth, mPreviewHeight};
}
public boolean setFilter(final MagicFilterType type) {
if (mCamera == null) {
return false;
}
queueEvent(new Runnable() {
@Override
@ -209,16 +256,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 +282,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 +291,7 @@ 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;
}
setRotation(180);
}
public int getCameraId() {
@ -285,7 +308,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 +351,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(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);
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 onDisconnected(CameraDevice camera) {
//相机链接断开
Log.e("dsdsfd", "fdsdf");
}
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 onError(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(CameraCaptureSession session) {
if (mCameraDevice == null) {
return;
}
cameraCaptureSession = session;
updatePreview();
}
} else {
params.setFlashMode(supportedFlashModes.get(0));
}
@Override
public void onConfigureFailed(CameraCaptureSession session) {
Log.e("dkkd", "fdsa");
}
}, null);
} catch (CameraAccessException e) {
throw new RuntimeException(e);
}
cameraCallbacksHandler.onCameraParameters(params);
mCamera.setParameters(params);
mCamera.setDisplayOrientation(mPreviewRotation);
}
private void updatePreview() {
captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
CaptureRequest captureRequest = captureRequestBuilder.build();
try {
mCamera.setPreviewTexture(surfaceTexture);
} catch (IOException e) {
e.printStackTrace();
cameraCaptureSession.setRepeatingRequest(captureRequest, null, null);
} catch (CameraAccessException e) {
throw new RuntimeException(e);
}
mCamera.startPreview();
}
return true;
public void startCamera() {
try {
if (curItem == null) {
curItem = itemlist.get(0);
}
//通过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.YUV_420_888, 10);
// imageReader.setOnImageAvailableListener(onImageAvailableListener,null);
// if (Activity.checkSelfPermission(getContext(), android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
// }
cameraManager.openCamera(cameraId, stateCallback, null);
} catch (CameraAccessException e) {
throw new RuntimeException(e);
}
}
public void stopCamera() {
disableEncoding();
stopTorch();
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
if (cameraCaptureSession != null) {
cameraCaptureSession.close();
cameraCaptureSession = null;
}
if (mCameraDevice != null) {
mCameraDevice.close();
mCameraDevice = 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 (frontCamId != -1) {
mCamId = frontCamId;
} else if (backCamId != -1) {
mCamId = backCamId;
} else {
mCamId = 0;
}
public List<CameraItemData> initCameraData() {
itemlist = new ArrayList();
cameraManager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE);//获取摄像头管理类
try {
cameraNames = cameraManager.getCameraIdList();//获取摄像头名称列表
} catch (CameraAccessException e) {
throw new RuntimeException(e);
}
try {
camera = Camera.open(mCamId);
for (String cameraName : cameraNames) {
CameraItemData itemData = new CameraItemData();
itemData.setId(cameraName);//摄像头编号
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();
}
});
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);//摄像头朝向
}catch (Exception e){
e.printStackTrace();
}
return camera;
}
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);
int lensFacing = characteristics.get(CameraCharacteristics.LENS_FACING);
itemData.setLENS_FACING(lensFacing);
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;
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;
}
float tmp = Math.abs(((float) size.width / (float) size.height) - xdy);
if (tmp < diff) {
diff = tmp;
best = 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);
}
itemData.setSupportedSizes(list);//摄像头输出格式
itemlist.add(itemData);
}
return best;
return itemlist;
}
public List<CameraItemData> getCameraData() {
return itemlist;
}
private int[] adaptFpsRange(int expectedFps, List<int[]> fpsRanges) {
@ -473,31 +533,16 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
return closestRange;
}
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 {
@ -505,7 +550,7 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
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 +566,7 @@ public class SrsCameraView extends GLSurfaceView implements GLSurfaceView.Render
public interface CameraCallbacks {
void onCameraParameters(Camera.Parameters params);
void onError(Exception e);
}

@ -1,6 +1,5 @@
package net.ossrs.yasea;
import android.hardware.Camera;
import android.media.AudioRecord;
import android.media.audiofx.AcousticEchoCanceler;
import android.media.audiofx.AutomaticGainControl;
@ -9,6 +8,7 @@ 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 +160,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 +179,9 @@ public class SrsPublisher {
startEncode();
}
}
public void resumePublish(){
if(mFlvMuxer != null) {
public void resumePublish() {
if (mFlvMuxer != null) {
mEncoder.resume();
resumeEncode();
}
@ -191,12 +194,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 +223,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 +262,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);
@ -309,14 +310,15 @@ public class SrsPublisher {
}
public void switchCameraFace(int id) {
List<CameraItemData> cameraData = mCameraView.getCameraData();
CameraItemData item = cameraData.get(id);
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();

Loading…
Cancel
Save