赞
踩
UVCAndroid是一款用于安卓UVC相机的通用开发库。
GitHub源码地址:https://github.com/shiyinghan/UVCAndroid
主要功能包括:
(1) 支持USB Camera设备检测,画面实时预览;
(2) 支持抓拍jpg格式图片,可设置图片压缩质量;
(3) 支持录制mp4格式视频,可屏蔽音频,可设置视频和音频的录制参数;
(4) 支持获取camera支持的分辨率,和分辨率切换;
(5) 支持预览自动识别各种相机的分辨率;
(6) 支持旋转摄像头90度、180度、270度;
(7) 支持调整对比度、亮度、色调、饱和度、白平衡等等一些相机控制参数;
(8) 支持多预览和多摄像头;
(9) 支持Android5.0+;
第一步 添加mavenCentral仓库到工程gradle文件
Step 1. Add the mavenCentral repository to your build file
Add it in your root build.gradle at the end of repositories:
allprojects {
repositories {
...
mavenCentral()
}
}
第二步 添加依赖到app Module的gradle文件
dependencies {
implementation 'com.herohan:UVCAndroid:1.0.5'
}
Request permissions
List<String> needPermissions = new ArrayList<>(); needPermissions.add(Manifest.permission.CAMERA); needPermissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);//拍照和录制视频时需要该权限 //needPermissions.add(Manifest.permission.MANAGE_EXTERNAL_STORAGE); //Android 11 使用该权限替代 WRITE_EXTERNAL_STORAGE needPermissions.add(Manifest.permission.RECORD_AUDIO);//录制视频时需要音频时需要该权限 //这里使用XXPermissions开源框架获取权限,你也可以使用系统原生的,或者其他开源框架获取权限 XXPermissions.with(this) .permission(needPermissions) .request((permissions, all) -> { if(!all){ return; } //摄像头业务操作 });
<application
...
android:requestLegacyExternalStorage="true"
>
Initialize CameraHelper,set UVC Camera state callback
private ICameraHelper mCameraHelper; private AspectRatioSurfaceView mCameraViewMain; private ICameraHelper.StateCallback mStateListener; //UVC摄像头状态回调 mStateListener = new ICameraHelper.StateCallback() { //插入UVC设备 @Override public void onAttach(UsbDevice device) { //设置为当前设备(如果没有权限,会显示授权对话框) mCameraHelper.selectDevice(device); } //打开UVC设备成功(也就是已经获取到UVC设备的权限) @Override public void onDeviceOpen(UsbDevice device, boolean isFirstOpen) { //打开UVC摄像头 mCameraHelper.openCamera(); } //打开摄像头成功 @Override public void onCameraOpen(UsbDevice device) { //开始预览 mCameraHelper.startPreview(); //获取预览使用的Size(包括帧格式、宽度、高度、FPS) Size size = mCameraHelper.getPreviewSize(); if (size != null) { int width = size.width; int height = size.height; //需要自适应摄像头分辨率的话,设置新的宽高比 mCameraViewMain.setAspectRatio(width, height); } //添加预览Surface mCameraHelper.addSurface(mCameraViewMain.getHolder().getSurface(), false); } //关闭摄像头成功 @Override public void onCameraClose(UsbDevice device) { if (mCameraHelper != null) { //移除预览Surface mCameraHelper.removeSurface(mCameraViewMain.getHolder().getSurface()); } } //关闭UVC设备成功 @Override public void onDeviceClose(UsbDevice device) { } //断开UVC设备 @Override public void onDetach(UsbDevice device) { } //用户没有授予访问UVC设备的权限 @Override public void onCancel(UsbDevice device) { } }; //设置SurfaceView的Surface监听回调 mCameraViewMain.getHolder().addCallback(new SurfaceHolder.Callback() { //创建了新的Surface @Override public void surfaceCreated(@NonNull SurfaceHolder holder) { if (mCameraHelper != null) { //添加预览Surface mCameraHelper.addSurface(holder.getSurface(), false); } } //Surface发生了改变 @Override public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) { } //销毁了原来的Surface @Override public void surfaceDestroyed(@NonNull SurfaceHolder holder) { if (mCameraHelper != null) { //移除预览Surface mCameraHelper.removeSurface(holder.getSurface()); } } }); mCameraHelper = new CameraHelper(); //设置UVC摄像头状态回调 mCameraHelper.setStateCallback(mStateListener);
Release CameraHelper(including canceling UVC Camera state callback, stopping Camera preview, etc.)
mCameraHelper.release();
Image Capture
//设置视图片抓拍全局参数(非必须,可以不设置,使用默认值) mCameraHelper.setImageCaptureConfig( mCameraHelper.getImageCaptureConfig().setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)); // mCameraHelper.setImageCaptureConfig( // mCameraHelper.getImageCaptureConfig().setJpegCompressionQuality(90)); //设置需要保存图片文件 File file = FileUtils.getCaptureFile(this, Environment.DIRECTORY_DCIM, ".jpg"); ImageCapture.OutputFileOptions options = new ImageCapture.OutputFileOptions.Builder(file).build(); // ContentValues contentValues = new ContentValues(); // contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "NEW_IMAGE"); // contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg"); // // ImageCapture.OutputFileOptions options = new ImageCapture.OutputFileOptions.Builder( // getContentResolver(), // MediaStore.Images.Media.EXTERNAL_CONTENT_URI, // contentValues).build(); // ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); // ImageCapture.OutputFileOptions options = new ImageCapture.OutputFileOptions.Builder(outputStream).build(); //进行图片抓拍 mCameraHelper.takePicture(options, new ImageCapture.OnImageCaptureCallback() { //图片抓拍成功 @Override public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) { Toast.makeText(TakePictureActivity.this, "save \"" + UriHelper.getPath(TakePictureActivity.this, outputFileResults.getSavedUri()) + "\"", Toast.LENGTH_SHORT).show(); } //图片抓拍出现错误 @Override public void onError(int imageCaptureError, @NonNull String message, @Nullable Throwable cause) { Toast.makeText(TakePictureActivity.this, message, Toast.LENGTH_SHORT).show(); } });
Video Capture
//设置视频录制全局参数(非必须,可以不设置,使用默认值) mCameraHelper.setVideoCaptureConfig( mCameraHelper.getVideoCaptureConfig() .setAudioCaptureEnable(true) // true:有音频;false:没有音频(默认为true) .setBitRate((int) (1024 * 1024 * 25 * 0.25)) .setVideoFrameRate(25) .setIFrameInterval(1)); //设置需要保存视频文件 File file = FileUtils.getCaptureFile(this, Environment.DIRECTORY_MOVIES, ".mp4"); VideoCapture.OutputFileOptions options = new VideoCapture.OutputFileOptions.Builder(file).build(); // ContentValues contentValues = new ContentValues(); // contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "NEW_VIDEO"); // contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4"); // // VideoCapture.OutputFileOptions options = new VideoCapture.OutputFileOptions.Builder( // getContentResolver(), // MediaStore.Video.Media.EXTERNAL_CONTENT_URI, // contentValues).build(); //开始录制 mCameraHelper.startRecording(options, new VideoCapture.OnVideoCaptureCallback() { @Override public void onStart() { } //视频录制成功 @Override public void onVideoSaved(@NonNull VideoCapture.OutputFileResults outputFileResults) { Toast.makeText( RecordVideoActivity.this, "save \"" + UriHelper.getPath(RecordVideoActivity.this, outputFileResults.getSavedUri()) + "\"", Toast.LENGTH_SHORT).show(); } //视频录制出现错误 @Override public void onError(int videoCaptureError, @NonNull String message, @Nullable Throwable cause) { Toast.makeText(RecordVideoActivity.this, message, Toast.LENGTH_LONG).show(); } });
Set camera preview parameters (including frame format, width, height, FPS)
//停止相机预览
mCameraHelper.stopPreview();
//设置摄像机预览参数
mCameraHelper.setPreviewSize(size);
//开始相机预览
mCameraHelper.startPreview();
//需要自适应摄像头分辨率的话,设置新的宽高比
mCameraViewMain.setAspectRatio(mPreviewWidth, mPreviewHeight);
Size里面的帧格式type只支持UVCCamera.UVC_VS_FRAME_UNCOMPRESSED(YUV格式)和UVCCamera.UVC_VS_FRAME_MJPEG(Mjpeg格式),使用的时候需要摄像头支持(摄像头可能支持YUV格式或者Mjpeg格式)。
Adjust contrast, brightness, hue, saturation, white balance, and other camera controls
//获取UVCControl对象,通过该对象调整相机控制参数 UVCControl control = mCameraHelper.getUVCControl(); //根据监听器设置各种相机控制参数 private void setAllControlChangeListener(UVCControl controls) { // Brightness isbBrightness.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setBrightness(seekParams.progress)); // Contrast isbContrast.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setContrast(seekParams.progress)); // Contrast Auto cbContrastAuto.setOnCheckedChangeListener((buttonView, isChecked) -> { controls.setContrastAuto(isChecked); }); // Hue isbHue.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setHue(seekParams.progress)); // Hue Auto cbHueAuto.setOnCheckedChangeListener((buttonView, isChecked) -> { controls.setHueAuto(isChecked); }); // Saturation isbSaturation.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setSaturation(seekParams.progress)); // Sharpness isbSharpness.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setSharpness(seekParams.progress)); // Gamma isbGamma.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setGamma(seekParams.progress)); // White Balance isbWhiteBalance.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setWhiteBalance(seekParams.progress)); // White Balance Auto cbWhiteBalanceAuto.setOnCheckedChangeListener((buttonView, isChecked) -> { controls.setWhiteBalanceAuto(isChecked); }); // Backlight Compensation isbBacklightComp.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setBacklightComp(seekParams.progress)); // Gain isbGain.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setGain(seekParams.progress)); // Exposure Time isbExposureTime.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setExposureTimeAbsolute(seekParams.progress)); // Exposure Time Auto cbExposureTimeAuto.setOnCheckedChangeListener((buttonView, isChecked) -> { controls.setExposureTimeAuto(isChecked); }); // Iris isbIris.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setIrisAbsolute(seekParams.progress)); // Focus isbFocus.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setFocusAbsolute(seekParams.progress)); // Focus Auto cbFocusAuto.setOnCheckedChangeListener((buttonView, isChecked) -> { controls.setFocusAuto(isChecked); }); // Zoom isbZoom.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setZoomAbsolute(seekParams.progress)); // Pan isbPan.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setPanAbsolute(seekParams.progress)); // Tilt isbTilt.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setTiltAbsolute(seekParams.progress)); // Roll isbRoll.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setRollAbsolute(seekParams.progress)); // Power Line Frequency rgPowerLineFrequency.setOnCheckedChangeListener((group, checkedId) -> { int value = 0; if (checkedId == R.id.rbPowerLineFrequencyDisable) { value = 0; } else if (checkedId == R.id.rbPowerLineFrequency50Hz) { value = 1; } else if (checkedId == R.id.rbPowerLineFrequency60Hz) { value = 2; } else if (checkedId == R.id.rbPowerLineFrequencyAuto) { value = 3; } controls.setPowerlineFrequency(value); }); } // 重置所有相机控制参数为初试值 private void resetAllControlParams(UVCControl control) { // Brightness control.resetBrightness(); // Contrast control.resetContrast(); // Contrast Auto control.resetContrastAuto(); // Hue control.resetHue(); // Hue Auto control.resetHueAuto(); // Saturation control.resetSaturation(); // Sharpness control.resetSharpness(); // Gamma control.resetGamma(); // White Balance control.resetWhiteBalance(); // White Balance Auto control.resetWhiteBalanceAuto(); // Backlight Compensation control.resetBacklightComp(); // Gain control.resetGain(); // Exposure Time control.resetExposureTimeAbsolute(); // Auto-Exposure Mode control.resetAutoExposureMode(); // Iris control.resetIrisAbsolute(); // Focus control.resetFocusAbsolute(); // Focus Auto control.resetFocusAuto(); // Zoom control.resetZoomAbsolute(); // Pan control.resetPanAbsolute(); // Tilt control.resetTiltAbsolute(); // Roll control.resetRollAbsolute(); // Power Line Frequency control.resetPowerlineFrequency(); }
Rotate the camera 90 degrees, 180 degrees, and 270 degrees , set the camera preview mirror
//旋转摄像头 private void rotateBy(int angle) { mPreviewRotation += angle; mPreviewRotation %= 360; if (mPreviewRotation < 0) { mPreviewRotation += 360; } if (mCameraHelper != null) { mCameraHelper.setPreviewConfig( mCameraHelper.getPreviewConfig().setRotation(mPreviewRotation)); } } //设置水平镜像显示 private void flipHorizontally() { if (mCameraHelper != null) { mCameraHelper.setPreviewConfig( mCameraHelper.getPreviewConfig().setMirror(MirrorMode.MIRROR_HORIZONTAL)); } } //设置垂直镜像显示 private void flipVertically() { if (mCameraHelper != null) { mCameraHelper.setPreviewConfig( mCameraHelper.getPreviewConfig().setMirror(MirrorMode.MIRROR_VERTICAL)); } }
Set multiple previews
mCameraHelper.addSurface(svCameraViewMain.getHolder().getSurface(), false);
mCameraHelper.addSurface(svCameraViewSecond.getHolder().getSurface(), false);
mCameraHelper.addSurface(svCameraViewThird.getHolder().getSurface(), false);
mCameraHelper.addSurface(svCameraViewFourth.getHolder().getSurface(), false);
Setting multiple Cameras
private ICameraHelper mCameraHelperLeft; private ICameraHelper mCameraHelperRight; private AspectRatioSurfaceView svCameraViewLeft; private AspectRatioSurfaceView svCameraViewRight; private UsbDevice mUsbDeviceLeft; private UsbDevice mUsbDeviceRight; private final ICameraHelper.StateCallback mStateListenerLeft = new ICameraHelper.StateCallback() { @Override public void onAttach(UsbDevice device) { synchronized (mSync) { if (mUsbDeviceLeft == null && !device.equals(mUsbDeviceRight)) { selectDeviceLeft(device); } } } @Override public void onDeviceOpen(UsbDevice device, boolean isFirstOpen) { if (device.equals(mUsbDeviceLeft)) { UVCParam param = new UVCParam(); param.setQuirks(UVCCamera.UVC_QUIRK_FIX_BANDWIDTH); mCameraHelperLeft.openCamera(param); } } @Override public void onCameraOpen(UsbDevice device) { if (device.equals(mUsbDeviceLeft)) { mCameraHelperLeft.startPreview(); Size size = mCameraHelperLeft.getPreviewSize(); if (size != null) { int width = size.width; int height = size.height; //auto aspect ratio svCameraViewLeft.setAspectRatio(width, height); } mCameraHelperLeft.addSurface(svCameraViewLeft.getHolder().getSurface(), false); mIsCameraLeftConnected = true; } } @Override public void onCameraClose(UsbDevice device) { if (device.equals(mUsbDeviceLeft)) { if (mCameraHelperLeft != null) { mCameraHelperLeft.removeSurface(svCameraViewLeft.getHolder().getSurface()); } mIsCameraLeftConnected = false; } } @Override public void onDeviceClose(UsbDevice device) { } @Override public void onDetach(UsbDevice device) { if (device.equals(mUsbDeviceLeft)) { mUsbDeviceLeft = null; } } @Override public void onCancel(UsbDevice device) { if (device.equals(mUsbDeviceLeft)) { mUsbDeviceLeft = null; } } }; private final ICameraHelper.StateCallback mStateListenerRight = new ICameraHelper.StateCallback() { @Override public void onAttach(UsbDevice device) { synchronized (mSync) { if (mUsbDeviceRight == null && !device.equals(mUsbDeviceLeft)) { selectDeviceRight(device); } } } @Override public void onDeviceOpen(UsbDevice device, boolean isFirstOpen) { if (device.equals(mUsbDeviceRight)) { UVCParam param = new UVCParam(); param.setQuirks(UVCCamera.UVC_QUIRK_FIX_BANDWIDTH); mCameraHelperRight.openCamera(param); } } @Override public void onCameraOpen(UsbDevice device) { if (device.equals(mUsbDeviceRight)) { mCameraHelperRight.startPreview(); Size size = mCameraHelperRight.getPreviewSize(); if (size != null) { int width = size.width; int height = size.height; //auto aspect ratio svCameraViewRight.setAspectRatio(width, height); } mCameraHelperRight.addSurface(svCameraViewRight.getHolder().getSurface(), false); mIsCameraRightConnected = true; } } @Override public void onCameraClose(UsbDevice device) { if (device.equals(mUsbDeviceRight)) { if (mCameraHelperRight != null) { mCameraHelperRight.removeSurface(svCameraViewRight.getHolder().getSurface()); } mIsCameraRightConnected = false; } } @Override public void onDeviceClose(UsbDevice device) { } @Override public void onDetach(UsbDevice device) { if (device.equals(mUsbDeviceRight)) { mUsbDeviceRight = null; } } @Override public void onCancel(UsbDevice device) { if (device.equals(mUsbDeviceRight)) { mUsbDeviceRight = null; } } }; svCameraViewLeft.getHolder().addCallback(new SurfaceHolder.Callback() { @Override public void surfaceCreated(@NonNull SurfaceHolder holder) { if (mCameraHelperLeft != null) { mCameraHelperLeft.addSurface(holder.getSurface(), false); } } @Override public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(@NonNull SurfaceHolder holder) { if (mCameraHelperLeft != null) { mCameraHelperLeft.removeSurface(holder.getSurface()); } } }); svCameraViewRight.setAspectRatio(DEFAULT_WIDTH, DEFAULT_HEIGHT); svCameraViewRight.getHolder().addCallback(new SurfaceHolder.Callback() { @Override public void surfaceCreated(@NonNull SurfaceHolder holder) { if (mCameraHelperRight != null) { mCameraHelperRight.addSurface(holder.getSurface(), false); } } @Override public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(@NonNull SurfaceHolder holder) { if (mCameraHelperRight != null) { mCameraHelperRight.removeSurface(holder.getSurface()); } } }); mCameraHelperLeft = new CameraHelper(); mCameraHelperLeft.setStateCallback(mStateListenerLeft); mCameraHelperRight = new CameraHelper(); mCameraHelperRight.setStateCallback(mStateListenerRight);
方法 | 说明 |
---|---|
getDeviceList() | 获取当前检测到的所有UVC设备 |
getSupportedFormatList() | 获取当前摄像头支持的Format列表 |
getSupportedSizeList() | 获取当前摄像头支持的Size列表 |
getPreviewSize() | 获取当前摄像头正在使用的预览Size |
setButtonCallback() | 设置按钮事件回调 |
setFrameCallback() | 设置实时预览图像数据回调(请在StateCallback的onDeviceOpen或者onCameraOpen回调函数里面调用,使用方法可以参考demo里面的SetFrameCallbackActivity),支持格式 UVCCamera.PIXEL_FORMAT_YUV;PIXEL_FORMAT_NV12;PIXEL_FORMAT_NV21;PIXEL_FORMAT_RGB565;PIXEL_FORMAT_RGBX等格式 |
openCamera(Size size) | 用指定格式打开当前摄像头 |
closeCamera() | 关闭当前摄像头 |
isRecording() | 是否正在录像 |
isCameraOpened() | 是否已经打开当前摄像头 |
Download demo APK
app-debug.apk
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。