使用zc301 USB摄像头,这个摄像头返回JPEG图形留,camera的preview需要进行jpeg解码(没做),但是可以直接take jpeg照片。
1、修改你的BoardConfig.mk
USE_CAMERA_STUB := false
将stub设置为false,在编译时不会编译android2.1/frameworks/base/camera/libcameraservice中的
CameraHardwareStub.cpp
CameraHardwareStub.h
FakeCamera.cpp
FakeCamera.h
几个文件
2、hardware下建立Camera HAL目录,android2.1/hardware/your board/libcamera
复制以上几个文件
CameraHardwareStub.cpp
CameraHardwareStub.h
FakeCamera.cpp
FakeCamera.h
可以将其重命名
S3C6410CameraHardware.cpp
UsbCamera.cpp
文件中的Fake和Stub同样可以替换
3、编写Android.mk文件
================================================================
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= S3C6410CameraHardware.cpp \
UsbCamera.cpp
LOCAL_C_INCLUDES := \
external/jpeg
LOCAL_SHARED_LIBRARIES:= libutils libbinder libui liblog
LOCAL_STATIC_LIBRARIES:= \
libjpeg
LOCAL_MODULE:= libcamera
include $(BUILD_SHARED_LIBRARY)
=================================================================
其中jpeg库是为了将来解码jpeg使用的,根据这个脚本可编译出libcamera.so
4、修改FakeCamera.cpp->UsbCamera.cpp
目前只实现了基本功能
该文件可以按照V4L2流程来写
网上也有现成的patch,使用mmap方式,可惜是1.6的,没编译过去,待研究
1)构造函数中进行初始化
UsbCamera::UsbCamera(int width, int height)
: mTmpRgb16Buffer(0)
{
fd = open (DEFAULT_DEVICE, O_RDWR /* required */ | O_NONBLOCK, 0);
LOGE("open /dev/video0 fd is %d",fd);
ioctl (fd, VIDIOC_QUERYCAP, &cap);
CLEAR (fmt);
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 640;
fmt.fmt.pix.height = 480;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
ioctl (fd, VIDIOC_S_FMT, &fmt);
length = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
}
2)获取一帧数据
void UsbCamera::getNextFrameAsYuv422(uint8_t *buffer)
{
LOGE("read to get a pic from camera!");
for (;;)
{
fd_set fds;
struct timeval tv;
int r;
FD_ZERO (&fds);
FD_SET (fd, &fds);
/* Timeout. */
tv.tv_sec = 3;
tv.tv_usec = 0;
r = select (fd + 1, &fds, NULL, NULL, &tv);
if (-1 == r) {
LOGE ("select"); }
if (0 == r) {
LOGE ("select timeout\n"); }
if (read (fd, buffer, length));
break;
}
}
3)析构函数
UsbCamera::~UsbCamera()
{
delete[] mTmpRgb16Buffer;
close (fd);
}
5、修改CameraHardwareStub.cpp->S3C6410CameraHardware.cpp
1)改成640x480吧
void CameraHardware::initDefaultParameters()
{
CameraParameters p;
p.setPreviewSize(640,480);
p.setPreviewFrameRate(1);
p.setPreviewFormat("yuv422sp");//("yuv422sp");
p.setPictureSize(640, 480);
p.setPictureFormat("jpeg");//("jpeg");
if (setParameters(p) != NO_ERROR) {
LOGE("Failed to set default parameters?!");
}
}
2)拍照部分要改,因为可以直接获取压缩的jpeg图片
int CameraHardware::pictureThread()
{
UsbCamera* usbCamera = mUsbCamera;
if (mMsgEnabled & CAMERA_MSG_SHUTTER)
mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {
//FIXME: use a canned YUV image!
// In the meantime just make another fake camera picture.
//int w, h;
//mParameters.getPictureSize(&w, &h);
//sp mem = new MemoryBase(mRawHeap, 0, w * 2 * h);
LOGE("CAMERA_MSG_RAW_IMAGE");
//UsbCamera cam(w, h);
//cam.getNextFrameAsYuv422((uint8_t *)mRawHeap->base());
//mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie);
}
if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
//sp heap = new MemoryHeapBase(20000);
//sp mem = new MemoryBase(heap, 0, 20000);
//memcpy(heap->base(), kCannedJpeg, 20000);
LOGE("CAMERA_MSG_COMPRESSED_IMAGE");
int w, h;
mParameters.getPictureSize(&w, &h);
sp mem = new MemoryBase(mRawHeap, 0, w * 2 * h);
//UsbCamera cam(w, h);
usbCamera->getNextFrameAsYuv422((uint8_t *)mRawHeap->base());
mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, mCallbackCookie);
}
return NO_ERROR;
}
3)status_t CameraHardware::setParameters(const CameraParameters& params)
有个地方只让take 320x240的pic,要注释掉
/* if (w != 320 && h != 240) {
LOGE("Still picture size must be size of canned JPEG (%dx%d)",
320, 240);
return -1;
}*/
至此Camera HAL已经可以拍照了。
存在问题:
1)需要做jpeg->YUV以实现preview功能,libjpeg没用过,暂时不做。
2)UsbCamera.cpp要改成V4L2标准流程,现在这种read模式太简单,效率低。