├── Android.mk ├── CameraHardware.cpp ├── CameraHardware.h ├── README.md └── v4l2 ├── V4L2Camera.cpp └── V4L2Camera.h /Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH:= $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | 5 | LOCAL_SRC_FILES:= \ 6 | CameraHardware.cpp \ 7 | v4l2/V4L2Camera.cpp 8 | 9 | LOCAL_MODULE:= libcamera 10 | 11 | LOCAL_SHARED_LIBRARIES:= \ 12 | libui \ 13 | libutils \ 14 | libcutils \ 15 | libmedia 16 | 17 | include $(BUILD_SHARED_LIBRARY) 18 | -------------------------------------------------------------------------------- /CameraHardware.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** 3 | ** Copyright 2008, The Android Open Source Project 4 | ** Copyright 2010, Moko365 Inc. 5 | ** 6 | ** Licensed under the Apache License, Version 2.0 (the "License"); 7 | ** you may not use this file except in compliance with the License. 8 | ** You may obtain a copy of the License at 9 | ** 10 | ** http://www.apache.org/licenses/LICENSE-2.0 11 | ** 12 | ** Unless required by applicable law or agreed to in writing, software 13 | ** distributed under the License is distributed on an "AS IS" BASIS, 14 | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | ** See the License for the specific language governing permissions and 16 | ** limitations under the License. 17 | */ 18 | 19 | #define LOG_TAG "CameraHardware" 20 | #include 21 | 22 | #include "CameraHardware.h" 23 | #include 24 | #include 25 | #include 26 | 27 | namespace android { 28 | 29 | CameraHardware::CameraHardware() 30 | : mParameters(), 31 | mPreviewHeap(0), 32 | mRawHeap(0), 33 | mCamera(0), 34 | mPreviewFrameSize(0), 35 | mRawPictureCallback(0), 36 | mJpegPictureCallback(0), 37 | mPictureCallbackCookie(0), 38 | mPreviewCallback(0), 39 | mPreviewCallbackCookie(0), 40 | mAutoFocusCallback(0), 41 | mAutoFocusCallbackCookie(0), 42 | mCurrentPreviewFrame(0) 43 | { 44 | initDefaultParameters(); 45 | } 46 | 47 | void CameraHardware::initDefaultParameters() 48 | { 49 | CameraParameters p; 50 | 51 | p.setPreviewSize(160, 120); 52 | p.setPreviewFrameRate(15); 53 | p.setPreviewFormat("rgb565"); 54 | 55 | p.setPictureSize(640, 480); 56 | p.setPictureFormat("rgb565"); 57 | 58 | if (setParameters(p) != NO_ERROR) { 59 | LOGE("Failed to set default parameters?!"); 60 | } 61 | } 62 | 63 | void CameraHardware::initHeapLocked() 64 | { 65 | // Create raw heap. Format is rgb565 (640x480) -- use vivi emulator 66 | int picture_width, picture_height; 67 | mParameters.getPictureSize(&picture_width, &picture_height); 68 | mRawHeap = new MemoryHeapBase(picture_width * 2 * picture_height); 69 | 70 | int preview_width, preview_height; 71 | mParameters.getPreviewSize(&preview_width, &preview_height); 72 | LOGD("initHeapLocked: preview size=%dx%d", preview_width, preview_height); 73 | 74 | // Note that we enforce yuv422 in setParameters(). 75 | int how_big = preview_width * preview_height * 2; 76 | 77 | // If we are being reinitialized to the same size as before, no 78 | // work needs to be done. 79 | if (how_big == mPreviewFrameSize) 80 | return; 81 | 82 | mPreviewFrameSize = how_big; 83 | 84 | // Make a new mmap'ed heap that can be shared across processes. 85 | // use code below to test with pmem 86 | mPreviewHeap = new MemoryHeapBase(mPreviewFrameSize * kBufferCount); 87 | // Make an IMemory for each frame so that we can reuse them in callbacks. 88 | for (int i = 0; i < kBufferCount; i++) { 89 | mBuffers[i] = new MemoryBase(mPreviewHeap, i * mPreviewFrameSize, mPreviewFrameSize); 90 | } 91 | } 92 | 93 | CameraHardware::~CameraHardware() 94 | { 95 | delete mCamera; 96 | mCamera = 0; 97 | singleton.clear(); 98 | } 99 | 100 | sp CameraHardware::getPreviewHeap() const 101 | { 102 | return mPreviewHeap; 103 | } 104 | 105 | sp CameraHardware::getRawHeap() const 106 | { 107 | return mRawHeap; 108 | } 109 | 110 | // --------------------------------------------------------------------------- 111 | 112 | int CameraHardware::previewThread() 113 | { 114 | mLock.lock(); 115 | // the attributes below can change under our feet... 116 | 117 | int previewFrameRate = mParameters.getPreviewFrameRate(); 118 | 119 | // Find the offset within the heap of the current buffer. 120 | ssize_t offset = mCurrentPreviewFrame * mPreviewFrameSize; 121 | 122 | sp heap = mPreviewHeap; 123 | 124 | sp buffer = mBuffers[mCurrentPreviewFrame]; 125 | 126 | mLock.unlock(); 127 | 128 | // TODO: here check all the conditions that could go wrong 129 | if (buffer != 0) { 130 | // This is always valid, even if the client died -- the memory 131 | // is still mapped in our process. 132 | void *base = heap->base(); 133 | 134 | // Fill the current frame with the fake camera. 135 | uint8_t *frame = ((uint8_t *)base) + offset; 136 | 137 | // V4L2: copy frame 138 | mCamera->GrabRawFrame(frame); 139 | 140 | //LOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame); 141 | // Notify the client of a new frame. 142 | mPreviewCallback(buffer, mPreviewCallbackCookie); 143 | 144 | // Advance the buffer pointer. 145 | mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount; 146 | } 147 | 148 | return NO_ERROR; 149 | } 150 | 151 | status_t CameraHardware::startPreview(preview_callback cb, void* user) 152 | { 153 | Mutex::Autolock lock(mLock); 154 | if (mPreviewThread != 0) { 155 | // already running 156 | return INVALID_OPERATION; 157 | } 158 | LOGD("startPreview: starting preview"); 159 | 160 | if (!mCamera) { 161 | delete mCamera; 162 | mCamera = new V4L2Camera(); 163 | } 164 | 165 | if (mCamera->Open("/dev/video0", 640, 480, V4L2_PIX_FMT_RGB565) < 0) { 166 | LOGE("startPreview: cannot open videodev"); 167 | return UNKNOWN_ERROR; 168 | } 169 | 170 | if (mCamera->Init() < 0) { 171 | LOGE("startPreview: init videodev failed, %s", strerror(errno)); 172 | return UNKNOWN_ERROR; 173 | } 174 | 175 | mCamera->StartStreaming(); 176 | 177 | mPreviewCallback = cb; 178 | mPreviewCallbackCookie = user; 179 | mPreviewThread = new PreviewThread(this); 180 | return NO_ERROR; 181 | } 182 | 183 | void CameraHardware::stopPreview() 184 | { 185 | sp previewThread; 186 | 187 | { // scope for the lock 188 | Mutex::Autolock lock(mLock); 189 | previewThread = mPreviewThread; 190 | } 191 | 192 | if (previewThread != 0) { 193 | mCamera->StopStreaming(); 194 | mCamera->Uninit(); 195 | mCamera->Close(); 196 | } 197 | 198 | // don't hold the lock while waiting for the thread to quit 199 | if (previewThread != 0) { 200 | previewThread->requestExitAndWait(); 201 | } 202 | 203 | Mutex::Autolock lock(mLock); 204 | mPreviewThread.clear(); 205 | } 206 | 207 | bool CameraHardware::previewEnabled() { 208 | return mPreviewThread != 0; 209 | } 210 | 211 | status_t CameraHardware::startRecording(recording_callback cb, void* user) 212 | { 213 | return UNKNOWN_ERROR; 214 | } 215 | 216 | void CameraHardware::stopRecording() 217 | { 218 | } 219 | 220 | bool CameraHardware::recordingEnabled() 221 | { 222 | return false; 223 | } 224 | 225 | void CameraHardware::releaseRecordingFrame(const sp& mem) 226 | { 227 | } 228 | 229 | // --------------------------------------------------------------------------- 230 | 231 | int CameraHardware::beginAutoFocusThread(void *cookie) 232 | { 233 | CameraHardware *c = (CameraHardware *)cookie; 234 | return c->autoFocusThread(); 235 | } 236 | 237 | int CameraHardware::autoFocusThread() 238 | { 239 | if (mAutoFocusCallback != NULL) { 240 | mAutoFocusCallback(true, mAutoFocusCallbackCookie); 241 | mAutoFocusCallback = NULL; 242 | return NO_ERROR; 243 | } 244 | return UNKNOWN_ERROR; 245 | } 246 | 247 | status_t CameraHardware::autoFocus(autofocus_callback af_cb, 248 | void *user) 249 | { 250 | Mutex::Autolock lock(mLock); 251 | 252 | if (mAutoFocusCallback != NULL) { 253 | return mAutoFocusCallback == af_cb ? NO_ERROR : INVALID_OPERATION; 254 | } 255 | 256 | mAutoFocusCallback = af_cb; 257 | mAutoFocusCallbackCookie = user; 258 | if (createThread(beginAutoFocusThread, this) == false) 259 | return UNKNOWN_ERROR; 260 | return NO_ERROR; 261 | } 262 | 263 | /*static*/ int CameraHardware::beginPictureThread(void *cookie) 264 | { 265 | CameraHardware *c = (CameraHardware *)cookie; 266 | return c->pictureThread(); 267 | } 268 | 269 | int CameraHardware::pictureThread() 270 | { 271 | mLock.lock(); 272 | sp mem = mBuffers[mCurrentPreviewFrame]; 273 | mLock.unlock(); 274 | 275 | if (mShutterCallback) 276 | mShutterCallback(mPictureCallbackCookie); 277 | 278 | if (mRawPictureCallback) { 279 | int w, h; 280 | mParameters.getPictureSize(&w, &h); 281 | //sp mem = new MemoryBase(mRawHeap, 0, w * 2 * h); 282 | 283 | if (mRawPictureCallback) 284 | mRawPictureCallback(mem, mPictureCallbackCookie); 285 | } 286 | 287 | if (mJpegPictureCallback) { 288 | } 289 | return NO_ERROR; 290 | } 291 | 292 | status_t CameraHardware::takePicture(shutter_callback shutter_cb, 293 | raw_callback raw_cb, 294 | jpeg_callback jpeg_cb, 295 | void* user) 296 | { 297 | stopPreview(); 298 | mShutterCallback = shutter_cb; 299 | mRawPictureCallback = raw_cb; 300 | mJpegPictureCallback = jpeg_cb; 301 | mPictureCallbackCookie = user; 302 | if (createThread(beginPictureThread, this) == false) 303 | return -1; 304 | return NO_ERROR; 305 | } 306 | 307 | status_t CameraHardware::cancelPicture(bool cancel_shutter, 308 | bool cancel_raw, 309 | bool cancel_jpeg) 310 | { 311 | if (cancel_shutter) mShutterCallback = NULL; 312 | if (cancel_raw) mRawPictureCallback = NULL; 313 | if (cancel_jpeg) mJpegPictureCallback = NULL; 314 | return NO_ERROR; 315 | } 316 | 317 | status_t CameraHardware::dump(int fd, const Vector& args) const 318 | { 319 | const size_t SIZE = 256; 320 | char buffer[SIZE]; 321 | String8 result; 322 | AutoMutex lock(&mLock); 323 | 324 | snprintf(buffer, 255, " preview frame(%d), size (%d), running(%s)\n", mCurrentPreviewFrame, mPreviewFrameSize, mPreviewRunning?"true": "false"); 325 | 326 | result.append(buffer); 327 | write(fd, result.string(), result.size()); 328 | 329 | return NO_ERROR; 330 | } 331 | 332 | status_t CameraHardware::setParameters(const CameraParameters& params) 333 | { 334 | Mutex::Autolock lock(mLock); 335 | 336 | if (strcmp(params.getPreviewFormat(), "rgb565") != 0) { 337 | LOGE("Only rgb565 preview is supported"); 338 | return -1; 339 | } 340 | 341 | if (strcmp(params.getPictureFormat(), "rgb565") != 0) { 342 | LOGE("Only rgb565 still pictures are supported"); 343 | return -1; 344 | } 345 | 346 | mParameters = params; 347 | 348 | initHeapLocked(); 349 | 350 | return NO_ERROR; 351 | } 352 | 353 | CameraParameters CameraHardware::getParameters() const 354 | { 355 | Mutex::Autolock lock(mLock); 356 | return mParameters; 357 | } 358 | 359 | void CameraHardware::release() 360 | { 361 | } 362 | 363 | wp CameraHardware::singleton; 364 | 365 | sp CameraHardware::createInstance() 366 | { 367 | if (singleton != 0) { 368 | sp hardware = singleton.promote(); 369 | if (hardware != 0) { 370 | return hardware; 371 | } 372 | } 373 | sp hardware(new CameraHardware()); 374 | singleton = hardware; 375 | return hardware; 376 | } 377 | 378 | extern "C" sp openCameraHardware() 379 | { 380 | return CameraHardware::createInstance(); 381 | } 382 | 383 | }; // namespace android 384 | -------------------------------------------------------------------------------- /CameraHardware.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** 3 | ** Copyright 2008, The Android Open Source Project 4 | ** Copyright 2010, Moko365 Inc. 5 | ** 6 | ** Licensed under the Apache License, Version 2.0 (the "License"); 7 | ** you may not use this file except in compliance with the License. 8 | ** You may obtain a copy of the License at 9 | ** 10 | ** http://www.apache.org/licenses/LICENSE-2.0 11 | ** 12 | ** Unless required by applicable law or agreed to in writing, software 13 | ** distributed under the License is distributed on an "AS IS" BASIS, 14 | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | ** See the License for the specific language governing permissions and 16 | ** limitations under the License. 17 | */ 18 | 19 | #ifndef ANDROID_HARDWARE_CAMERA_HARDWARE_H 20 | #define ANDROID_HARDWARE_CAMERA_HARDWARE_H 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "v4l2/V4L2Camera.h" 29 | 30 | namespace android { 31 | 32 | class CameraHardware : public CameraHardwareInterface { 33 | public: 34 | virtual sp getPreviewHeap() const; 35 | virtual sp getRawHeap() const; 36 | 37 | virtual status_t startPreview(preview_callback cb, void* user); 38 | virtual void stopPreview(); 39 | virtual bool previewEnabled(); 40 | 41 | virtual status_t startRecording(recording_callback cb, void* user); 42 | virtual void stopRecording(); 43 | virtual bool recordingEnabled(); 44 | virtual void releaseRecordingFrame(const sp& mem); 45 | 46 | virtual status_t autoFocus(autofocus_callback, void *user); 47 | virtual status_t takePicture(shutter_callback, 48 | raw_callback, 49 | jpeg_callback, 50 | void* user); 51 | virtual status_t cancelPicture(bool cancel_shutter, 52 | bool cancel_raw, 53 | bool cancel_jpeg); 54 | virtual status_t dump(int fd, const Vector& args) const; 55 | virtual status_t setParameters(const CameraParameters& params); 56 | virtual CameraParameters getParameters() const; 57 | virtual void release(); 58 | 59 | static sp createInstance(); 60 | 61 | private: 62 | CameraHardware(); 63 | virtual ~CameraHardware(); 64 | 65 | static wp singleton; 66 | 67 | static const int kBufferCount = 4; 68 | 69 | class PreviewThread : public Thread { 70 | CameraHardware* mHardware; 71 | public: 72 | PreviewThread(CameraHardware* hw) 73 | : Thread(false), mHardware(hw) { } 74 | virtual void onFirstRef() { 75 | run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY); 76 | } 77 | virtual bool threadLoop() { 78 | mHardware->previewThread(); 79 | // loop until we need to quit 80 | return true; 81 | } 82 | }; 83 | 84 | void initDefaultParameters(); 85 | void initHeapLocked(); 86 | 87 | int previewThread(); 88 | 89 | static int beginAutoFocusThread(void *cookie); 90 | int autoFocusThread(); 91 | 92 | static int beginPictureThread(void *cookie); 93 | int pictureThread(); 94 | 95 | mutable Mutex mLock; 96 | 97 | CameraParameters mParameters; 98 | 99 | sp mPreviewHeap; 100 | sp mRawHeap; 101 | sp mBuffers[kBufferCount]; 102 | 103 | bool mPreviewRunning; 104 | int mPreviewFrameSize; 105 | 106 | shutter_callback mShutterCallback; 107 | raw_callback mRawPictureCallback; 108 | jpeg_callback mJpegPictureCallback; 109 | void *mPictureCallbackCookie; 110 | 111 | // protected by mLock 112 | sp mPreviewThread; 113 | preview_callback mPreviewCallback; 114 | void *mPreviewCallbackCookie; 115 | 116 | autofocus_callback mAutoFocusCallback; 117 | void *mAutoFocusCallbackCookie; 118 | 119 | // only used from PreviewThread 120 | int mCurrentPreviewFrame; 121 | 122 | // use V4L2 123 | V4L2Camera *mCamera; 124 | }; 125 | 126 | }; // namespace android 127 | 128 | #endif 129 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | libv4l2-android 2 | =============== 3 | 4 | v4l2 library for android camera HAL 5 | 6 | ## Quickstart 7 | 8 | 1. Copy this project into product tree of Android source tree. 9 | 2. Use Android.mk to compile this project. 10 | 11 | ``` 12 | $ cd 13 | $ . build/envsetup.sh 14 | $ lunch 15 | $ cd /device//libv4l2-android 16 | $ mm 17 | ``` 18 | 19 | ## Reference 20 | 21 | * V4l2 API Spec, http://www.linuxtv.org/downloads/legacy/video4linux/API/V4L2_API/spec-single/v4l2.html 22 | -------------------------------------------------------------------------------- /v4l2/V4L2Camera.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** 3 | ** Copyright (C) 2010 Moko365 Inc 4 | ** Copyright 2008, The Android Open Source Project 5 | ** 6 | ** Licensed under the Apache License, Version 2.0 (the "License"); 7 | ** you may not use this file except in compliance with the License. 8 | ** You may obtain a copy of the License at 9 | ** 10 | ** http://www.apache.org/licenses/LICENSE-2.0 11 | ** 12 | ** Unless required by applicable law or agreed to in writing, software 13 | ** distributed under the License is distributed on an "AS IS" BASIS, 14 | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | ** See the License for the specific language governing permissions and 16 | ** limitations under the License. 17 | */ 18 | 19 | #define LOG_TAG "V4LCAMERA" 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | #include 35 | 36 | #include "V4L2Camera.h" 37 | 38 | namespace android { 39 | 40 | V4L2Camera::V4L2Camera() 41 | : start(0) 42 | { 43 | } 44 | 45 | V4L2Camera::~V4L2Camera() 46 | { 47 | } 48 | 49 | int V4L2Camera::Open(const char *filename, 50 | unsigned int w, 51 | unsigned int h, 52 | unsigned int p) 53 | { 54 | int ret; 55 | struct v4l2_format format; 56 | 57 | fd = open(filename, O_RDWR); 58 | if (fd < 0) { 59 | LOGE("Error opening device: %s", filename); 60 | return -1; 61 | } 62 | 63 | width = w; 64 | height = h; 65 | pixelformat = p; 66 | 67 | format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 68 | format.fmt.pix.width = width; 69 | format.fmt.pix.height = height; 70 | format.fmt.pix.pixelformat = pixelformat; 71 | 72 | // MUST set 73 | format.fmt.pix.field = V4L2_FIELD_ANY; 74 | 75 | ret = ioctl(fd, VIDIOC_S_FMT, &format); 76 | if (ret < 0) { 77 | LOGE("Unable to set format: %s", strerror(errno)); 78 | return -1; 79 | } 80 | 81 | return 0; 82 | } 83 | 84 | void V4L2Camera::Close() 85 | { 86 | close(fd); 87 | } 88 | 89 | int V4L2Camera::Init() 90 | { 91 | int ret; 92 | struct v4l2_requestbuffers rb; 93 | 94 | start = false; 95 | 96 | /* V4L2: request buffers, only 1 frame */ 97 | rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 98 | rb.memory = V4L2_MEMORY_MMAP; 99 | rb.count = 1; 100 | 101 | ret = ioctl(fd, VIDIOC_REQBUFS, &rb); 102 | if (ret < 0) { 103 | LOGE("Unable request buffers: %s", strerror(errno)); 104 | return -1; 105 | } 106 | 107 | /* V4L2: map buffer */ 108 | memset(&buf, 0, sizeof(struct v4l2_buffer)); 109 | 110 | buf.index = 0; 111 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 112 | buf.memory = V4L2_MEMORY_MMAP; 113 | 114 | ret = ioctl(fd, VIDIOC_QUERYBUF, &buf); 115 | if (ret < 0) { 116 | LOGE("Unable query buffer: %s", strerror(errno)); 117 | return -1; 118 | } 119 | 120 | /* Only map one */ 121 | mem = (unsigned char *)mmap(0, buf.length, PROT_READ | PROT_WRITE, 122 | MAP_SHARED, fd, buf.m.offset); 123 | if (mem == MAP_FAILED) { 124 | LOGE("Unable map buffer: %s", strerror(errno)); 125 | return -1; 126 | } 127 | 128 | /* V4L2: queue buffer */ 129 | ret = ioctl(fd, VIDIOC_QBUF, &buf); 130 | 131 | return 0; 132 | } 133 | 134 | void V4L2Camera::Uninit() 135 | { 136 | munmap(mem, buf.length); 137 | return ; 138 | } 139 | 140 | void V4L2Camera::StartStreaming() 141 | { 142 | enum v4l2_buf_type type; 143 | int ret; 144 | 145 | if (start) return; 146 | 147 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 148 | 149 | ret = ioctl(fd, VIDIOC_STREAMON, &type); 150 | if (ret < 0) { 151 | LOGE("Unable query buffer: %s", strerror(errno)); 152 | return; 153 | } 154 | 155 | start = true; 156 | } 157 | 158 | void V4L2Camera::StopStreaming() 159 | { 160 | enum v4l2_buf_type type; 161 | int ret; 162 | 163 | if (!start) return; 164 | 165 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 166 | 167 | ret = ioctl(fd, VIDIOC_STREAMOFF, &type); 168 | if (ret < 0) { 169 | LOGE("Unable query buffer: %s", strerror(errno)); 170 | return; 171 | } 172 | 173 | start = false; 174 | } 175 | 176 | void V4L2Camera::GrabRawFrame(void *raw_base) 177 | { 178 | int ret; 179 | 180 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 181 | buf.memory = V4L2_MEMORY_MMAP; 182 | 183 | /* V4L2: dequeue buffer */ 184 | ret = ioctl(fd, VIDIOC_DQBUF, &buf); 185 | if (ret < 0) { 186 | LOGE("Unable query buffer: %s", strerror(errno)); 187 | return; 188 | } 189 | 190 | /* copy to userspace */ 191 | memcpy((unsigned char *)raw_base, mem, buf.bytesused); 192 | 193 | /* V4l2: queue buffer again after that */ 194 | ret = ioctl(fd, VIDIOC_QBUF, &buf); 195 | if (ret < 0) { 196 | LOGE("Unable query buffer: %s", strerror(errno)); 197 | return; 198 | } 199 | } 200 | 201 | void V4L2Camera::Convert(void *r, void *p, unsigned int ppm) 202 | { 203 | unsigned char *raw = (unsigned char *)r; 204 | unsigned char *preview = (unsigned char *)p; 205 | 206 | /* We don't need to really convert that */ 207 | if (pixelformat == PIXEL_FORMAT_RGB_888) { 208 | /* copy to preview buffer */ 209 | memcpy(preview, raw, width*height*ppm); 210 | } 211 | 212 | /* TODO: Convert YUV to RGB. */ 213 | 214 | return; 215 | } 216 | 217 | 218 | }; // namespace 219 | -------------------------------------------------------------------------------- /v4l2/V4L2Camera.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** 3 | ** Copyright (C) 2010 Moko365 Inc. 4 | ** Copyright 2008, The Android Open Source Project 5 | ** 6 | ** Licensed under the Apache License, Version 2.0 (the "License"); 7 | ** you may not use this file except in compliance with the License. 8 | ** You may obtain a copy of the License at 9 | ** 10 | ** http://www.apache.org/licenses/LICENSE-2.0 11 | ** 12 | ** Unless required by applicable law or agreed to in writing, software 13 | ** distributed under the License is distributed on an "AS IS" BASIS, 14 | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | ** See the License for the specific language governing permissions and 16 | ** limitations under the License. 17 | */ 18 | 19 | #ifndef _CAMIF_H_ 20 | #define _CAMIF_H_ 21 | 22 | #include 23 | 24 | namespace android { 25 | 26 | class V4L2Camera { 27 | 28 | public: 29 | V4L2Camera(); 30 | ~V4L2Camera(); 31 | 32 | int Open(const char *device, 33 | unsigned int width, 34 | unsigned int height, 35 | unsigned int pixelformat); 36 | int Init(); 37 | void Uninit(); 38 | void Close(); 39 | 40 | void StartStreaming(); 41 | void StopStreaming(); 42 | 43 | void GrabRawFrame(void *raw_base); 44 | void Convert(void *raw_base, 45 | void *preview_base, 46 | unsigned int ppnum); 47 | 48 | private: 49 | int fd; 50 | int start; 51 | unsigned char *mem; 52 | struct v4l2_buffer buf; 53 | 54 | unsigned int width; 55 | unsigned int height; 56 | unsigned int pixelformat; 57 | }; 58 | 59 | }; // namespace 60 | 61 | #endif 62 | --------------------------------------------------------------------------------