赞
踩
Camera、Camera2、CameraX?3者之间啥关系?
CameraX、CamX分不清?
今天我们就一起来学习、了解下这些内容,为大家解开迷惑。
这篇文章分下面几点展开:
1) CameraX初认识?
2) Google为啥要推出CameraX?
3) CameraX基本框架介绍;
4) CameraX的基本使用示例;
5) CameraX、Camx要分清;
1) CameraX 是一个 Jetpack 库,最低版本是兼容到Android5.0。好学的同学们,肯定又会问,那Jetpack库又是啥呢?
好了,那我们先来扯下Android Jetpack又是个啥。
在 Jetpack 的官方文档中是这样对它定义的:
Jetpack 是一套组件库,可帮助开发人员遵循最佳实践,减少样板代码并编写可在 Android 版本和设备上一致工作的代码,以便开发人员可以专注于他们关心的代码。
上面其实就是2个核心点,第一:Jetpack是一套组件库,注意,是一套,一套那就表示包含很多不同的组件。第二:使用Jetpack,方便我们在不同的android设备和不同的android版本上的适配,简单说,就是适配性强。
下面列表,就是热门和常用的Jetpack库,我们可以看到Camera也在其中,这个Camera*就是我们今天要重点介绍的CameraX。
上面介绍了这么多,大家应该对cameraX应该有个最基础的了解了。CameraX是一个 Jetpack 库。
这个CameraX库呢,然后呢,这个库是针对相机领域的。
关于这点,从前面Android Jetpack库的介绍里面,其实我们也基本可以知道原因了。这个库是为了方便我们在各个Android版本和Android设备直接的适配和兼容。
官方的介绍是这样的:
CameraX 是 Jetpack 的新增库。利用该库,可以更轻松地向应用添加相机功能。该库提供了很多兼容性修复程序和解决方法,有助于在众多设备上打造一致的开发者体验。
主要优势表现为以下几点:
1)广泛的设备兼容性
CameraX 支持搭载 Android 5.0(API 级别 21)或更高版本的设备,覆盖现有 Android 设备的 98% 以上。
2)易用性
CameraX 着重于用例,使您可以专注于需要完成的任务,而无需花时间处理不同设备之间的细微差别。CameraX 支持大多数常见的相机用例:
预览:在屏幕上查看图片。
图片分析:无缝访问缓冲区中的图片以便在算法中使用,例如将其传递到机器学习套件。
图片拍摄:保存图片。
视频拍摄:保存视频和音频。
3)确保各设备间的一致性
要维持一致的相机行为并非易事。您必须考虑宽高比、屏幕方向、旋转角度、预览大小和图像大小。有了 CameraX,这些基本行为都不用您再费心。
我们设立了一个自动化 CameraX 测试实验室,用于测试搭载了 Android 5.0 及更高版本的一系列设备和这些操作系统版本中的各种相机行为。我们将持续运行这些测试,以找出各种各样的问题并进行修复。
4)新体验
CameraX 有一个可选的 Extensions API,您只需两行代码,便可借助该 API 实现与设备的原生相机应用相同的特性和功能。
扩展程序包含焦外成像(人像)、高动态范围 (HDR)、夜间模式和脸部照片修复功能,所有这些都需要设备支持。
从下图我们可以看到,CameraX是基于Camera2的API进行的封装。
Camera API1,Google已经声明在Android5.0之后的设备上废弃了。所以,CameraX所能支持的功能,也就是Camera2所支持的功能。
目前CameraX为我们提供下下面几个最主要的功能,分别是预览、图片分析、图片拍摄、视频拍摄等。这些都是相机开发里面常用的功能。
1)实现预览
在向应用添加预览时,请使用 PreviewView
,这是一种可以剪裁、缩放和旋转以确保正确显示的 View
。
当相机处于活动状态时,图片预览会流式传输到 PreviewView
中的 Surface。
如需使用 PreviewView
实现 CameraX 预览,请按以下步骤操作(稍后将对这些步骤进行说明):
(可选)配置 CameraXConfig.Provider
。
将 PreviewView
添加到布局。
请求 ProcessCameraProvider
。
在创建 View
时,请检查 ProcessCameraProvider
。
选择相机并绑定生命周期和用例。
使用 PreviewView
存在一些限制。使用 PreviewView
时,您无法执行以下任何操作:
创建 SurfaceTexture
,以在 TextureView
和 Preview.SurfaceProvider
上进行设置。
从 TextureView
检索 SurfaceTexture
,并在 Preview.SurfaceProvider
上对其进行设置。
从 SurfaceView
获取 Surface
,并在 Preview.SurfaceProvider
上对其进行设置。
如果出现上述任何一种情况,Preview
就会停止将帧流式传输到 PreviewView
。
以下示例显示了布局中的 PreviewView
:
- <FrameLayout
- android:id="@+id/container">
- <androidx.camera.view.PreviewView
- android:id="@+id/previewView" />
- </FrameLayout>
以下代码展示了如何请求 CameraProvider
:
- import androidx.camera.lifecycle.ProcessCameraProvider
- import com.google.common.util.concurrent.ListenableFuture
-
- public class MainActivity extends AppCompatActivity {
- private ListenableFuture<ProcessCameraProvider> cameraProviderFuture;
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- cameraProviderFuture = ProcessCameraProvider.getInstance(this);
- }
- }
请求 CameraProvider
后,请验证它能否在视图创建后成功初始化。以下代码展示了如何执行此操作:
- cameraProviderFuture.addListener(() -> {
- try {
- ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
- bindPreview(cameraProvider);
- } catch (ExecutionException | InterruptedException e) {
- // No errors need to be handled for this Future.
- // This should never be reached.
- }
- }, ContextCompat.getMainExecutor(this));
如需查看此示例中使用的 bindPreview
函数的示例,请参阅下一部分中提供的代码。
创建并确认 CameraProvider
后,请执行以下操作:
创建 Preview
。
指定所需的相机 LensFacing
选项。
将所选相机和任意用例绑定到生命周期。
将 Preview
连接到 PreviewView
。
以下代码展示了一个示例:
- void bindPreview(@NonNull ProcessCameraProvider cameraProvider) {
- Preview preview = new Preview.Builder()
- .build();
-
- CameraSelector cameraSelector = new CameraSelector.Builder()
- .requireLensFacing(CameraSelector.LENS_FACING_BACK)
- .build();
-
- preview.setSurfaceProvider(previewView.getSurfaceProvider());
-
- Camera camera = cameraProvider.bindToLifecycle((LifecycleOwner)this, cameraSelector, preview);
- }
请注意,bindToLifecycle()
会返回一个 Camera
对象。如需详细了解如何控制相机输出(如变焦和曝光),请参阅此指南。
现在,您已完成实现相机预览的操作。请构建您的应用,然后确认预览是否出现在您的应用中并能按预期工作。
2) 图像分析
图像分析用例为您的应用提供可供 CPU 访问的图像,您可以对这些图像执行图像处理、计算机视觉或机器学习推断。应用会实现对每个帧运行的 analyze()
方法。
如需在您的应用中使用图像分析,请按以下步骤操作:
构建 ImageAnalysis
用例。
创建 ImageAnalysis.Analyzer
。
将分析器设为 ImageAnalysis
。
将生命周期所有者、相机选择器和 ImageAnalysis
用例绑定到生命周期。
绑定后,CameraX 会立即将图像发送到已注册的分析器。完成分析后,调用 ImageAnalysis.clearAnalyzer()
或解除绑定 ImageAnalysis
用例以停止分析。
ImageAnalysis
可将分析器(图像使用方)连接到 CameraX(图像生成方)。应用可以使用 ImageAnalysis.Builder
来构建 ImageAnalysis
对象。借助 ImageAnalysis.Builder
,应用可以进行以下配置:
图像输出参数:
格式:CameraX 可通过 setOutputImageFormat(int)
支持 YUV_420_888
和 RGBA_8888
。默认格式为 YUV_420_888
。
Resolution 和 AspectRatio:您可以设置其中一个参数,但请注意,您不能同时设置这两个值。
旋转角度。
目标名称:使用该参数进行调试。* 图像流控制:
后台执行器
图像队列深度(分析器和 CamaraX 之间)
背压策略
应用可以设置分辨率或宽高比,但不能同时设置这两个值。确切的输出分辨率取决于应用请求的大小(或宽高比)和硬件功能,并可能与请求的大小或宽高比不同。如需了解分辨率匹配算法,请参阅有关 setTargetResolution()
的文档
应用可以将输出图像像素配置为采用 YUV(默认)或 RGBA 颜色空间。设置 RGBA 输出格式时,CameraX 会在内部将图像从 YUV 颜色空间转换为 RGBA 颜色空间,并将图像位打包到 ImageProxy 第一个平面(其他两个平面未使用)的 ByteBuffer
中,序列如下:
- ImageProxy.getPlanes()[0].buffer[0]: alpha
- ImageProxy.getPlanes()[0].buffer[1]: red
- ImageProxy.getPlanes()[0].buffer[2]: green
- ImageProxy.getPlanes()[0].buffer[3]: blue
- ...
在执行设备无法满足帧速率要求的复杂图像分析时,您可以使用本主题的操作模式部分所述的策略将 CameraX 配置为丢帧。
应用可以通过实现 ImageAnalysis.Analyzer
接口并替换 analyze(ImageProxy image)
来创建分析器。在每个分析器中,应用都会收到一个 ImageProxy
,它是 Media.Image 的封装容器。可以使用 ImageProxy.getFormat()
来查询图像格式。该格式使用应用通过 ImageAnalysis.Builder
提供的以下值之一表示:
如果应用请求了 OUTPUT_IMAGE_FORMAT_RGBA_8888
,则为 ImageFormat.RGBA_8888
。
如果应用请求了 OUTPUT_IMAGE_FORMAT_YUV_420_888
,则为 ImageFormat.YUV_420_888
。
如需了解颜色空间配置以及可检索像素字节的位置,请参阅构建 ImageAnalysis 用例。
在分析器中,应用应执行以下操作:
尽快分析给定的帧,最好在给定的帧速率时间限制内进行分析(例如,如果帧速率为 30 fps,则用时应低于 32 毫秒)。如果应用无法足够快地分析帧,请考虑采用一种受支持的丢帧机制。
通过调用 ImageProxy.close()
将 ImageProxy
发布到 CameraX。请注意,您不应调用已封装 Media.Image 的 close 函数 (Media.Image.close()
)。
应用可以直接使用 ImageProxy 中的已封装 Media.Image
。请不要对已封装的图像调用 Media.Image.close()
,因为这会破坏 CameraX 中的图像分享机制;请改为使用 ImageProxy.close()
将底层 Media.Image
发布到 CameraX。
创建分析器后,使用 ImageAnalysis.setAnalyzer()
注册该分析器以开始分析。完成分析后,使用 ImageAnalysis.clearAnalyer()
移除已注册的分析器。
您只能配置一个活跃分析器用于分析图像。调用 ImageAnalysis.setAnalyzer()
会替换已注册的分析器(如果已存在该分析器)。应用可以在绑定用例之前或之后随时设置新的分析器。
注意:该步骤适用于所有 CameraX 用例。如需详细了解绑定和生命周期自定义,请参阅 CameraX API 模型。
强烈建议您使用 ProcessCameraProvider.bindToLifecycle()
函数将 ImageAnalysis
绑定到现有的 AndroidX 生命周期。请注意,bindToLifecycle()
函数会返回选定的 Camera
设备,该函数可用于微调曝光等高级设置。如需详细了解如何控制相机输出,请参阅此指南。
以下示例结合了上述步骤中的所有操作,将 CameraX ImageAnalysis
和 Preview
用例绑定到了 lifeCycle
所有者:
- ImageAnalysis imageAnalysis =
- new ImageAnalysis.Builder()
- // enable the following line if RGBA output is needed.
- //.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888)
- .setTargetResolution(new Size(1280, 720))
- .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
- .build();
-
- imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() {
- @Override
- public void analyze(@NonNull ImageProxy imageProxy) {
- int rotationDegrees = imageProxy.getImageInfo().getRotationDegrees();
- // insert your code here.
- ...
- // after done, release the ImageProxy object
- imageProxy.close();
- }
- });
-
- cameraProvider.bindToLifecycle((LifecycleOwner) this, cameraSelector, imageAnalysis, preview);
图片拍摄用例旨在拍摄高分辨率的优质照片,不仅提供简单的相机手动控制功能,还提供自动白平衡、自动曝光和自动对焦 (3A) 功能。调用方负责决定如何使用拍摄的照片,具体包括以下选项:
takePicture(Executor, OnImageCapturedCallback)
:此方法为拍摄的图片提供内存缓冲区。
takePicture(OutputFileOptions, Executor, OnImageSavedCallback)
:此方法将拍摄的图片保存到提供的文件位置。
运行 ImageCapture
的可自定义执行程序有两种类型:回调执行程序和 IO 执行程序。
回调执行程序是 takePicture
方法的参数。它用于执行用户提供的 OnImageCapturedCallback()
。
如果调用方选择将图片保存到文件位置,您可以指定执行程序以执行 IO。如需设置 IO 执行程序,请调用 ImageCapture.Builder.setIoExecutor(Executor)
。如果执行程序不存在,则默认 CameraX 为任务的内部 IO 执行程序。
提供了拍照所需的基本控制功能。照片是使用闪光灯选项和连续自动对焦拍摄的。
如需缩短照片拍摄的延迟时间,请将 ImageCapture.CaptureMode
设置为 CAPTURE_MODE_MINIMIZE_LATENCY
。如需优化照片质量,请将其设置为 CAPTURE_MODE_MAXIMIZE_QUALITY
。
以下代码示例展示了如何配置应用以拍摄照片:
- ImageCapture imageCapture =
- new ImageCapture.Builder()
- .setTargetRotation(view.getDisplay().getRotation())
- .build();
-
- cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, imageCapture, imageAnalysis, preview);
请注意,bindToLifecycle()
会返回一个 Camera
对象。如需详细了解如何控制相机输出(如变焦和曝光),请参阅此指南。
配置好相机后,以下代码会根据用户操作拍照:
- public void onClick() {
- ImageCapture.OutputFileOptions outputFileOptions =
- new ImageCapture.OutputFileOptions.Builder(new File(...)).build();
- imageCapture.takePicture(outputFileOptions, cameraExecutor,
- new ImageCapture.OnImageSavedCallback() {
- @Override
- public void onImageSaved(ImageCapture.OutputFileResults outputFileResults) {
- // insert your code here.
- }
- @Override
- public void onError(ImageCaptureException error) {
- // insert your code here.
- }
- }
- );
- }
图片拍摄方法完全支持 JPEG
格式。如需查看有关如何将 Media.Image
对象从 YUV_420_888
格式转换为 RGB Bitmap
对象的示例代码,请参阅 YuvToRgbConverter.kt
。
4)CameraX 视频捕获架构
捕获系统通常会录制视频流和音频流,对其进行压缩,对这两个流进行多路复用,然后将生成的流写入磁盘。
图 1. 视频和音频捕获系统概念图。
在 CameraX 中,用于视频捕获的解决方案是 VideoCapture
用例:
图 2. 展示 CameraX 如何处理 VideoCapture
用例的概念图。
如图 2 所示,CameraX 视频捕获包括几个高级架构组件:
SurfaceProvider
,表示视频来源。
AudioSource
,表示音频来源。
用于对视频/音频进行编码和压缩的两个编码器。
用于对两个流进行多路复用的媒体复用器。
用于写出结果的文件保存器。
VideoCapture API 会对复杂的捕获引擎进行抽象化处理,为应用提供更加简单且直观的 API。
VideoCapture
是一种 CameraX 用例,既可以单独使用,也可以与其他用例搭配使用。受支持的具体组合取决于相机硬件功能,不过 Preview
和 VideoCapture
这一用例组合适用于所有设备。
注意:VideoCapture
是在 CameraX 软件包内的 camera-video
库中实现的,在 1.1.0-alpha10
及更高版本中可用。
VideoCapture API 包含可与应用通信的以下对象:
VideoCapture
是顶级用例类。VideoCapture
通过 CameraSelector
和其他 CameraX 用例绑定到 LifecycleOwner
。如需详细了解这些概念和用法,请参阅 CameraX 架构。
Recorder
是与 VideoCapture
紧密耦合的 VideoOutput 实现。 Recorder
用于执行视频和音频捕获操作。应用通过 Recorder
创建录制对象。
PendingRecording
会配置录制对象,同时提供启用音频和设置事件监听器等选项。您必须使用 Recorder
来创建 PendingRecording
。PendingRecording
不会录制任何内容。
Recording
会执行实际录制操作。您必须使用 PendingRecording
来创建 Recording
。
图 3 展示了这些对象之间的关系:
图 3. 展示 VideoCapture 用例中发生的交互的示意图。
图例:
使用 QualitySelector
创建 Recorder
。
使用其中一个 OutputOptions
配置 Recorder
。
如果需要,使用 withAudioEnabled()
启用音频。
使用 VideoRecordEvent
监听器调用 start()
以开始录制。
针对 Recording
使用 pause()
/resume()
/stop()
来控制录制操作。
在事件监听器内响应 VideoRecordEvents
。
详细的 API 列表位于源代码内的 current-txt 中。
如需将 CameraX VideoCapture
用例集成到您的应用中,请执行以下操作:
绑定 VideoCapture
。
准备和配置录制。
开始和控制运行时录制。
后面的部分概述了您可以在每个步骤中执行哪些操作,以获取端到端录制会话。
如需绑定 VideoCapure
用例,请执行以下操作:
创建一个 Recorder
对象。
创建 VideoCapture
对象。
绑定到 Lifecycle
。
CameraX VideoCapture API 遵循构建器设计模式。应用使用 Recorder.Builder
来创建 Recorder
。您还可以通过 QualitySelector
对象为 Recorder
配置视频分辨率。
CameraX Recorder
支持以下预定义的视频分辨率 Qualities
:
Quality.UHD
,适用于 4K 超高清视频大小 (2160p)
Quality.FHD
,适用于全高清视频大小 (1080p)
Quality.HD
,适用于高清视频大小 (720p)
Quality.SD
,适用于标清视频大小 (480p)
请注意,获得应用授权后,CameraX 还可以选择其他分辨率。
每个选项对应的确切视频大小取决于相机和编码器的功能。如需了解详情,请参阅 CamcorderProfile
的文档。
应用可以通过创建 QualitySelector
来配置分辨率。您可以使用以下方法之一创建 QualitySelector
:
使用 fromOrderedList()
提供几个首选分辨率,并包含一个后备策略,以备在不支持任何首选分辨率时使用。
CameraX 可以根据所选相机的功能确定最佳后备匹配项。如需了解详情,请参阅 QualitySelector
的 FallbackStrategy specification
。例如,以下代码会请求支持的最高录制分辨率;如果所有请求分辨率都不受支持,则授权 CameraX 选择最接近 Quality.SD 分辨率的分辨率:
- val qualitySelector = QualitySelector.fromOrderedList(
- listOf(Quality.UHD, Quality.FHD, Quality.HD, Quality.SD),
- FallbackStrategy.lowerQualityOrHigherThan(Quality.SD))
首先查询相机功能,然后使用 QualitySelector::from()
从受支持的分辨率中进行选择:
- val cameraInfo = cameraProvider.availableCameraInfos.filter {
- Camera2CameraInfo
- .from(it)
- .getCameraCharacteristic(CameraCharacteristics.LENS\_FACING) == CameraMetadata.LENS_FACING_BACK
- }
-
- val supportedQualities = QualitySelector.getSupportedQualities(cameraInfo[0])
- val filteredQualities = arrayListOf (Quality.UHD, Quality.FHD, Quality.HD, Quality.SD)
- .filter { supportedQualities.contains(it) }
-
- // Use a simple ListView with the id of simple_quality_list_view
- viewBinding.simpleQualityListView.apply {
- adapter = ArrayAdapter(context,
- android.R.layout.simple_list_item_1,
- filteredQualities.map { it.qualityToString() })
-
- // Set up the user interaction to manually show or hide the system UI.
- setOnItemClickListener { _, _, position, _ ->
- // Inside View.OnClickListener,
- // convert Quality.* constant to QualitySelector
- val qualitySelector = QualitySelector.from(filteredQualities[position])
-
- // Create a new Recorder/VideoCapture for the new quality
- // and bind to lifecycle
- val recorder = Recorder.Builder()
- .setQualitySelector(qualitySelector).build()
-
- // ...
- }
- }
-
- // A helper function to translate Quality to a string
- fun Quality.qualityToString() : String {
- return when (this) {
- Quality.UHD -> "UHD"
- Quality.FHD -> "FHD"
- Quality.HD -> "HD"
- Quality.SD -> "SD"
- else -> throw IllegalArgumentException()
- }
- }
请注意,QualitySelector.getSupportedQualities()
返回的功能肯定适用于 VideoCapture
用例或 VideoCapture
和 Preview
用例的组合。与 ImageCapture
或 ImageAnalysis
用例绑定时,如果请求的相机不支持所需的组合,CameraX 仍可能会绑定失败。
具有 QualitySelector
后,应用即可创建 VideoCapture
对象并执行绑定。请注意,此绑定与和其他用例的绑定相同:
- val recorder = Recorder.Builder()
- .setExecutor(cameraExecutor).setQualitySelector(qualitySelector)
- .build()
- val videoCapture = VideoCapture.withOutput(recorder)
-
- try {
- // Bind use cases to camera
- cameraProvider.bindToLifecycle(
- this, CameraSelector.DEFAULT_BACK_CAMERA, preview, videoCapture)
- } catch(exc: Exception) {
- Log.e(TAG, "Use case binding failed", exc)
- }
请注意,bindToLifecycle()
会返回一个 Camera
对象。如需详细了解如何控制相机输出(如变焦和曝光),请参阅此指南
注意:目前无法配置最终的视频编解码器和容器格式。
Recorder
会选择最适合系统的格式。最常见的视频编解码器是 H.264 AVC,其容器格式为 MPEG-4。
应用可以通过 Recorder
创建录制对象来执行视频和音频捕获操作。应用通过执行以下操作来创建录制对象:
使用 prepareRecording()
配置 OutputOptions
。
(可选)启用录音功能。
使用 start()
注册 VideoRecordEvent
监听器,并开始捕获视频。
当您调用 start()
函数时,Recorder
会返回 Recording
对象。应用可以使用此 Recording
对象完成捕获或执行其他操作,例如暂停或恢复。
Recorder
一次支持一个 Recording
对象。对前面的 Recording
对象调用 Recording.stop()
或 Recording.close()
后,您便可以开始新的录制。
我们来更详细地看看这些步骤。首先,应用使用 Recorder.prepareRecording()
为 Recorder 配置 OutputOptions
。Recorder
支持以下类型的 OutputOptions
:
FileDescriptorOutputOptions
,用于捕获到 FileDescriptor
中。
FileOutputOptions
,用于捕获到 File
中。
MediaStoreOutputOptions
,用于捕获到 MediaStore
中。
无论使用哪种 OutputOptions
类型,您都能通过 setFileSizeLimit()
来设置文件大小上限。其他选项特定于单个输出类型,例如 ParcelFileDescriptor
特定于 FileDescriptorOutputOptions
。
prepareRecording()
会返回 PendingRecording
对象,该对象是一个中间对象,用于创建相应的 Recording
对象。PendingRecording
是一个瞬态类,在大多数情况下应不可见,并且很少被应用缓存。
应用可以进一步配置录制对象,例如:
使用 withAudioEnabled()
启用音频。
使用 start(Executor, Consumer<VideoRecordEvent>)
注册监听器,以接收视频录制事件。
要开始录制,请调用 PendingRecording.start()
。CameraX 会将 PendingRecording
转换为 Recording
,将录制请求加入队列,并将新创建的 Recording
对象返回给应用。一旦在相应相机设备上开始录制,CameraX 就会发送 VideoRecordEvent.EVENT_TYPE_START
事件。
以下示例展示了如何将视频和音频录制到 MediaStore
文件中:
- // Create MediaStoreOutputOptions for our recorder
- val name = "CameraX-recording-" +
- SimpleDateFormat(FILENAME_FORMAT, Locale.US)
- .format(System.currentTimeMillis()) + ".mp4"
- val contentValues = ContentValues().apply {
- put(MediaStore.Video.Media.DISPLAY_NAME, name)
- }
- val mediaStoreOutput = MediaStoreOutputOptions.Builder(this.contentResolver,
- MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
- .setContentValues(contentValues)
- .build()
-
- // 2. Configure Recorder and Start recording to the mediaStoreOutput.
- val recording = videoCapture.output
- .prepareRecording(context, mediaStoreOutput)
- .withAudioEnabled()
- .start(ContextCompat.getMainExecutor(this), captureListener)
您可以使用以下方法暂停、恢复和停止正在进行的 Recording
:
pause
,用于暂停当前的活跃录制。
resume()
,用于恢复已暂停的活跃录制。
stop()
,用于完成录制并清空所有关联的录制对象。
请注意,无论录制处于暂停状态还是活跃状态,您都可以调用 stop()
来终止 Recording
。
如果您已使用 PendingRecording.start()
注册了 EventListener
,Recording
会使用 VideoRecordEvent
进行通信。
VideoRecordEvent.EVENT_TYPE_STATUS
用于录制统计信息,例如当前文件的大小和录制的时间跨度。
VideoRecordEvent.EVENT_TYPE_FINALIZE
用于录制结果,会包含最终文件的 URI 以及任何相关错误等信息。
在您的应用收到表示录制会话成功的 EVENT_TYPE_FINALIZE
后,您就可以从 OutputOptions
中指定的位置访问捕获的视频。
从事高通平台Camera Hal开发的同学, 对Camx应该不陌生。CamX是高通目前最新的Camera框架,是Hal层实现的一套框架,高通旧的Camera框架是mm-camera框架。
所以对应CameraX,我一般会说成Google CameraX,方便有些同学搞混淆。
参考文档:
Android Jetpack介绍
https://developer.android.google.cn/jetpack?hl=zh-cn
CameraX架构
https://developer.android.google.cn/training/camerax/architecture?hl=zh_cn
相机使用示例代码
https://github.com/android/camera-samples/
《Android Camera开发入门》、《Camx初认识》已经上架,可以点击了解 -> 小驰成长圈 |期待见证彼此的成长
觉得不错,点个赞呗
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。