startPreview()调用细节分析二

本文详细分析了Android Camera在启动预览模式时的调用流程,从Camera类的startPreview()开始,经过BpCamera、BnCamera、CameraClient和CameraHardwareInterface等层次,最终到硬件层的startPreview()实现。文中揭示了各层之间的交互机制,特别是涉及到IPC通信的部分。
摘要由CSDN通过智能技术生成
由之前的章节可知,Camera.cpp中的mCamera对象实际上是BpCamera的实例,因此,Camera类的startPreview()函数会调用

BpCamera的startPreview()函数,如下:

class BpCamera: public BpInterface<ICamera>
{
public:
    BpCamera(const sp<IBinder>& impl)
        : BpInterface<ICamera>(impl)
    {
    }

    省略...
    // start preview mode, must call setPreviewTarget first
    status_t startPreview()
    {
        ALOGV("startPreview");
        Parcel data, reply;
        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
        remote()->transact(START_PREVIEW, data, &reply);
        return reply.readInt32();
    }

    省略...
};

其中remote()的值是上述interface_cast()函数注入的IBinder对象,它实际上是由MediaServer进程通过ipc传过来的

CameraService::Client对象(这点我们会在后续章节中论证),而CameraService::Client又是BnCamera的派生类,因此,remote()->transact()函数

实际上会调用到BnCamera的onTransact()函数中.


status_t BnCamera::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        省略...
        case START_PREVIEW: {
            ALOGV("START_PREVIEW");
            CHECK_INTERFACE(ICamera, data, reply);
            reply->writeInt32(startPreview());
            return NO_ERROR;
        } break;
        省略...
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }

}

CameraClient是CameraServcie::Client的派生类,CameraService::Client是BnCamera的实现类,即startPreview()函数在CameraClient中定义.

/ start preview mode
status_t CameraClient::startPreview() {
    LOG1("startPreview (pid %d)", getCallingPid());
    return startCameraMode(CAMERA_PREVIEW_MODE);
}


// start preview or recording
status_t CameraClient::startCameraMode(camera_mode mode) {
    LOG1("startCameraMode(%d)", mode);
    Mutex::Autolock lock(mLock);
    status_t result = checkPidAndHardware();
    if (result != NO_ERROR) return result;

    switch(mode) {
        case CAMERA_PREVIEW_MODE:
            if (mSurface == 0 && mPreviewWindow == 0) {
                LOG1("mSurface is not set yet.");
                // still able to start preview in this case.
            }
            return startPreviewMode();
        case CAMERA_RECORDING_MODE:
            if (mSurface == 0 && mPreviewWindow == 0) {
                ALOGE("mSurface or mPreviewWindow must be set before startRecordingMode.");
                return INVALID_OPERATION;
            }
            return startRecordingMode();
        default:
            return UNKNOWN_ERROR;
    }

}


status_t CameraClient::startPreviewMode() {
    LOG1("startPreviewMode");
    status_t result = NO_ERROR;

    // if preview has been enabled, nothing needs to be done
    if (mHardware->previewEnabled()) {
        return NO_ERROR;
    }

    if (mPreviewWindow != 0) {
        native_window_set_scaling_mode(mPreviewWindow.get(),
                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
        native_window_set_buffers_transform(mPreviewWindow.get(),
                mOrientation);
    }
    mHardware->setPreviewWindow(mPreviewWindow);
    result = mHardware->startPreview();

    return result;
}

mHardware是CameraHardwareInterface对象,因此下一步会调用CameraHardwareInterface的startPreview()函数:

/**
 * Start preview mode.
 */
status_t startPreview()
{
    ALOGV("%s(%s)", __FUNCTION__, mName.string());
    if (mDevice->ops->start_preview)
        return mDevice->ops->start_preview(mDevice);
    return INVALID_OPERATION;
}

mDevice是camera_device_t类型的指针

typedef struct camera_device {
    /**
     * camera_device.common.version must be in the range
     * HARDWARE_DEVICE_API_VERSION(0,0)-(1,FF). CAMERA_DEVICE_API_VERSION_1_0 is
     * recommended.
     */
    hw_device_t common;
    camera_device_ops_t *ops;
    void *priv;
} camera_device_t;

而mDevice->ops是camera_device_ops_t类型的指针

typedef struct camera_device_ops {
    省略...
    /**
     * Start preview mode.
     */
    int (*start_preview)(struct camera_device *);
    省略...
} camera_device_ops_t;

camera_device_t指针和camera_device_ops_t又是在哪初始化的呢?

这里我们以lge的mako平台为例进行分析,mako平台也是使用高通的芯片,先看看hal层的相关实现:

在QualcommCamera.cpp中,

camera_device_ops_t camera_ops = {
  省略...
  start_preview:              android::start_preview,
  stop_preview:               android::stop_preview,
  省略...
};

extern "C" int  camera_device_open(
  const struct hw_module_t* module, const char* id,
          struct hw_device_t** hw_device)
{
    省略...
    if(module && id && hw_device) {
        省略...

        if (!strcmp(module->name, camera_common.name)) {
            省略...
            if (camHal->hardware && camHal->hardware->isCameraReady()) {
                camHal->cameraId = cameraId;
                device = &camHal->hw_dev;
                device->common.close = close_camera_device;
                device->ops = &camera_ops;
                device->priv = (void *)camHal;
                rc =  0;
            } else {
               省略...
            }
        }
    }
    /* pass actual hw_device ptr to framework. This amkes that we actally be use memberof() macro */
    *hw_device = (hw_device_t*)&device->common;
    LOGE("%s:  end rc %d", __func__, rc);
    return rc;
}


static hw_module_methods_t camera_module_methods = {
    open: camera_device_open,
};

static hw_module_t camera_common  = {
  tag: HARDWARE_MODULE_TAG,
  version_major: 0,
  version_minor: 01,
  id: CAMERA_HARDWARE_MODULE_ID,
  name: "Qcamera",
  author:"Qcom",
  methods: &camera_module_methods,
  dso: NULL,
  //reserved[0]:  0,
};
camera_module_t HAL_MODULE_INFO_SYM = {
  common: camera_common,
  get_number_of_cameras: get_number_of_cameras,
  get_camera_info: get_camera_info,
};

从上诉代码可得知,camera_device_open()函数在hal层camera模块初始化的时候会被调用,CameraHardwareInterface中的

mDevice和mDevice->ops就是在这时候初始化的.

好,我们回到QualcommCamera.cpp中继续看start_preview()函数:

int start_preview(struct camera_device * device)
{
  ALOGV("Q%s: E", __func__);
  int rc = -1;
  QualcommCameraHardware * hardware = util_get_Hal_obj(device);
  if(hardware != NULL){
    rc = hardware->startPreview( );
  }
  ALOGV("Q%s: X", __func__);
  return rc;
}

status_t QualcommCameraHardware::startPreview()
{
  status_t result;
  ALOGV("startPreview E");
  Mutex::Autolock l(&mLock);
  if( mPreviewWindow == NULL) {
    /* startPreview has been called before setting the preview
     * window. Start the camera with initial buffers because the
     * CameraService expects the preview to be enabled while
     * setting a valid preview window */
    ALOGV(" %s : Starting preview with initial buffers ", __FUNCTION__);
    result = startInitialPreview();
  } else {
      /* startPreview has been issued after a valid preview window
       * is set. Get the preview buffers from gralloc and start
       * preview normally */
    ALOGV(" %s : Starting normal preview ", __FUNCTION__);
    result = getBuffersAndStartPreview();
  }
  ALOGV("startPreview X");
  return result;
}

status_t QualcommCameraHardware::getBuffersAndStartPreview() {
    省略...
    mFrameThreadWaitLock.lock();
    while (mFrameThreadRunning) {
        ALOGV("%s: waiting for old frame thread to complete.", __FUNCTION__);
        mFrameThreadWait.wait(mFrameThreadWaitLock);
        ALOGV("%s: old frame thread completed.",__FUNCTION__);
    }
    mFrameThreadWaitLock.unlock();

    省略...

    //Starting preview now as the preview buffers are allocated
 //   if(!mPreviewInitialized && !mCameraRunning) {   // TODO just for testing
        ALOGI("setPreviewWindow: Starting preview after buffer allocation");
        startPreviewInternal();
 //   }
    ALOGV(" %s : X ",__FUNCTION__);
    return NO_ERROR;
}

status_t QualcommCameraHardware::startPreviewInternal()
{
    省略...

    if (!mPreviewInitialized) {
        mLastQueuedFrame = NULL;
        mPreviewInitialized = initPreview();
        if (!mPreviewInitialized) {
            ALOGE("startPreview X initPreview failed.  Not starting preview.");
            mPreviewBusyQueue.deinit();
            return UNKNOWN_ERROR;
        }
    }

    省略...
}

bool QualcommCameraHardware::initPreview()
{
    省略...
    // See comments in deinitPreview() for why we have to wait for the frame
    // thread here, and why we can't use pthread_join().
    mFrameThreadWaitLock.lock();
    while (mFrameThreadRunning) {
        mFrameThreadWait.wait(mFrameThreadWaitLock);
    }
    mFrameThreadWaitLock.unlock();


    省略...

    if (ret) {
        if(mIs3DModeOn != true) {
            省略...
            
            mPreviewThreadWaitLock.lock();
            pthread_attr_t pattr;
            pthread_attr_init(&pattr);
            pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED);

            mPreviewThreadRunning = !pthread_create(&mPreviewThread,
                                      &pattr,
                                      preview_thread,
                                      (void*)NULL);
            ret = mPreviewThreadRunning;
            mPreviewThreadWaitLock.unlock();

            省略...
        }

        mFrameThreadWaitLock.lock();
        pthread_attr_t attr;
        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
        省略...

        mFrameThreadRunning = !pthread_create(&mFrameThread,
                                              &attr,
                                              frame_thread,
                                              &camframeParams);
        ret = mFrameThreadRunning;
        mFrameThreadWaitLock.unlock();
        LINK_wait_cam_frame_thread_ready();
    }
    mFirstFrame = true;

    ALOGV("initPreview X: %d", ret);
    return ret;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值