/** 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);
}
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