Android Camera Subsystem - startPreview

来源:互联网 发布:ember.js 中文教程 编辑:程序博客网 时间:2024/05/16 19:03

 

 

 

startPreview

 

1.     Camera::startPreview()

frameworks/base/core/java/android/hardware/Camera.java

public native final voidstartPreview();

 

2.     android_hardware_Camera_startPreview()

frameworks/base/core/jni/android_hardware_Camera.cpp

static voidandroid_hardware_Camera_startPreview(JNIEnv *env, jobject thiz)

{

ALOGV("startPreview");

 

//得到本地Camera对象

 

   sp<Camera> camera =get_native_camera(env, thiz, NULL);

   if (camera == 0) return;

 

//调用本地Camera::startPreview方法

 

   if (camera->startPreview() != NO_ERROR){

       jniThrowRuntimeException(env, "startPreview failed");

       return;

    }

}

 

3   Camera::startPreview()

frameworks/av/camera/Camera.cpp

// start preview mode

status_t Camera::startPreview()

{

   ALOGV("startPreview");

 

sp<ICamera> c = mCamera;  

 

// mCameraCameraBase成员变量,它指向的是一个BpCamera对象。

//Camera open的过程中, mCameracs->connect()返回中

//得到的是 BpCamera对象,因此c将为BpCamera对象。

 

   if (c == 0) return NO_INIT;

   return c->startPreview();

}

 

4   BpCamera::startPreview()

frameworks/av/camera/ICamera.cpp

class BpCamera: publicBpInterface<ICamera>

{

// start preview mode, must call setPreviewDisplay first

status_t startPreview()

{

       ALOGV("startPreview");

       Parcel data, reply;

       data.writeInterfaceToken(ICamera::getInterfaceDescriptor());

       remote()->transact(START_PREVIEW,data, &reply);

       return reply.readInt32();

}

};

 

camera open过程中, cs->connect()时从service回复reply中得到的一个binder对象(实际上是一个CameraClientCamera2Client对象),在interfaca_cast时,会从依据这个对象查询其对应的本地接口(BpBinder对象),在创建BpCamera对象时将这个BpBinder本地接口对象传入BpCamera的构造函数,最终这个BpBinder对象赋值给BpCameramRemote成员变量。而remote()函数就是返回mRemote成员变量。

 

因此remote()->transact()实际上调用的是BpBinder::transact()

 

5   BpBinder::transact()

Frameworks/native/libs/binder/BpBinder.cpp

status_t BpBinder::transact(

   uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

   // Once a binder has died, it will never come back to life.

   if (mAlive) {

       status_t status = IPCThreadState::self()->transact(

           mHandle, code, data, reply, flags);

       if (status == DEAD_OBJECT) mAlive = 0;

       return status;

    }

 

   return DEAD_OBJECT;

}

 

6.   IPCThreadState::transact()

Frameworks/native/libs/binder/IPCThreadState.cpp

status_t IPCThreadState::transact(int32_thandle,

                                  uint32_tcode, const Parcel& data,

                                  Parcel*reply, uint32_t flags)

{

   status_t err = data.errorCheck();

 

   flags |= TF_ACCEPT_FDS;

 

   IF_LOG_TRANSACTIONS() {

       TextOutput::Bundle _b(alog);

       alog << "BC_TRANSACTION thr " <<(void*)pthread_self() << " / hand "

           << handle << " / code " << TypeCode(code)<< ": "

           << indent << data << dedent << endl;

    }

   

   if (err == NO_ERROR) {

       LOG_ONEWAY(">>>> SEND from pid %d uid %d %s",getpid(), getuid(),

           (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONEWAY");

       err =writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);

    }

   

   if (err != NO_ERROR) {

       if (reply) reply->setError(err);

       return (mLastError = err);

    }

   

   if ((flags & TF_ONE_WAY) == 0) {

       #if 0

       if (code == 4) { // relayout

           ALOGI(">>>>>> CALLING transaction 4");

       } else {

           ALOGI(">>>>>> CALLING transaction %d",code);

       }

       #endif

       if (reply) {

           err = waitForResponse(reply);

       } else {

           Parcel fakeReply;

           err = waitForResponse(&fakeReply);

       }

       #if 0

       if (code == 4) { // relayout

           ALOGI("<<<<<< RETURNING transaction 4");

       } else {

           ALOGI("<<<<<< RETURNING transaction %d",code);

       }

       #endif

       

       IF_LOG_TRANSACTIONS() {

           TextOutput::Bundle _b(alog);

           alog << "BR_REPLY thr " << (void*)pthread_self()<< " / hand "

                << handle <<": ";

           if (reply) alog << indent << *reply << dedent <<endl;

           else alog <<"(none requested)" << endl;

       }

    }else {

       err = waitForResponse(NULL, NULL);

    }

   

   return err;

}

 

 

IPCThreadState::writeTransactionData()

IPCThreadState:: waitForResponse ()

 

 

7.   status_tIPCThreadState::executeCommand(int32_t cmd)

Frameworks/native/libs/binder/IPCThreadState.cpp

status_tIPCThreadState::executeCommand(int32_t cmd)

{

   BBinder* obj;

   RefBase::weakref_type* refs;

   status_t result = NO_ERROR;

   

   switch (cmd) {

   case BR_ERROR:

       result = mIn.readInt32();

       break;

……………………………………………………………..

   case BR_TRANSACTION:

       {

           binder_transaction_data tr;

           result = mIn.read(&tr, sizeof(tr));

           ALOG_ASSERT(result == NO_ERROR,

                "Not enough command datafor brTRANSACTION");

           if (result != NO_ERROR) break;

           

           Parcel buffer;

           buffer.ipcSetDataReference(

                reinterpret_cast<constuint8_t*>(tr.data.ptr.buffer),

                tr.data_size,

                reinterpret_cast<constsize_t*>(tr.data.ptr.offsets),

                tr.offsets_size/sizeof(size_t),freeBuffer, this);

           

           const pid_t origPid = mCallingPid;

           const uid_t origUid = mCallingUid;

           

           mCallingPid = tr.sender_pid;

           mCallingUid = tr.sender_euid;

           

           int curPrio = getpriority(PRIO_PROCESS, mMyThreadId);

           if (gDisableBackgroundScheduling) {

                if (curPrio >ANDROID_PRIORITY_NORMAL) {

                    // We have inherited areduced priority from the caller, but do not

                    // want to run in thatstate in this process.  The driver setour

                    // priority already (thoughnot our scheduling class), so bounce

                    // it back to the defaultbefore invoking the transaction.

                    setpriority(PRIO_PROCESS,mMyThreadId, ANDROID_PRIORITY_NORMAL);

                }

           } else {

                if (curPrio >=ANDROID_PRIORITY_BACKGROUND) {

                    // We want to use theinherited priority from the caller.

                    // Ensure this thread is inthe background scheduling class,

                    // since the driver won'tmodify scheduling classes for us.

                    // The scheduling group isreset to default by the caller

                    // once this method returnsafter the transaction is complete.

                   set_sched_policy(mMyThreadId, SP_BACKGROUND);

                }

           }

 

           //ALOGI(">>>> TRANSACT from pid %d uid %d\n",mCallingPid, mCallingUid);

           

           Parcel reply;

           IF_LOG_TRANSACTIONS() {

                TextOutput::Bundle _b(alog);

                alog <<"BR_TRANSACTION thr " << (void*)pthread_self()

                    << " / obj" << tr.target.ptr << " / code "

                    << TypeCode(tr.code)<< ": " << indent << buffer

                    << dedent <<endl

                    << "Data addr = "

                    <<reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer)

                    << ", offsetsaddr="

                    <<reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << endl;

           }

           if (tr.target.ptr) {

//这儿的b应该就是 Camera::open()调用过程中,在服务端生成的CameraClient

// Camera2Client对象

// class CameraClient : public CameraService::Client

// clas CameraService::Client : public BnCamera, publicBasicClient

// class BnCamera: public BnInterface<ICamera>

// class BnInterface : public INTERFACE, public BBinder

// class BBinder : public IBinder

 

               sp<BBinder>b((BBinder*)tr.cookie);

               const status_t error =b->transact(tr.code, buffer, &reply, tr.flags);

                if (error < NO_ERROR)reply.setError(error);

 

           } else {

                const status_t error =the_context_object->transact(tr.code, buffer, &reply, tr.flags);

                if (error < NO_ERROR)reply.setError(error);

           }

           

           //ALOGI("<<<< TRANSACT from pid %d restore pid %d uid%d\n",

           //     mCallingPid, origPid,origUid);

           

           if ((tr.flags & TF_ONE_WAY) == 0) {

                LOG_ONEWAY("Sending replyto %d!", mCallingPid);

                sendReply(reply, 0);

           } else {

                LOG_ONEWAY("NOT sendingreply to %d!", mCallingPid);

           }

           

           mCallingPid = origPid;

           mCallingUid = origUid;

 

           IF_LOG_TRANSACTIONS() {

                TextOutput::Bundle _b(alog);

                alog << "BC_REPLYthr " << (void*)pthread_self() << " / obj "

                    << tr.target.ptr<< ": " << indent << reply << dedent <<endl;

           }

           

       }

       break;

   …………………………………………………………….

}

 

 

 

8.    BBinder::transact()

Frameworks/native/libs/binder/binder.cpp

// class CameraClient : public CameraService::Client

// clas CameraService::Client : public BnCamera, publicBasicClient

// class BnCamera: public BnInterface<ICamera>

// class BnInterface : public INTERFACE, public BBinder

// class BBinder : public IBinder

 

由于CameraClient没有改写BBindertransact(),因此上述b->transact()

实际上就是调用BBindertransact() .

 

status_t BBinder::transact(

   uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

   data.setDataPosition(0);

 

   status_t err = NO_ERROR;

   switch (code) {

       case PING_TRANSACTION:

           reply->writeInt32(pingBinder());

           break;

       default:

           err = onTransact(code, data, reply,flags);

           break;

    }

 

   if (reply != NULL) {

       reply->setDataPosition(0);

    }

 

   return err;

}

 

 

 

9.   BnCamera::onTransact ()

Frameworks/av/camera/ICamera.cpp

status_t BnCamera::onTransact(

    uint32_tcode, const Parcel& data, Parcel* reply, uint32_t flags)

{

   switch(code) {

       case DISCONNECT: {

           ALOGV("DISCONNECT");

           CHECK_INTERFACE(ICamera, data, reply);

           disconnect();

           return NO_ERROR;

       } break;

       case SET_PREVIEW_TEXTURE: {

           ALOGV("SET_PREVIEW_TEXTURE");

           CHECK_INTERFACE(ICamera, data, reply);

           sp<IGraphicBufferProducer> st =

               interface_cast<IGraphicBufferProducer>(data.readStrongBinder());

           reply->writeInt32(setPreviewTexture(st));

           return NO_ERROR;

       } break;

       case SET_PREVIEW_CALLBACK_FLAG: {

           ALOGV("SET_PREVIEW_CALLBACK_TYPE");

           CHECK_INTERFACE(ICamera, data, reply);

           int callback_flag = data.readInt32();

           setPreviewCallbackFlag(callback_flag);

           return NO_ERROR;

       } break;

       case START_PREVIEW: {

           ALOGV("START_PREVIEW");

           CHECK_INTERFACE(ICamera, data, reply);

           reply->writeInt32(startPreview());

           return NO_ERROR;

       } break;

       case START_RECORDING: {

           ALOGV("START_RECORDING");

           CHECK_INTERFACE(ICamera, data, reply);

           reply->writeInt32(startRecording());

           return NO_ERROR;

       } break;

       case STOP_PREVIEW: {

           ALOGV("STOP_PREVIEW");

           CHECK_INTERFACE(ICamera, data, reply);

           stopPreview();

           return NO_ERROR;

       } break;

        case STOP_RECORDING: {

           ALOGV("STOP_RECORDING");

           CHECK_INTERFACE(ICamera, data, reply);

           stopRecording();

           return NO_ERROR;

       } break;

       case RELEASE_RECORDING_FRAME: {

           ALOGV("RELEASE_RECORDING_FRAME");

           CHECK_INTERFACE(ICamera, data, reply);

           sp<IMemory> mem =interface_cast<IMemory>(data.readStrongBinder());

           releaseRecordingFrame(mem);

           return NO_ERROR;

       } break;

       case STORE_META_DATA_IN_BUFFERS: {

           ALOGV("STORE_META_DATA_IN_BUFFERS");

           CHECK_INTERFACE(ICamera, data, reply);

           bool enabled = data.readInt32();

           reply->writeInt32(storeMetaDataInBuffers(enabled));

           return NO_ERROR;

       } break;

       case PREVIEW_ENABLED: {

           ALOGV("PREVIEW_ENABLED");

           CHECK_INTERFACE(ICamera, data, reply);

           reply->writeInt32(previewEnabled());

           return NO_ERROR;

       } break;

       case RECORDING_ENABLED: {

           ALOGV("RECORDING_ENABLED");

           CHECK_INTERFACE(ICamera, data, reply);

           reply->writeInt32(recordingEnabled());

           return NO_ERROR;

       } break;

       case AUTO_FOCUS: {

           ALOGV("AUTO_FOCUS");

           CHECK_INTERFACE(ICamera, data, reply);

           reply->writeInt32(autoFocus());

           return NO_ERROR;

       } break;

       case CANCEL_AUTO_FOCUS: {

           ALOGV("CANCEL_AUTO_FOCUS");

           CHECK_INTERFACE(ICamera, data, reply);

           reply->writeInt32(cancelAutoFocus());

           return NO_ERROR;

       } break;

       case TAKE_PICTURE: {

           ALOGV("TAKE_PICTURE");

           CHECK_INTERFACE(ICamera, data, reply);

           int msgType = data.readInt32();

           reply->writeInt32(takePicture(msgType));

           return NO_ERROR;

       } break;

       case SET_PARAMETERS: {

           ALOGV("SET_PARAMETERS");

           CHECK_INTERFACE(ICamera, data, reply);

           String8 params(data.readString8());

           reply->writeInt32(setParameters(params));

           return NO_ERROR;

        } break;

       case GET_PARAMETERS: {

           ALOGV("GET_PARAMETERS");

           CHECK_INTERFACE(ICamera, data, reply);

            reply->writeString8(getParameters());

           return NO_ERROR;

        } break;

       case SEND_COMMAND: {

           ALOGV("SEND_COMMAND");

           CHECK_INTERFACE(ICamera, data, reply);

           int command = data.readInt32();

           int arg1 = data.readInt32();

           int arg2 = data.readInt32();

           reply->writeInt32(sendCommand(command, arg1, arg2));

           return NO_ERROR;

        } break;

       case CONNECT: {

           CHECK_INTERFACE(ICamera, data, reply);

           sp<ICameraClient> cameraClient =interface_cast<ICameraClient>(data.readStrongBinder());

           reply->writeInt32(connect(cameraClient));

           return NO_ERROR;

       } break;

       case LOCK: {

           CHECK_INTERFACE(ICamera, data, reply);

           reply->writeInt32(lock());

           return NO_ERROR;

       } break;

       case UNLOCK: {

           CHECK_INTERFACE(ICamera, data, reply);

           reply->writeInt32(unlock());

            return NO_ERROR;

       } break;

       default:

           return BBinder::onTransact(code, data, reply, flags);

    }

}

 

10.   CameraClient::startPreview()

Frameworks/av/services/camera/libcameraservice/CameraClient.cpp

上述case语句中startPreview()实际上调用的是CameraClient::startPreview()

       case START_PREVIEW: {

           ALOGV("START_PREVIEW");

           CHECK_INTERFACE(ICamera, data, reply);

           reply->writeInt32(startPreview());

           return NO_ERROR;

       } break;

 

// start preview mode

status_t CameraClient::startPreview() {

   LOG1("startPreview (pid %d)", getCallingPid());

    returnstartCameraMode(CAMERA_PREVIEW_MODE);

}

 

// start preview or recording

status_tCameraClient::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 setyet.");

                // still able to start previewin this case.

           }

           return startPreviewMode();

       case CAMERA_RECORDING_MODE:

           if (mSurface == 0 && mPreviewWindow == 0) {

                ALOGE("mSurface ormPreviewWindow 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;

}

 

 

11.   CameraClient::startPreview()

Frameworks/av/services/camera/libcameraservice/CameraHardwareInterface.h

//调用设备驱动例程

   status_t startPreview()

    {

       ALOGV("%s(%s)", __FUNCTION__, mName.string());

       if (mDevice->ops->start_preview)

           returnmDevice->ops->start_preview(mDevice);

       return INVALID_OPERATION;

    }