usb camera HAL :CameraHardware.cpp


/** Copyright (C) 2010 SpectraCore Technologies
** Author : Venkat Raju
** Email : codredruids@spectracoretech.com
** Initial Code : http://code.google.com/p/android-m912/downloads/detail?name=v4l2_camera_v2.patch

**
** Copyright (C) 2009 0xlab.org - http://0xlab.org/

**
** Copyright 2008, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0

**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

#define LOG_TAG "CameraHardwareStub"
#include <utils/Log.h>

#include "CameraHardware.h"
#include <utils/threads.h>
#include <fcntl.h>
#include <sys/mman.h>

#include "converter.h"

#define MIN_WIDTH 640
#define MIN_HEIGHT 480     // 预设的分辨率

namespace android {

CameraHardwareStub::CameraHardwareStub(int cameraId) //这个叫构造函数,与自己类同名的。
                  : mParameters(),
                    mPreviewHeap(0),  //这些叫成员变量初始化。
                    mRawHeap(0),
                    mFakeCamera(0),
                    mPreviewFrameSize(0),
                    mNotifyCb(0),
                    mDataCb(0),
                    mDataCbTimestamp(0),
                    mCallbackCookie(0),
                    mMsgEnabled(0),
                    mRecordRunning(false)
// mCurrentPreviewFrame(0)

{
    initDefaultParameters();
    if (cameraId == 0)  //支持2个摄像头
        strcpy(mVideoDevice, "/dev/video0");
    else
        strcpy(mVideoDevice, "/dev/video1");
}

void CameraHardwareStub::initDefaultParameters()
{
    CameraParameters p;

    p.setPreviewSize(MIN_WIDTH, MIN_HEIGHT);
    p.setPreviewFrameRate(30);    //帧率30,即一秒钟播放30帧,1/30秒播放一帧
    p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_RGB565);
//preview 图像格式RGB565. 即RRRRRGGGGGGBBBBB 18位宽.
    p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
          "1600x1200,1024x768,640x480,352x288,320x240");
    p.setPictureSize(MIN_WIDTH, MIN_HEIGHT);
    p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);
// picture 图像格式 jpeg。
    p.set(CameraParameters::KEY_JPEG_QUALITY, "100"); // max quality  //图像质量100.

    p.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT,
          CameraParameters::PIXEL_FORMAT_YUV420SP);  //视频录像格式 YUV420SP.

    if (setParameters(p) != NO_ERROR) {
        LOGE("Failed to set default parameters?!");
    }
}

void CameraHardwareStub::initHeapLocked()
{
    // Create raw heap.

    int picture_width, picture_height;
    mParameters.getPictureSize(&picture_width, &picture_height);
    mRawHeap = new MemoryHeapBase(picture_width * picture_height * 3 / 2);  //申请picture内存,用来存取capture时的picture的图像数据.不知道为什么要*3/2 ,可能跟图像压缩率有关?
    mRawBuffer = new MemoryBase(mRawHeap, 0, picture_width * picture_height * 3 / 2);

    int preview_width, preview_height;
    mParameters.getPreviewSize(&preview_width, &preview_height);
    LOGD("initHeapLocked: preview size=%dx%d", preview_width, preview_height);

    // Note that we enforce yuv420sp in setParameters().

    int how_big = preview_width * preview_height * 2;

    // If we are being reinitialized to the same size as before, no

    // work needs to be done.

    if (how_big == mPreviewFrameSize)
        return;

    mPreviewFrameSize = how_big;
    // mPreviewFrameSize = preview_width * preview_height * 3 / 2;


    // Make a new mmap'ed heap that can be shared across processes.

    // use code below to test with pmem

    mPreviewHeap = new MemoryHeapBase(mPreviewFrameSize);
//申请preview内存,用来存取preview的图像数据,不知道为什么大小要 分辨率*2?
    // Recreate the fake camera to reflect the current size.

    if(!mFakeCamera) {    //不知道这个是什么作用?感觉有点抽风。。
        delete mFakeCamera;
        LOGD("%s: new V4L2Camera", __func__);
        mFakeCamera = new V4L2Camera();
    }
}

CameraHardwareStub::~CameraHardwareStub()   //这个叫析构函数,函数退出时用来释放内存的,没办法,刚学C++,菜呀
{
    delete mFakeCamera;
    mFakeCamera = 0; // paranoia

}

sp<IMemoryHeap> CameraHardwareStub::getPreviewHeap() const
{
    return mPreviewHeap;   //preview 的buffer
}

sp<IMemoryHeap> CameraHardwareStub::getRawHeap() const
{
    return mRawHeap;      // 原始数据的buffer,即usb传过来的原始数据
}

void CameraHardwareStub::setCallbacks(notify_callback notify_cb,//发消息通知
                                      data_callback data_cb //发消息通知,顺便带个数据地址,告诉可以从那去取数据
                                      data_callback_timestamp //带时间戳的回调,比如录像,是需要计算时间。

data_cb_timestamp,
                                      void* user)  //设回调函数,我看应该是回头告诉cameraservice 有消息来了,该进行消息动作了。
{
    Mutex::Autolock lock(mLock); //这个锁是干啥的。。用来保护下面的临界区? 别人调用它,需要先拥有锁? 对锁不了解呀。。
    mNotifyCb = notify_cb;
    mDataCb = data_cb;
    mDataCbTimestamp = data_cb_timestamp;
    mCallbackCookie = user; // 这个不知道干啥的,用户?
}

void CameraHardwareStub::enableMsgType(int32_t msgType)
{
    Mutex::Autolock lock(mLock);
    mMsgEnabled |= msgType;
}

void CameraHardwareStub::disableMsgType(int32_t msgType)
{
    Mutex::Autolock lock(mLock);
    mMsgEnabled &= ~msgType;
}

bool CameraHardwareStub::msgTypeEnabled(int32_t msgType)
{
    Mutex::Autolock lock(mLock);
    return (mMsgEnabled & msgType);
}

// ---------------------------------------------------------------------------


int CameraHardwareStub::previewThread()
{
    mLock.lock();
        // the attributes below can change under our feet...


        int previewFrameRate = mParameters.getPreviewFrameRate();

        sp<MemoryHeapBase> heap = mPreviewHeap;  //转成heap

        // this assumes the internal state of fake camera doesn't change

        // (or is thread safe)

        V4L2Camera* fakeCamera = mFakeCamera;  //转成fakeCamera

        sp<MemoryBase> buffer = mRawBuffer;    //buffer

    mLock.unlock();

    // TODO: here check all the conditions that could go wrong

    if (buffer != 0) {
        // Calculate how long to wait between frames.

        int delay = (int)(1000000.0f / float(previewFrameRate)); //多久播放一帧,帧率的倒数。

        mPreviewLock.lock();

        char *rawFramePointer = fakeCamera->GrabRawFrame(); // 这里调用V4L2Camera.cpp的函数 调用ioctl(DQBUF),返回存放数据的指针。


        // Notify the client of a new frame.

        if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) {
            fakeCamera->convert((unsigned char *) rawFramePointer,
                                (unsigned char *) heap->getBase(),
                                MIN_WIDTH, MIN_HEIGHT);
// 关键地方,转换格式。原始数据存到previewHeap里去,rawFramePointer -> heap->getBase()
            yuyv422_to_yuv420sp((unsigned char *)rawFramePointer,
                                (unsigned char *)mRawHeap->getBase(),
                                MIN_WIDTH, MIN_HEIGHT);

//转换格式, 原始数据存到存取原始数据内存去 rawFramePointer -> mRawHeap->getBase 

            mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie);

//发通知 告诉cameraservice 可以preview了,同时发了地址buffer回去,不是地址就是内容~
        }

        if (mRecordRunning == true) { //录像开始
            LOGE(" ------- mRecordRunning --------");
            mDataCbTimestamp(systemTime(SYSTEM_TIME_MONOTONIC), CAMERA_MSG_VIDEO_FRAME, buffer, mCallbackCookie);

//发了个带时间戳的,回调函数,告诉cameraservice 可以录像了,同时送了buffer回去,不知道是地址还是数据。
        }

        fakeCamera->ProcessRawFrameDone();
//调用V4L2Camera 的ioctl (QBUF)
        // Wait for it...

        usleep(delay); // 播放的帧率
       mPreviewLock.unlock();
    }

    return NO_ERROR;
}

status_t CameraHardwareStub::startPreview() // 应用打开camera,会发消息到cameraservice,然后cameraservice会调用这里。
{
    Mutex::Autolock lock(mLock);
    if (mPreviewThread != 0) {
        // already running

        return INVALID_OPERATION;
    }

    if (!mFakeCamera->isAlreadyOpened()) {
        if (mFakeCamera->Open(mVideoDevice, MIN_WIDTH, MIN_HEIGHT, V4L2_PIX_FMT_YUYV) < 0) {   //打开设备video0,调用V4L2Camera.cpp
            LOGE("%s: cannot open device: %s", __func__, mVideoDevice);
            return UNKNOWN_ERROR;
        }

        if (mFakeCamera->Init()) { //
            LOGE("Camera Init failed: %s", strerror(errno));
            return UNKNOWN_ERROR;
        }

        if (mFakeCamera->StartStreaming()) {
            LOGE("Camera StartStreaming failed: %s", strerror(errno));
            return UNKNOWN_ERROR;
        }
    }

    mPreviewThread = new PreviewThread(this);
    return NO_ERROR;
}

void CameraHardwareStub::stopPreview()
{
    sp<PreviewThread> previewThread;

    { // scope for the lock

        Mutex::Autolock lock(mLock);
        previewThread = mPreviewThread;
    }

    // don't hold the lock while waiting for the thread to quit

    if (previewThread != 0) {
        previewThread->requestExitAndWait();
    }

    Mutex::Autolock lock(mLock);
    mPreviewThread.clear();

    {
        Mutex::Autolock lock(mPreviewLock);
        if (mFakeCamera->isAlreadyOpened()) {
            mFakeCamera->Uninit();
            mFakeCamera->StopStreaming();
            mFakeCamera->Close();
        }
    }
}

bool CameraHardwareStub::previewEnabled() {
    return mPreviewThread != 0;
}

status_t CameraHardwareStub::startRecording()
{
    mRecordRunning = true;
    return NO_ERROR;
}

void CameraHardwareStub::stopRecording()
{
    mRecordRunning = false;
}

bool CameraHardwareStub::recordingEnabled()
{
    return mRecordRunning;
}

void CameraHardwareStub::releaseRecordingFrame(const sp<IMemory>& mem)
{
}

// ---------------------------------------------------------------------------


int CameraHardwareStub::beginAutoFocusThread(void *cookie)
{
    CameraHardwareStub *c = (CameraHardwareStub *)cookie;
    return c->autoFocusThread();
}

int CameraHardwareStub::autoFocusThread()
{
    if (mMsgEnabled & CAMERA_MSG_FOCUS)
        mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
    return NO_ERROR;
}

status_t CameraHardwareStub::autoFocus()
{
    Mutex::Autolock lock(mLock);
    if (createThread(beginAutoFocusThread, this) == false)
        return UNKNOWN_ERROR;
    return NO_ERROR;
}

status_t CameraHardwareStub::cancelAutoFocus()
{
    return NO_ERROR;
}

/*static*/ int CameraHardwareStub::beginPictureThread(void *cookie)
{
    CameraHardwareStub *c = (CameraHardwareStub *)cookie;
    return c->pictureThread();
}

int CameraHardwareStub::pictureThread()
{
    if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
        LOGE("Take Picture COMPRESSED IMAGE");
        mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mFakeCamera->GrabJpegFrame(), mCallbackCookie);
    }
    return NO_ERROR;
}

status_t CameraHardwareStub::takePicture()
{
    sp<PreviewThread> previewThread;

    { // scope for the lock

        Mutex::Autolock lock(mLock);
        previewThread = mPreviewThread;
    }

    // don't hold the lock while waiting for the thread to quit

    if (previewThread != 0) {
        previewThread->requestExitAndWait();
    }

    {
        Mutex::Autolock lock(mLock);
        mPreviewThread.clear();
    }

    if (createThread(beginPictureThread, this) == false)
        return UNKNOWN_ERROR;
    return NO_ERROR;
}

status_t CameraHardwareStub::cancelPicture()
{
    return NO_ERROR;
}

status_t CameraHardwareStub::dump(int fd, const Vector<String16>& args) const
{
    return NO_ERROR;
}

status_t CameraHardwareStub::setParameters(const CameraParameters& params)
{
    Mutex::Autolock lock(mLock);
    // XXX verify params


    if (strcmp(params.getPreviewFormat(),
        CameraParameters::PIXEL_FORMAT_RGB565) != 0) {
        LOGE("Only yuv420sp preview is supported");
        return -1;
    }

    if (strcmp(params.getPictureFormat(),
        CameraParameters::PIXEL_FORMAT_JPEG) != 0) {
        LOGE("Only jpeg still pictures are supported");
        return -1;
    }

    mParameters = params;
    initHeapLocked();

    return NO_ERROR;
}

CameraParameters CameraHardwareStub::getParameters() const
{
    Mutex::Autolock lock(mLock);
    return mParameters;
}

status_t CameraHardwareStub::sendCommand(int32_t command, int32_t arg1,
                                         int32_t arg2)
{
    return BAD_VALUE;
}

void CameraHardwareStub::release()
{
}

sp<CameraHardwareInterface> CameraHardwareStub::createInstance(int cameraId)
{
    return new CameraHardwareStub(cameraId);
}

static CameraInfo sCameraInfo[] = {
    {
        CAMERA_FACING_BACK,
        0, /* orientation */
    },
    {
        CAMERA_FACING_FRONT,
        0,
    }
};

extern "C" int HAL_getNumberOfCameras()
{
    return sizeof(sCameraInfo) / sizeof(sCameraInfo[0]);
}

extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo)
{
    memcpy(cameraInfo, &sCameraInfo[cameraId], sizeof(CameraInfo));
}

extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId)
{
    return CameraHardwareStub::createInstance(cameraId);
}

}; // namespace android

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值