Camera 1 / 2 /x介绍
Camera1 在5.0以前系统上使用、使用方法也很简单
Camera.open()打开摄像头,获取当前设备的摄像头个数,根据id打开摄像头,如果想要做视频直播的话,在设置预览回调,设置预览buffer,设置摄像头采集视频流格式、一般采集格式Nv21,android标准采集方式、在预览回调里取出预览buff,然后转换yuv数据,交给ffmpeg软编成H264数据或者通过MediaCodec硬编成H264、发送给服务器
基本上这就是camera采集数据方式
之前做过android智慧平板项目,由于系统5.0以上的比较少、所以也就一直使用camera1版本,另外扩展和借鉴的是外国大神的OpenCamera 并在Camera1上做了许多扩展 、查看地址
Camera2是5.0时,谷歌针对摄像头新推出的一套api
通过获取CameraService获取CameraManagr,并通过CameraManager.openCamera方法打开camera,并注册camera开启监听回调,新增了ImageReader设置,并通过ImageReader设置监听,通过监听回调拿到ImageReader获取的预览buffer,并拿出buffer 之后操作差不多
CameraX是jetpack的一个支持库、提供的方法
// CameraX core library.
implementation "androidx.camera:camera-core:1.0.0"
// If you want to use Camera2 extensions.
implementation "androidx.camera:camera-camera2:1.0.0"
implementation "androidx.camera:camera-lifecycle:1.0.0"
//other
// If you to use the Camera View class
implementation "androidx.camera:camera-view:1.0.0-alpha24"
// If you to use Camera Extensions
implementation "androidx.camera:camera-extensions:1.0.0-alpha24"
复制代码
private fun startCamera() {
//获取CameraProvider
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
//添加监听
cameraProviderFuture.addListener(Runnable {
获取cameraProvider
val cameraProvider = cameraProviderFuture.get()
//设置imageCapturem模式初始化
imageCapture = ImageCapture.Builder().setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY).build()
//设置预览监听并把预览buffer,通过自定义接口回调出来byteBuffer
imageAnalyzer = ImageAnalysis.Builder()
.build()
.also {
it.setAnalyzer(cameraExecutor,ImageAnalysis.Analyzer { image ->
val rotationDegrees = image.imageInfo.rotationDegrees
val buffer = image.planes[0].buffer as ByteBuffer
//拿到buffer处理成自己需要的就行了
image.close()
})
}
preview = Preview.Builder().build()
val cameraSelector =
CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build()
cameraProvider.unbindAll()
//绑定cameraProvider生命周期
camera = cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture,imageAnalyzer)
//1.0.0版本surfaceProvider系同已经创建好了
preview?.setSurfaceProvider(viewFinder.surfaceProvider)
}, ContextCompat.getMainExecutor(this))
}
复制代码
//获取CameraProvider
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
//源码方法
@NonNull
public static ListenableFuture<ProcessCameraProvider> getInstance(
@NonNull Context context) {
return Futures.transform(CameraX.getOrCreateInstance(context), cameraX -> {
sAppInstance.setCameraX(cameraX);
return sAppInstance;
}, CameraXExecutors.directExecutor());
}
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public static ListenableFuture<CameraX> getOrCreateInstance(@NonNull Context context) {
Preconditions.checkNotNull(context, "Context must not be null.");
synchronized (INSTANCE_LOCK) {
boolean isConfigured = sConfigProvider != null;
ListenableFuture<CameraX> instanceFuture = getInstanceLocked();
if (instanceFuture.isDone()) {
try {
instanceFuture.get();
} catch (InterruptedException e) {
// Should not be possible since future is complete.
throw new RuntimeException("Unexpected thread interrupt. Should not be "
+ "possible since future is already complete.", e);
} catch (ExecutionException e) {
// Either initialization failed or initialize() has not been called, ensure we
// can try to reinitialize.
shutdownLocked();
instanceFuture = null;
}
}
if (instanceFuture == null) {
if (!isConfigured) {
// Attempt initialization through Application or Resources
CameraXConfig.Provider configProvider = getConfigProvider(context);
if (configProvider == null) {
throw new IllegalStateException("CameraX is not configured properly. "
+ "The most likely cause is you did not include a default "
+ "implementation in your build such as 'camera-camera2'.");
}
configureInstanceLocked(configProvider);
}
//初始化cameraX方法
initializeInstanceLocked(context);
instanceFuture = getInstanceLocked();
}
return instanceFuture;
}
}
@GuardedBy("INSTANCE_LOCK")
private static void initializeInstanceLocked(@NonNull Context context) {
Preconditions.checkNotNull(context);
Preconditions.checkState(sInstance == null, "CameraX already initialized.");
Preconditions.checkNotNull(sConfigProvider);
//初始化camerax
CameraX cameraX = new CameraX(sConfigProvider.getCameraXConfig());
sInstance = cameraX;
sInitializeFuture = CallbackToFutureAdapter.getFuture(completer -> {
synchronized (INSTANCE_LOCK) {
// The sShutdownFuture should always be successful, otherwise it will not
// propagate to transformAsync() due to the behavior of FutureChain.
ListenableFuture<Void> future = FutureChain.from(sShutdownFuture)
.transformAsync(input -> cameraX.initInternal(context),
CameraXExecutors.directExecutor());
Futures.addCallback(future, new FutureCallback<Void>() {
@Override
public void onSuccess(@Nullable Void result) {
completer.set(null);
}
@SuppressWarnings("FutureReturnValueIgnored")
@Override
public void onFailure(Throwable t) {
Logger.w(TAG, "CameraX initialize() failed", t);
// Call shutdown() automatically, if initialization fails.
synchronized (INSTANCE_LOCK) {
// Make sure it is the same instance to prevent reinitialization
// during initialization.
if (sInstance == cameraX) {
shutdownLocked();
}
}
completer.setException(t);
}
}, CameraXExecutors.directExecutor());
return "CameraX-initialize";
}
});
}
复制代码
preview?.setSurfaceProvider(viewFinder.surfaceProvider)
使用PreviewViews视图创建预览方法时,系统已经给我们创建好了一个Preview.SurfaceProvider()直接绑定就行了
// Synthetic access
@SuppressWarnings("WeakerAccess")
final Preview.SurfaceProvider mSurfaceProvider = new Preview.SurfaceProvider() {
@OptIn(markerClass = ExperimentalUseCaseGroup.class)
@Override
@AnyThread
public void onSurfaceRequested(@NonNull SurfaceRequest surfaceRequest) {
if (!Threads.isMainThread()) {
// Post on main thread to ensure thread safety.
ContextCompat.getMainExecutor(getContext()).execute(
() -> mSurfaceProvider.onSurfaceRequested(surfaceRequest));
return;
}
Logger.d(TAG, "Surface requested by Preview.");
CameraInternal camera = surfaceRequest.getCamera();
surfaceRequest.setTransformationInfoListener(
ContextCompat.getMainExecutor(getContext()),
transformationInfo -> {
Logger.d(TAG,
"Preview transformation info updated. " + transformationInfo);
// TODO(b/159127402): maybe switch to COMPATIBLE mode if target
// rotation is not display rotation.
boolean isFrontCamera =
camera.getCameraInfoInternal().getLensFacing()
== CameraSelector.LENS_FACING_FRONT;
mPreviewTransform.setTransformationInfo(transformationInfo,
surfaceRequest.getResolution(), isFrontCamera);
redrawPreview();
});
mImplementation = shouldUseTextureView(surfaceRequest, mImplementationMode)
? new TextureViewImplementation(PreviewView.this, mPreviewTransform)
: new SurfaceViewImplementation(PreviewView.this, mPreviewTransform);
PreviewStreamStateObserver streamStateObserver =
new PreviewStreamStateObserver(camera.getCameraInfoInternal(),
mPreviewStreamStateLiveData, mImplementation);
mActiveStreamStateObserver.set(streamStateObserver);
camera.getCameraState().addObserver(
ContextCompat.getMainExecutor(getContext()), streamStateObserver);
mImplementation.onSurfaceRequested(surfaceRequest, () -> {
// We've no longer needed this observer, if there is no new StreamStateObserver
// (another SurfaceRequest), reset the streamState to IDLE.
// This is needed for the case when unbinding preview while other use cases are
// still bound.
if (mActiveStreamStateObserver.compareAndSet(streamStateObserver, null)) {
streamStateObserver.updatePreviewStreamState(StreamState.IDLE);
}
streamStateObserver.clear();
camera.getCameraState().removeObserver(streamStateObserver);
});
}
};
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END