Android Camera从上至下(四)------CameraService(服务启动和初始化)

简介

  本文主要介绍CameraService的初始化过程。希望能够在了解CameraService初始化的流程
,让读者更能清晰的了解CameraService在整个Camera框架中的作用。
  在阅读本文时,需要读者留意在初始化过程中,CameraService与CameraProvider进行交互的
相关操作。

1 启动流程

1.1 rc

service cameraserver /system/bin/cameraserver // 该部分定义了一个名为cameraserver的服务,他的可执行文件路径为system/bin/cameraserver
    class main	// 类别为main
    user cameraserver // 在执行此服务之前,请更改为“cameraserver ”
    group audio camera input drmrpc // 在执行此服务之前,请更改为“groupname”。除了(必需的)第一个之外的其他组名用于设置进程的补充组(通过setgroups())。
    ioprio rt 4 // 通过ioprioset系统调用,为该服务设置IO优先级类别和IO优先级
    task_profiles CameraServiceCapacity MaxPerformance // 设置任务配置文件。在安卓U之前,配置文件应用于服务的主线程。对于Android U及更高版本,配置文件将应用于整个服务过程。这是为了取代使用writepid选项将进程移动到cgroup中。
    rlimit rtprio 10 10 // 他的将给定的rlimit应用于服务。rlimit由子进程继承,因此这将有效地将给定的rlimit应用于此服务启动的进程树。它的解析类似于下面指定的setrlimit命令。

1.2 main_cameraserver.cpp

#include "CameraService.h"
#include <hidl/HidlTransportSupport.h>

using namespace android;

int main(int argc __unused, char** argv __unused)
{
  signal(SIGPIPE, SIG_IGN);

  // Set 5 threads for HIDL calls. Now cameraserver will serve HIDL calls in
  // addition to consuming them from the Camera HAL as well.
  hardware::configureRpcThreadpool(5, /*willjoin*/ false);

  sp<ProcessState> proc(ProcessState::self());
  sp<IServiceManager> sm = defaultServiceManager();
  ALOGI("ServiceManager: %p", sm.get());
  CameraService::instantiate();    //注释一,
  ALOGI("ServiceManager: %p done instantiate", sm.get());
  ProcessState::self()->startThreadPool();
  IPCThreadState::self()->joinThreadPool();
}

2 初始化流程

文件路径class name
\frameworks\native\libs\binder\include\binder\BinderService.htemplate class BinderService
\frameworks\native\libs\binder\include\binder\IBinder.hIBinder::DeathRecipient
\frameworks\av\services\camera\libcameraservice\common\CameraProviderManager.hCameraProviderManager::StatusListener
\frameworks\av\camera\aidl\android\hardware\ICameraService.aidl::android::hardware::BnCameraService
virtual
virtual
virtual
BnCameraService
CameraService
+void onFirstRef()
DeathRecipient
StatusListener
BindService<CameraService>
+static in32_t publish(bool, int)
+static void instantiate()

在上述的表和图中,CameraService继承了BnCameraService,DeathRecipient,StatusListener,BinderService四个类, 其中继承的第四个类是以CameraService类为模板的BinderService类。BinderService类中包含了静态方法instantiate。这里我们着重看一下BindService ::instantiate这个函数

2.1 BindService ::instantiate

该函数做了以下事件:

  • 将CameraService传入ServiceManager中进行统一管理(addService)
    :而在这个过程中,由于调用addService时存在CameraService的sp引用,因此会调用CameraService::onFirstRef
template<typename SERVICE>
class BinderService
{
public:
   static status_t publish(bool allowIsolated = false,
                           int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {
       sp<IServiceManager> sm(defaultServiceManager());
       return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated,
                             dumpFlags);//此处的ServiceName为“media.camera”
   }

   static void publishAndJoinThreadPool(
           bool allowIsolated = false,
           int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {
       publish(allowIsolated, dumpFlags);
       joinThreadPool();
   }

   static void instantiate() { publish(); }

   static status_t shutdown() { return NO_ERROR; }

private:
   static void joinThreadPool() {
       sp<ProcessState> ps(ProcessState::self());
       ps->startThreadPool();
       ps->giveThreadPoolName();
       IPCThreadState::self()->joinThreadPool();
   }
};

2.2 CameraService::onFirstRef()

void CameraService::onFirstRef()
{

    ALOGI("CameraService process starting");

    BnCameraService::onFirstRef();
...
//枚举CameraProvider
    res = enumerateProviders();
...
}

2.3 CameraService::enumerateProviders()

该函数主要完成了以下事件:

  • 枚举设备的过程中先获取mServiceLock, 防止其他资源访问
  • 创建CameraProviderManager对象并初始化
  • 初始化后会设置vendorTags(相机静态能力)
  • 创建CameraFlashlight对象
  • 通过初始化完成的CameraProvidermanager对象获取CameraID
  • 获取cameraid后释放mServiceLock。
  • 上报camera id到framework,然后通过配置的ro.odm.build.media_performance_class决定是否需要过滤相机参数信息(过滤时依需获取mServiceLock锁资源)。
status_t CameraService::enumerateProviders() {
    status_t res;

    std::vector<std::string> deviceIds;
    std::unordered_map<std::string, std::set<std::string>> unavailPhysicalIds;
    {
        Mutex::Autolock l(mServiceLock);//枚举设备的过程中先获取mServiceLock

        if (nullptr == mCameraProviderManager.get()) {
            mCameraProviderManager = new CameraProviderManager();
            res = mCameraProviderManager->initialize(this);// 创建CameraProviderManager对象并初始化
        ...


        // Setup vendor tags before we call get_camera_info the first time
        // because HAL might need to setup static vendor keys in get_camera_info
        // TODO: maybe put this into CameraProviderManager::initialize()?
        mCameraProviderManager->setUpVendorTags();//初始化后会设置vendorTags

        if (nullptr == mFlashlight.get()) {
        //创建CameraFlashlight对象
            mFlashlight = new CameraFlashlight(mCameraProviderManager, this);
        }

        res = mFlashlight->findFlashUnits();
        if (res != OK) {
            ALOGE("Failed to enumerate flash units: %s (%d)", strerror(-res), res);
        }
		//上报camera id到framework
        deviceIds = mCameraProviderManager->getCameraDeviceIds(&unavailPhysicalIds);
    }
    for (auto& cameraId : deviceIds) {
        if (getCameraState(cameraId) == nullptr) {
            onDeviceStatusChanged(cameraId, CameraDeviceStatus::PRESENT);
        }
        if (unavailPhysicalIds.count(cameraId) > 0) {
            for (const auto& physicalId : unavailPhysicalIds[cameraId]) {
                onDeviceStatusChanged(cameraId, physicalId, CameraDeviceStatus::NOT_PRESENT);
            }
        }
    }

    // Derive primary rear/front cameras, and filter their charactierstics.
    // This needs to be done after all cameras are enumerated and camera ids are sorted.
    if (SessionConfigurationUtils::IS_PERF_CLASS) {
        // Assume internal cameras are advertised from the same
        // provider. If multiple providers are registered at different time,
        // and each provider contains multiple internal color cameras, the current
        // logic may filter the characteristics of more than one front/rear color
        // cameras.
        Mutex::Autolock l(mServiceLock);
        filterSPerfClassCharacteristicsLocked();
    }
    return OK;
}

3 总结

    本文中主要介绍了CameraService的初始化流程,当然其中还有很多细节没有进行详细梳理。比较重要的内容
就是CameraProvider 服务的启动流程和初始化流程。这些内容会在之后的文章中进行逐一梳理。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
你可以使用AndroidCamera2 API来录制15秒的视频。以下是一个简单的示例代码,可以帮助你开始录制视频: 1. 在你的AndroidManifest.xml文件中添加以下权限: ```xml <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ``` 2. 在你的布局文件中添加一个SurfaceView元素用于预览视频: ```xml <SurfaceView android:id="@+id/surfaceView" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 3. 在你的Activity或Fragment中,获取SurfaceView并设置它的回调: ```java private SurfaceView surfaceView; private SurfaceHolder surfaceHolder; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); surfaceView = findViewById(R.id.surfaceView); surfaceHolder = surfaceView.getHolder(); surfaceHolder.addCallback(surfaceHolderCallback); } private SurfaceHolder.Callback surfaceHolderCallback = new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { // 初始化Camera initializeCamera(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // 当SurfaceView尺寸发生变化时,更新Camera参数 updateCameraParameters(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { // 释放Camera资源 releaseCamera(); } }; ``` 4. 初始化Camera并设置参数: ```java private CameraDevice camera; private CameraCaptureSession captureSession; private CaptureRequest.Builder previewRequestBuilder; private Size previewSize; private void initializeCamera() { CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); try { // 获取后置摄像头 String cameraId = cameraManager.getCameraIdList()[0]; CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId); StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); previewSize = map.getOutputSizes(SurfaceTexture.class)[0]; // 打开Camera if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { cameraManager.openCamera(cameraId, cameraStateCallback, null); } } catch (CameraAccessException e) { e.printStackTrace(); } } private CameraDevice.StateCallback cameraStateCallback = new CameraDevice.StateCallback() { @Override public void onOpened(CameraDevice camera) { MainActivity.this.camera = camera; // 开始预览 startPreview(); } @Override public void onDisconnected(CameraDevice camera) { camera.close(); MainActivity.this.camera = null; } @Override public void onError(CameraDevice camera, int error) { camera.close(); MainActivity.this.camera = null; } }; private void startPreview() { try { SurfaceTexture texture = surfaceHolder.getSurfaceTexture(); texture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight()); Surface surface = new Surface(texture); previewRequestBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); previewRequestBuilder.addTarget(surface); List<Surface> surfaces = new ArrayList<>(); surfaces.add(surface); camera.createCaptureSession(surfaces, captureSessionStateCallback, null); } catch (CameraAccessException e) { e.printStackTrace(); } } private CameraCaptureSession.StateCallback captureSessionStateCallback = new CameraCaptureSession.StateCallback() { @Override public void onConfigured(CameraCaptureSession session) { captureSession = session; try { previewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); CaptureRequest previewRequest = previewRequestBuilder.build(); captureSession.setRepeatingRequest(previewRequest, null, null); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onConfigureFailed(CameraCaptureSession session) { session.close(); captureSession = null; } }; private void updateCameraParameters() { if (camera == null) { return; } try { // 获取最佳预览尺寸 CameraCharacteristics characteristics = camera.getCameraCharacteristics(camera.getId()); StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); Size[] supportedSizes = map.getOutputSizes(SurfaceTexture.class); Size optimalSize = getOptimalPreviewSize(supportedSizes, surfaceView.getWidth(), surfaceView.getHeight()); // 更新预览尺寸 if (!previewSize.equals(optimalSize)) { previewSize = optimalSize; updatePreview(); } } catch (CameraAccessException e) { e.printStackTrace(); } } private void updatePreview() { if (camera == null) { return; } try { // 停止当前预览 captureSession.stopRepeating(); captureSession.abortCaptures(); // 更新预览大小 SurfaceTexture texture = surfaceHolder.getSurfaceTexture(); texture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight()); // 创建新的预览请求 Surface surface = new Surface(texture); previewRequestBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); previewRequestBuilder.addTarget(surface); List<Surface> surfaces = new ArrayList<>(); surfaces.add(surface); camera.createCaptureSession(surfaces, captureSessionStateCallback, null); } catch (CameraAccessException e) { e.printStackTrace(); } } private Size getOptimalPreviewSize(Size[] sizes, int width, int height) { final double ASPECT_TOLERANCE = 0.1; double targetRatio = (double) height / width; if (sizes == null) { return null; } Size optimalSize = null; double minDiff = Double.MAX_VALUE; int targetHeight = height; for (Size size : sizes) { double ratio = (double) size.getWidth() / size.getHeight(); if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) { continue; } if (Math.abs(size.getHeight() - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.getHeight() - targetHeight); } } if (optimalSize == null) { minDiff = Double.MAX_VALUE; for (Size size : sizes) { if (Math.abs(size.getHeight() - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.getHeight() - targetHeight); } } } return optimalSize; } ``` 5. 在你的Activity或Fragment中实现录制视频的逻辑: ```java private MediaRecorder mediaRecorder; private File outputFile; private void startRecording() { try { // 创建输出文件 outputFile = new File(getExternalFilesDir(null), "video.mp4"); // 创建MediaRecorder mediaRecorder = new MediaRecorder(); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); mediaRecorder.setVideoSize(previewSize.getWidth(), previewSize.getHeight()); mediaRecorder.setVideoFrameRate(30); mediaRecorder.setOutputFile(outputFile.getAbsolutePath()); // 配置MediaRecorder mediaRecorder.prepare(); mediaRecorder.start(); // 录制15秒后停止 new Handler().postDelayed(new Runnable() { @Override public void run() { stopRecording(); } }, 15000); } catch (IOException e) { e.printStackTrace(); } } private void stopRecording() { if (mediaRecorder != null) { mediaRecorder.stop(); mediaRecorder.release(); mediaRecorder = null; // 停止预览 if (camera != null) { captureSession.close(); captureSession = null; camera.close(); camera = null; } // 播放录制的视频 Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(outputFile.getAbsolutePath())); intent.setDataAndType(Uri.parse(outputFile.getAbsolutePath()), "video/*"); startActivity(intent); } } ``` 6. 最后,在你的Activity或Fragment中添加一个按钮来启动录制: ```java public void onRecordButtonClicked(View view) { startRecording(); } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值