libcamera:Initial commit

The library has been taken from android-x86 draft code
from
https://android-x86.googlegroups.com/attach/820408521e8c3e10/libcamera.tar.bz2?part=4

Signed-off-by: Vishal Bhoj <vishal.bhoj@linaro.org>
diff --git a/libcamera/Android.mk b/libcamera/Android.mk
new file mode 100644
index 0000000..e2a82b9
--- /dev/null
+++ b/libcamera/Android.mk
@@ -0,0 +1,28 @@
+ifneq ($(USE_CAMERA_STUB),true)
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES :=       \
+    CameraHardware.cpp   \
+    V4L2Camera.cpp       \
+    converter.cpp
+
+LOCAL_C_INCLUDES += external/jpeg
+
+LOCAL_MODULE := libcamera
+LOCAL_MODULE_TAGS := optional
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SHARED_LIBRARIES := \
+    libui                 \
+    libjpeg               \
+    libutils              \
+    libbinder             \
+    libcutils             \
+    libcamera_client
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/libcamera/CameraHardware.cpp b/libcamera/CameraHardware.cpp
new file mode 100644
index 0000000..bd7f079
--- /dev/null
+++ b/libcamera/CameraHardware.cpp
@@ -0,0 +1,432 @@
+/*
+**
+** Copyright 2009, The Android-x86 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.
+**
+** Author: Niels Keeman <nielskeeman@gmail.com>
+**
+*/
+
+#define LOG_TAG "CameraHardware"
+#include <utils/Log.h>
+
+#include "CameraHardware.h"
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#define VIDEO_DEVICE        "/dev/video0"
+#define MIN_WIDTH           640
+#define MIN_HEIGHT          480
+#define CAM_SIZE            "640x480"
+#define PIXEL_FORMAT        V4L2_PIX_FMT_YUYV
+
+namespace android {
+
+wp<CameraHardwareInterface> CameraHardware::singleton;
+
+CameraHardware::CameraHardware(int cameraId)
+                  : mCameraId(cameraId),
+                    mParameters(),
+                    mHeap(0),
+                    mPreviewHeap(0),
+                    mRecordHeap(0),
+                    mRawHeap(0),
+                    mPreviewFrameSize(0),
+                    mCurrentPreviewFrame(0),
+                    mRecordRunning(false),
+                    previewStopped(true),
+                    nQueued(0),
+                    nDequeued(0),
+                    mNotifyFn(NULL),
+                    mDataFn(NULL),
+                    mTimestampFn(NULL),
+                    mUser(NULL),
+                    mMsgEnabled(0)
+{
+    initDefaultParameters();
+}
+
+void CameraHardware::initDefaultParameters()
+{
+    CameraParameters p;
+
+    p.setPreviewSize(MIN_WIDTH, MIN_HEIGHT);
+    p.setPreviewFrameRate(15);
+    p.setPreviewFormat("yuv422sp");
+    p.set(p.KEY_SUPPORTED_PREVIEW_SIZES, CAM_SIZE);
+
+    p.setPictureSize(MIN_WIDTH, MIN_HEIGHT);
+    p.setPictureFormat("jpeg");
+    p.set(p.KEY_SUPPORTED_PICTURE_SIZES, CAM_SIZE);
+
+    if (setParameters(p) != NO_ERROR) {
+        LOGE("Failed to set default parameters?!");
+    }
+}
+
+CameraHardware::~CameraHardware()
+{
+    singleton.clear();
+}
+
+sp<IMemoryHeap> CameraHardware::getPreviewHeap() const
+{
+    return mHeap;
+}
+
+sp<IMemoryHeap> CameraHardware::getRawHeap() const
+{
+    return mRawHeap;
+}
+
+// ---------------------------------------------------------------------------
+
+void CameraHardware::setCallbacks(notify_callback notify_cb,
+                                  data_callback data_cb,
+                                  data_callback_timestamp data_cb_timestamp,
+                                  void *arg)
+{
+    Mutex::Autolock lock(mLock);
+    mNotifyFn = notify_cb;
+    mDataFn = data_cb;
+    mTimestampFn = data_cb_timestamp;
+    mUser = arg;
+}
+
+void CameraHardware::enableMsgType(int32_t msgType)
+{
+    Mutex::Autolock lock(mLock);
+    mMsgEnabled |= msgType;
+}
+
+void CameraHardware::disableMsgType(int32_t msgType)
+{
+    Mutex::Autolock lock(mLock);
+    mMsgEnabled &= ~msgType;
+}
+
+bool CameraHardware::msgTypeEnabled(int32_t msgType)
+{
+    Mutex::Autolock lock(mLock);
+    return (mMsgEnabled & msgType);
+}
+
+
+//-------------------------------------------------------------
+int CameraHardware::previewThread()
+{
+    if (!previewStopped) {
+        // Get preview frame
+        camera.GrabPreviewFrame(mHeap->getBase());
+        if ((mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) ||
+		(mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
+            if (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME) {
+			camera.GrabRecordFrame(mRecordHeap->getBase());
+			nsecs_t timeStamp = systemTime(SYSTEM_TIME_MONOTONIC);
+			mTimestampFn(timeStamp, CAMERA_MSG_VIDEO_FRAME,mRecordBuffer, mUser);
+            }
+            mDataFn(CAMERA_MSG_PREVIEW_FRAME,mBuffer, mUser);
+	}
+    }
+
+    return NO_ERROR;
+}
+
+status_t CameraHardware::startPreview()
+{
+    int ret;
+    int width, height;
+
+    Mutex::Autolock lock(mLock);
+    if (mPreviewThread != 0) {
+        //already running
+        return INVALID_OPERATION;
+    }
+
+        LOGI("startPreview: in startpreview \n");
+    camera.Open(VIDEO_DEVICE, MIN_WIDTH, MIN_HEIGHT, PIXEL_FORMAT);
+
+    mPreviewFrameSize = MIN_WIDTH * MIN_HEIGHT * 2;
+
+    mHeap = new MemoryHeapBase(mPreviewFrameSize);
+    mBuffer = new MemoryBase(mHeap, 0, mPreviewFrameSize);
+
+    ret = camera.Init();
+    if (ret != 0) {  
+        LOGI("startPreview: Camera.Init failed\n");
+        camera.Close();
+        return ret;
+    }
+
+    ret = camera.StartStreaming();
+    if (ret != 0) {  
+        LOGI("startPreview: Camera.StartStreaming failed\n");
+        camera.Uninit();
+        camera.Close();
+        return ret;
+    }
+
+    previewStopped = false;
+    mPreviewThread = new PreviewThread(this);
+
+    return NO_ERROR;
+}
+
+void CameraHardware::stopPreview()
+{
+    sp<PreviewThread> previewThread;
+
+    { // scope for the lock
+        Mutex::Autolock lock(mLock);
+        previewStopped = true;
+    }
+
+    if (mPreviewThread != 0) {
+        camera.Uninit();
+        camera.StopStreaming();
+        camera.Close();
+    }
+
+    {
+        Mutex::Autolock lock(mLock);
+        previewThread = mPreviewThread;
+    }
+
+    if (previewThread != 0) {
+        previewThread->requestExitAndWait();
+    }
+
+    Mutex::Autolock lock(mLock);
+    mPreviewThread.clear();
+}
+
+bool CameraHardware::previewEnabled()
+{
+    return mPreviewThread != 0;
+}
+
+status_t CameraHardware::startRecording()
+{
+    Mutex::Autolock lock(mLock);
+
+    mRecordHeap = new MemoryHeapBase(mPreviewFrameSize);
+    mRecordBuffer = new MemoryBase(mRecordHeap, 0, mPreviewFrameSize);
+    mRecordRunning = true;
+
+    return NO_ERROR;
+}
+
+void CameraHardware::stopRecording()
+{
+    mRecordRunning = false;
+}
+
+bool CameraHardware::recordingEnabled()
+{
+    return mRecordRunning;
+}
+
+void CameraHardware::releaseRecordingFrame(const sp<IMemory>& mem)
+{
+}
+
+// ---------------------------------------------------------------------------
+
+int CameraHardware::beginAutoFocusThread(void *cookie)
+{
+    CameraHardware *c = (CameraHardware *)cookie;
+    return c->autoFocusThread();
+}
+
+int CameraHardware::autoFocusThread()
+{
+    if (mMsgEnabled & CAMERA_MSG_FOCUS)
+        mNotifyFn(CAMERA_MSG_FOCUS, true, 0, mUser);
+    return NO_ERROR;
+}
+
+status_t CameraHardware::autoFocus()
+{
+    Mutex::Autolock lock(mLock);
+    if (createThread(beginAutoFocusThread, this) == false)
+        return UNKNOWN_ERROR;
+    return NO_ERROR;
+}
+
+status_t CameraHardware::cancelAutoFocus()
+{
+    return NO_ERROR;
+}
+
+/*static*/ int CameraHardware::beginPictureThread(void *cookie)
+{
+    CameraHardware *c = (CameraHardware *)cookie;
+    return c->pictureThread();
+}
+
+int CameraHardware::pictureThread()
+{
+    unsigned char *frame;
+    int bufferSize;
+    int w,h;
+    int ret;
+    struct v4l2_buffer buffer;
+    struct v4l2_format format;
+    struct v4l2_buffer cfilledbuffer;
+    struct v4l2_requestbuffers creqbuf;
+    struct v4l2_capability cap;
+
+
+   if (mMsgEnabled & CAMERA_MSG_SHUTTER)
+        mNotifyFn(CAMERA_MSG_SHUTTER, 0, 0, mUser);
+
+    mParameters.getPictureSize(&w, &h);
+    LOGD("Picture Size: Width = %d \t Height = %d", w, h);
+
+    int width, height;
+    mParameters.getPictureSize(&width, &height);
+    camera.Open(VIDEO_DEVICE, MIN_WIDTH, MIN_HEIGHT, PIXEL_FORMAT);
+    camera.Init();
+    camera.StartStreaming();
+
+    if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
+        LOGD ("mJpegPictureCallback");
+        mDataFn(CAMERA_MSG_COMPRESSED_IMAGE, camera.GrabJpegFrame(),mUser);
+    }
+
+    camera.Uninit();
+    camera.StopStreaming();
+    camera.Close();
+
+    return NO_ERROR;
+}
+
+status_t CameraHardware::takePicture()
+{
+        LOGD ("takepicture");
+    stopPreview();
+    //if (createThread(beginPictureThread, this) == false)
+    //    return -1;
+
+    pictureThread();
+
+    return NO_ERROR;
+}
+
+status_t CameraHardware::cancelPicture()
+{
+
+    return NO_ERROR;
+}
+
+status_t CameraHardware::dump(int fd, const Vector<String16>& args) const
+{
+    return NO_ERROR;
+}
+
+status_t CameraHardware::setParameters(const CameraParameters& params)
+{
+    Mutex::Autolock lock(mLock);
+
+    if (strcmp(params.getPreviewFormat(), "yuv422sp") != 0) {
+        LOGE("Only yuv422sp preview is supported");
+        return -1;
+    }
+
+    if (strcmp(params.getPictureFormat(), "jpeg") != 0) {
+        LOGE("Only jpeg still pictures are supported");
+        return -1;
+    }
+
+    int w, h;
+    int framerate;
+
+    params.getPreviewSize(&w, &h);
+    framerate = params.getPreviewFrameRate();
+    LOGD("PREVIEW SIZE: w=%d h=%d framerate=%d", w, h, framerate);
+
+    params.getPictureSize(&w, &h);
+
+    mParameters = params;
+
+    // Set to fixed sizes
+    mParameters.setPreviewSize(MIN_WIDTH,MIN_HEIGHT);
+
+    return NO_ERROR;
+}
+
+status_t CameraHardware::sendCommand(int32_t command, int32_t arg1, int32_t arg2)
+{
+    return BAD_VALUE;
+}
+
+CameraParameters CameraHardware::getParameters() const
+{
+    CameraParameters params;
+
+    Mutex::Autolock lock(mLock);
+    params = mParameters;
+
+    return params;
+}
+
+void CameraHardware::release()
+{
+    close(camera_device);
+}
+
+sp<CameraHardwareInterface> CameraHardware::createInstance(int cameraId)
+{
+    if (singleton != 0) {
+        sp<CameraHardwareInterface> hardware = singleton.promote();
+        if (hardware != 0) {
+            return hardware;
+        }
+    }
+    sp<CameraHardwareInterface> hardware(new CameraHardware(cameraId));
+    singleton = hardware;
+    return hardware;
+}
+
+static CameraInfo sCameraInfo[] = {
+	{
+		facing: CAMERA_FACING_BACK,
+		orientation: 0
+	},
+/*
+	{
+		facing: CAMERA_FACING_FRONT,
+		orientation: 0
+	}
+*/
+};
+
+extern "C" int HAL_getNumberOfCameras()
+{
+	return sizeof(sCameraInfo) / sizeof(sCameraInfo[0]);
+}
+
+extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo)
+{
+LOGD("HAL_getCameraInfo: %d", cameraId);
+	memcpy(cameraInfo, &sCameraInfo[cameraId], sizeof(CameraInfo));
+}
+
+extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId)
+{
+LOGD("HAL_openCameraHardware: %d", cameraId);
+	return CameraHardware::createInstance(cameraId);
+}
+
+}; // namespace android
diff --git a/libcamera/CameraHardware.h b/libcamera/CameraHardware.h
new file mode 100644
index 0000000..7491cce
--- /dev/null
+++ b/libcamera/CameraHardware.h
@@ -0,0 +1,156 @@
+/*
+**
+** Copyright 2009, The Android-x86 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.
+**
+** Author: Niels Keeman <nielskeeman@gmail.com>
+**
+*/
+
+#ifndef ANDROID_HARDWARE_CAMERA_HARDWARE_H
+#define ANDROID_HARDWARE_CAMERA_HARDWARE_H
+
+#include <utils/threads.h>
+#include <camera/CameraHardwareInterface.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <utils/threads.h>
+
+#include <sys/ioctl.h>
+#include "V4L2Camera.h"
+
+namespace android {
+
+class CameraHardware : public CameraHardwareInterface {
+public:
+    virtual sp<IMemoryHeap> getPreviewHeap() const;
+    virtual sp<IMemoryHeap> getRawHeap() const;
+
+    virtual status_t    startPreview();
+    virtual void        setCallbacks(notify_callback notify_cb,
+                                     data_callback data_cb,
+                                     data_callback_timestamp data_cb_timestamp,
+                                     void* arg);
+    /**
+     * Enable a message, or set of messages.
+     */
+    virtual void        enableMsgType(int32_t msgType);
+
+    /**
+     * Disable a message, or a set of messages.
+     */
+    virtual void        disableMsgType(int32_t msgType);
+
+    /**
+     * Query whether a message, or a set of messages, is enabled.
+     * Note that this is operates as an AND, if any of the messages
+     * queried are off, this will return false.
+     */
+    virtual bool        msgTypeEnabled(int32_t msgType);
+
+    virtual void        stopPreview();
+    virtual bool        previewEnabled();
+
+    virtual status_t    startRecording();
+    virtual void        stopRecording();
+    virtual bool        recordingEnabled();
+    virtual void        releaseRecordingFrame(const sp<IMemory>& mem);
+
+    virtual status_t    autoFocus();
+    virtual status_t    cancelAutoFocus();
+    virtual status_t    takePicture();
+    virtual status_t    cancelPicture();
+    virtual status_t    dump(int fd, const Vector<String16>& args) const;
+    virtual status_t    setParameters(const CameraParameters& params);
+    virtual CameraParameters  getParameters() const;
+    virtual void release();
+    virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
+
+    static sp<CameraHardwareInterface> createInstance(int cameraId);
+
+private:
+                        CameraHardware(int cameraId);
+    virtual             ~CameraHardware();
+
+    static wp<CameraHardwareInterface> singleton;
+
+    static const int kBufferCount = 4;
+
+    class PreviewThread : public Thread {
+        CameraHardware* mHardware;
+    public:
+        PreviewThread(CameraHardware* hw)
+            : Thread(false), mHardware(hw) { }
+        virtual void onFirstRef() {
+            run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY);
+        }
+        virtual bool threadLoop() {
+            mHardware->previewThread();
+            // loop until we need to quit
+            return true;
+        }
+    };
+
+    void initDefaultParameters();
+    bool initHeapLocked();
+
+    int previewThread();
+
+    static int beginAutoFocusThread(void *cookie);
+    int autoFocusThread();
+
+    static int beginPictureThread(void *cookie);
+    int pictureThread();
+
+    mutable Mutex           mLock;
+
+    int                     mCameraId;
+    CameraParameters        mParameters;
+
+    sp<MemoryHeapBase>      mHeap;
+    sp<MemoryBase>          mBuffer;
+
+    sp<MemoryHeapBase>      mPreviewHeap;
+    sp<MemoryHeapBase>      mRawHeap;
+    sp<MemoryHeapBase>      mRecordHeap;
+    sp<MemoryBase>          mRecordBuffer;
+
+    bool                    mPreviewRunning;
+    bool                    mRecordRunning;
+    int                     mPreviewFrameSize;
+
+    // protected by mLock
+    sp<PreviewThread>       mPreviewThread;
+
+    // only used from PreviewThread
+    int                     mCurrentPreviewFrame;
+
+    void *                  framebuffer;
+    bool                    previewStopped;
+    int                     camera_device;
+    void*                   mem[4];
+    int                     nQueued;
+    int                     nDequeued;
+    V4L2Camera              camera;
+    notify_callback         mNotifyFn;
+    data_callback           mDataFn;
+    data_callback_timestamp mTimestampFn;
+    void*                   mUser;
+    int32_t                 mMsgEnabled;
+
+};
+
+}; // namespace android
+
+#endif
diff --git a/libcamera/CameraService.h b/libcamera/CameraService.h
new file mode 100644
index 0000000..75e96c6
--- /dev/null
+++ b/libcamera/CameraService.h
@@ -0,0 +1,226 @@
+/*
+**
+** Copyright (C) 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.
+*/
+
+#ifndef ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
+#define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
+
+#include <camera/ICameraService.h>
+#include <camera/CameraHardwareInterface.h>
+#include <camera/Camera.h>
+
+namespace android {
+
+class MemoryHeapBase;
+class MediaPlayer;
+
+// ----------------------------------------------------------------------------
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+// When enabled, this feature allows you to send an event to the CameraService
+// so that you can cause all references to the heap object gWeakHeap, defined
+// below, to be printed. You will also need to set DEBUG_REFS=1 and
+// DEBUG_REFS_ENABLED_BY_DEFAULT=0 in libutils/RefBase.cpp. You just have to
+// set gWeakHeap to the appropriate heap you want to track.
+
+#define DEBUG_HEAP_LEAKS 0
+
+// ----------------------------------------------------------------------------
+
+class CameraService : public BnCameraService
+{
+    class Client;
+
+public:
+    static void instantiate();
+
+    // ICameraService interface
+    virtual sp<ICamera>     connect(const sp<ICameraClient>& cameraClient);
+
+    virtual status_t        dump(int fd, const Vector<String16>& args);
+
+            void            removeClient(const sp<ICameraClient>& cameraClient);
+
+    virtual status_t onTransact(
+        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
+
+private:
+
+// ----------------------------------------------------------------------------
+
+    class Client : public BnCamera {
+
+    public:
+        virtual void            disconnect();
+
+        // connect new client with existing camera remote
+        virtual status_t        connect(const sp<ICameraClient>& client);
+
+        // prevent other processes from using this ICamera interface
+        virtual status_t        lock();
+
+        // allow other processes to use this ICamera interface
+        virtual status_t        unlock();
+
+        // pass the buffered ISurface to the camera service
+        virtual status_t        setPreviewDisplay(const sp<ISurface>& surface);
+
+        // set the preview callback flag to affect how the received frames from
+        // preview are handled.
+        virtual void            setPreviewCallbackFlag(int callback_flag);
+
+        // start preview mode, must call setPreviewDisplay first
+        virtual status_t        startPreview();
+
+        // stop preview mode
+        virtual void            stopPreview();
+
+        // get preview state
+        virtual bool            previewEnabled();
+
+        // start recording mode
+        virtual status_t        startRecording();
+
+        // stop recording mode
+        virtual void            stopRecording();
+
+        // get recording state
+        virtual bool            recordingEnabled();
+
+        // release a recording frame
+        virtual void            releaseRecordingFrame(const sp<IMemory>& mem);
+
+        // auto focus
+        virtual status_t        autoFocus();
+
+        // cancel auto focus
+        virtual status_t        cancelAutoFocus();
+
+        // take a picture - returns an IMemory (ref-counted mmap)
+        virtual status_t        takePicture();
+
+        // set preview/capture parameters - key/value pairs
+        virtual status_t        setParameters(const String8& params);
+
+        // get preview/capture parameters - key/value pairs
+        virtual String8         getParameters() const;
+
+        // send command to camera driver
+        virtual status_t        sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
+
+        // our client...
+        const sp<ICameraClient>&    getCameraClient() const { return mCameraClient; }
+
+    private:
+        friend class CameraService;
+                                Client(const sp<CameraService>& cameraService,
+                                        const sp<ICameraClient>& cameraClient,
+                                        pid_t clientPid);
+                                Client();
+        virtual                 ~Client();
+
+                    status_t    checkPid();
+
+        static      void        notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user);
+        static      void        dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user);
+        static      void        dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
+                                                      const sp<IMemory>& dataPtr, void* user);
+
+        static      sp<Client>  getClientFromCookie(void* user);
+
+                    void        handlePreviewData(const sp<IMemory>&);
+                    void        handleShutter(image_rect_type *image);
+                    void        handlePostview(const sp<IMemory>&);
+                    void        handleRawPicture(const sp<IMemory>&);
+                    void        handleCompressedPicture(const sp<IMemory>&);
+
+                    void        copyFrameAndPostCopiedFrame(const sp<ICameraClient>& client,
+                                    const sp<IMemoryHeap>& heap, size_t offset, size_t size);
+
+        // camera operation mode
+        enum camera_mode {
+            CAMERA_PREVIEW_MODE   = 0,  // frame automatically released
+            CAMERA_RECORDING_MODE = 1,  // frame has to be explicitly released by releaseRecordingFrame()
+        };
+        status_t                startCameraMode(camera_mode mode);
+        status_t                startPreviewMode();
+        status_t                startRecordingMode();
+        status_t                setOverlay();
+        status_t                registerPreviewBuffers();
+
+        // Ensures atomicity among the public methods
+        mutable     Mutex                       mLock;
+
+        // mSurfaceLock synchronizes access to mSurface between
+        // setPreviewSurface() and postPreviewFrame().  Note that among
+        // the public methods, all accesses to mSurface are
+        // syncrhonized by mLock.  However, postPreviewFrame() is called
+        // by the CameraHardwareInterface callback, and needs to
+        // access mSurface.  It cannot hold mLock, however, because
+        // stopPreview() may be holding that lock while attempting
+        // to stop preview, and stopPreview itself will block waiting
+        // for a callback from CameraHardwareInterface.  If this
+        // happens, it will cause a deadlock.
+        mutable     Mutex                       mSurfaceLock;
+        mutable     Condition                   mReady;
+                    sp<CameraService>           mCameraService;
+                    sp<ISurface>                mSurface;
+                    int                         mPreviewCallbackFlag;
+                    int                         mOrientation;
+
+                    sp<MediaPlayer>             mMediaPlayerClick;
+                    sp<MediaPlayer>             mMediaPlayerBeep;
+
+                    // these are immutable once the object is created,
+                    // they don't need to be protected by a lock
+                    sp<ICameraClient>           mCameraClient;
+                    sp<CameraHardwareInterface> mHardware;
+                    pid_t                       mClientPid;
+                    bool                        mUseOverlay;
+
+                    sp<OverlayRef>              mOverlayRef;
+                    int                         mOverlayW;
+                    int                         mOverlayH;
+
+        mutable     Mutex                       mPreviewLock;
+                    sp<MemoryHeapBase>          mPreviewBuffer;
+    };
+
+// ----------------------------------------------------------------------------
+
+                            CameraService();
+    virtual                 ~CameraService();
+
+    // We use a count for number of clients (shoule only be 0 or 1).
+    volatile    int32_t                     mUsers;
+    virtual     void                        incUsers();
+    virtual     void                        decUsers();
+
+    mutable     Mutex                       mServiceLock;
+                wp<Client>                  mClient;
+
+#if DEBUG_HEAP_LEAKS
+                wp<IMemoryHeap>             gWeakHeap;
+#endif
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif
diff --git a/libcamera/V4L2Camera.cpp b/libcamera/V4L2Camera.cpp
new file mode 100644
index 0000000..6c0ed4b
--- /dev/null
+++ b/libcamera/V4L2Camera.cpp
@@ -0,0 +1,505 @@
+/*
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      Author: Niels Keeman <nielskeeman@gmail.com>
+ *
+ */
+
+#define LOG_TAG "V4L2Camera"
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <fcntl.h>
+
+#include "converter.h"
+#include "V4L2Camera.h"
+
+extern "C" { /* Android jpeglib.h missed extern "C" */
+#include <jpeglib.h>
+}
+
+namespace android {
+
+V4L2Camera::V4L2Camera ()
+    : nQueued(0), nDequeued(0)
+{
+    videoIn = (struct vdIn *) calloc (1, sizeof (struct vdIn));
+}
+
+V4L2Camera::~V4L2Camera()
+{
+    free(videoIn);
+}
+
+int V4L2Camera::Open (const char *device, int width, int height, int pixelformat)
+{
+    int ret;
+
+    if ((fd = open(device, O_RDWR)) == -1) {
+        LOGE("ERROR opening V4L interface: %s", strerror(errno));
+    return -1;
+    }
+
+    ret = ioctl (fd, VIDIOC_QUERYCAP, &videoIn->cap);
+    if (ret < 0) {
+        LOGE("Error opening device: unable to query device.");
+        return -1;
+    }
+
+    if ((videoIn->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
+        LOGE("Error opening device: video capture not supported.");
+        return -1;
+    }
+
+    if (!(videoIn->cap.capabilities & V4L2_CAP_STREAMING)) {
+        LOGE("Capture device does not support streaming i/o");
+        return -1;
+    }
+
+    videoIn->width = width;
+    videoIn->height = height;
+    videoIn->framesizeIn = (width * height << 1);
+    videoIn->formatIn = pixelformat;
+
+    videoIn->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    videoIn->format.fmt.pix.width = width;
+    videoIn->format.fmt.pix.height = height;
+    videoIn->format.fmt.pix.pixelformat = pixelformat;
+
+    ret = ioctl(fd, VIDIOC_S_FMT, &videoIn->format);
+    if (ret < 0) {
+        LOGE("Open: VIDIOC_S_FMT Failed: %s", strerror(errno));
+        return ret;
+    }
+
+    return 0;
+}
+
+void V4L2Camera::Close ()
+{
+    close(fd);
+}
+
+int V4L2Camera::Init()
+{
+    int ret;
+
+    /* Check if camera can handle NB_BUFFER buffers */
+    videoIn->rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    videoIn->rb.memory = V4L2_MEMORY_MMAP;
+    videoIn->rb.count = NB_BUFFER;
+
+    ret = ioctl(fd, VIDIOC_REQBUFS, &videoIn->rb);
+    if (ret < 0) {
+        LOGE("Init: VIDIOC_REQBUFS failed: %s", strerror(errno));
+        return ret;
+    }
+
+    for (int i = 0; i < NB_BUFFER; i++) {
+
+        memset (&videoIn->buf, 0, sizeof (struct v4l2_buffer));
+
+        videoIn->buf.index = i;
+        videoIn->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        videoIn->buf.memory = V4L2_MEMORY_MMAP;
+
+        ret = ioctl (fd, VIDIOC_QUERYBUF, &videoIn->buf);
+        if (ret < 0) {
+            LOGE("Init: Unable to query buffer (%s)", strerror(errno));
+            return ret;
+        }
+
+        videoIn->mem[i] = mmap (0,
+               videoIn->buf.length,
+               PROT_READ | PROT_WRITE,
+               MAP_SHARED,
+               fd,
+               videoIn->buf.m.offset);
+
+        if (videoIn->mem[i] == MAP_FAILED) {
+            LOGE("Init: Unable to map buffer (%s)", strerror(errno));
+            return -1;
+        }
+
+        ret = ioctl(fd, VIDIOC_QBUF, &videoIn->buf);
+        if (ret < 0) {
+            LOGE("Init: VIDIOC_QBUF Failed");
+            return -1;
+        }
+
+        nQueued++;
+    }
+
+    return 0;
+}
+
+void V4L2Camera::Uninit ()
+{
+    int ret;
+
+    videoIn->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    videoIn->buf.memory = V4L2_MEMORY_MMAP;
+
+    /* Dequeue everything */
+    int DQcount = nQueued - nDequeued;
+
+    for (int i = 0; i < DQcount-1; i++) {
+        ret = ioctl(fd, VIDIOC_DQBUF, &videoIn->buf);
+        if (ret < 0)
+            LOGE("Uninit: VIDIOC_DQBUF Failed");
+    }
+    nQueued = 0;
+    nDequeued = 0;
+
+    /* Unmap buffers */
+    for (int i = 0; i < NB_BUFFER; i++)
+        if (munmap(videoIn->mem[i], videoIn->buf.length) < 0)
+            LOGE("Uninit: Unmap failed");
+}
+
+int V4L2Camera::StartStreaming ()
+{
+    enum v4l2_buf_type type;
+    int ret;
+
+    if (!videoIn->isStreaming) {
+        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+        ret = ioctl (fd, VIDIOC_STREAMON, &type);
+        if (ret < 0) {
+            LOGE("StartStreaming: Unable to start capture: %s", strerror(errno));
+            return ret;
+        }
+
+        videoIn->isStreaming = true;
+    }
+
+    return 0;
+}
+
+int V4L2Camera::StopStreaming ()
+{
+    enum v4l2_buf_type type;
+    int ret;
+
+    if (videoIn->isStreaming) {
+        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+        ret = ioctl (fd, VIDIOC_STREAMOFF, &type);
+        if (ret < 0) {
+            LOGE("StopStreaming: Unable to stop capture: %s", strerror(errno));
+            return ret;
+        }
+
+        videoIn->isStreaming = false;
+    }
+
+    return 0;
+}
+
+void V4L2Camera::GrabPreviewFrame (void *previewBuffer)
+{
+    unsigned char *tmpBuffer;
+    int ret;
+
+    tmpBuffer = (unsigned char *) calloc (1, videoIn->width * videoIn->height * 2);
+
+    videoIn->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    videoIn->buf.memory = V4L2_MEMORY_MMAP;
+
+    /* DQ */
+    ret = ioctl(fd, VIDIOC_DQBUF, &videoIn->buf);
+    if (ret < 0) {
+        //LOGE("GrabPreviewFrame: VIDIOC_DQBUF Failed");
+
+        return;
+    }
+    nDequeued++;
+
+    //memcpy (tmpBuffer, videoIn->mem[videoIn->buf.index], (size_t) videoIn->buf.bytesused);
+    memcpy (tmpBuffer, videoIn->mem[videoIn->buf.index], (size_t) videoIn->buf.bytesused);
+    //convertYUYVtoYUV422SP((uint8_t *)tmpBuffer, (uint8_t *)previewBuffer, videoIn->width, videoIn->height);
+    convert((unsigned char *)tmpBuffer, (unsigned char *)previewBuffer, videoIn->width, videoIn->height);
+
+    ret = ioctl(fd, VIDIOC_QBUF, &videoIn->buf);
+    if (ret < 0) {
+        LOGE("GrabPreviewFrame: VIDIOC_QBUF Failed");
+        return;
+    }
+
+    nQueued++;
+
+    free(tmpBuffer);
+}
+
+void V4L2Camera::GrabRecordFrame (void *recordBuffer)
+{
+    unsigned char *tmpBuffer;
+    int ret;
+
+    tmpBuffer = (unsigned char *) calloc (1, videoIn->width * videoIn->height * 2);
+
+    videoIn->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    videoIn->buf.memory = V4L2_MEMORY_MMAP;
+
+    /* DQ */
+    ret = ioctl(fd, VIDIOC_DQBUF, &videoIn->buf);
+    if (ret < 0) {
+        LOGE("GrabRecordFrame: VIDIOC_DQBUF Failed");
+
+        return;
+    }
+    nDequeued++;
+
+    memcpy (tmpBuffer, videoIn->mem[videoIn->buf.index], (size_t) videoIn->buf.bytesused);
+
+    yuyv422_to_yuv420((unsigned char *)tmpBuffer, (unsigned char *)recordBuffer, videoIn->width, videoIn->height);
+
+    ret = ioctl(fd, VIDIOC_QBUF, &videoIn->buf);
+    if (ret < 0) {
+        LOGE("GrabRecordFrame: VIDIOC_QBUF Failed");
+        return;
+    }
+
+    nQueued++;
+
+    free(tmpBuffer);
+}
+
+sp<IMemory> V4L2Camera::GrabRawFrame ()
+{
+    sp<MemoryHeapBase> memHeap = new MemoryHeapBase(videoIn->width * videoIn->height * 2);
+    sp<MemoryBase> memBase = new MemoryBase(memHeap, 0, videoIn->width * videoIn->height * 2);
+
+    // Not yet implemented, do I have to?
+
+    return memBase;
+}
+
+// a helper class for jpeg compression in memory
+class MemoryStream {
+public:
+    MemoryStream(char* buf, size_t sz);
+    ~MemoryStream() { closeStream(); }
+
+    void closeStream();
+    size_t getOffset() const { return bytesWritten; }
+    operator FILE *() { return file; }
+
+private:
+    static int runThread(void *);
+    int readPipe();
+
+    char *buffer;
+    size_t size;
+    size_t bytesWritten;
+    int pipefd[2];
+    FILE *file;
+    Mutex lock;
+    Condition exitedCondition;
+};
+
+MemoryStream::MemoryStream(char* buf, size_t sz)
+    : buffer(buf), size(sz), bytesWritten(0)
+{
+    if ((file = pipe(pipefd) ? NULL : fdopen(pipefd[1], "w")))
+        createThread(runThread, this);
+}
+
+void MemoryStream::closeStream()
+{
+    if (file) {
+        AutoMutex l(lock);
+        fclose(file);
+        file = NULL;
+        exitedCondition.wait(lock);
+    }
+}
+
+int MemoryStream::runThread(void *self)
+{
+    return static_cast<MemoryStream *>(self)->readPipe();
+}
+
+int MemoryStream::readPipe()
+{
+    char *buf = buffer;
+    ssize_t sz;
+    while ((sz = read(pipefd[0], buf, size - bytesWritten)) > 0) {
+        bytesWritten += sz;
+        buf += sz;
+    }
+    close(pipefd[0]);
+    AutoMutex l(lock);
+    exitedCondition.signal();
+    return 0;
+}
+
+sp<IMemory> V4L2Camera::GrabJpegFrame ()
+{
+    int ret;
+
+    videoIn->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    videoIn->buf.memory = V4L2_MEMORY_MMAP;
+
+    /* Dequeue buffer */
+    ret = ioctl(fd, VIDIOC_DQBUF, &videoIn->buf);
+    if (ret < 0) {
+        LOGE("GrabJpegFrame: VIDIOC_DQBUF Failed");
+        return NULL;
+    }
+    nDequeued++;
+
+    LOGI("GrabJpegFrame: Generated a frame from capture device");
+
+    /* Enqueue buffer */
+    ret = ioctl(fd, VIDIOC_QBUF, &videoIn->buf);
+    if (ret < 0) {
+        LOGE("GrabJpegFrame: VIDIOC_QBUF Failed");
+        return NULL;
+    }
+    nQueued++;
+
+    size_t bytesused = videoIn->buf.bytesused;
+    if (char *tmpBuf = new char[bytesused]) {
+        MemoryStream strm(tmpBuf, bytesused);
+        saveYUYVtoJPEG((unsigned char *)videoIn->mem[videoIn->buf.index], videoIn->width, videoIn->height, strm, 100);
+        strm.closeStream();
+        size_t fileSize = strm.getOffset();
+
+        sp<MemoryHeapBase> mjpegPictureHeap = new MemoryHeapBase(fileSize);
+        sp<MemoryBase> jpegmemBase = new MemoryBase(mjpegPictureHeap, 0, fileSize);
+        memcpy(mjpegPictureHeap->base(), tmpBuf, fileSize);
+        delete[] tmpBuf;
+
+        return jpegmemBase;
+    }
+
+    return NULL;
+}
+
+int V4L2Camera::saveYUYVtoJPEG (unsigned char *inputBuffer, int width, int height, FILE *file, int quality)
+{
+    struct jpeg_compress_struct cinfo;
+    struct jpeg_error_mgr jerr;
+    JSAMPROW row_pointer[1];
+    unsigned char *line_buffer, *yuyv;
+    int z;
+    int fileSize;
+
+    line_buffer = (unsigned char *) calloc (width * 3, 1);
+    yuyv = inputBuffer;
+
+    cinfo.err = jpeg_std_error (&jerr);
+    jpeg_create_compress (&cinfo);
+    jpeg_stdio_dest (&cinfo, file);
+
+    LOGI("JPEG PICTURE WIDTH AND HEIGHT: %dx%d", width, height);
+
+    cinfo.image_width = width;
+    cinfo.image_height = height;
+    cinfo.input_components = 3;
+    cinfo.in_color_space = JCS_RGB;
+
+    jpeg_set_defaults (&cinfo);
+    jpeg_set_quality (&cinfo, quality, TRUE);
+
+    jpeg_start_compress (&cinfo, TRUE);
+
+    z = 0;
+    while (cinfo.next_scanline < cinfo.image_height) {
+        int x;
+        unsigned char *ptr = line_buffer;
+
+        for (x = 0; x < width; x++) {
+            int r, g, b;
+            int y, u, v;
+
+            if (!z)
+                y = yuyv[0] << 8;
+            else
+                y = yuyv[2] << 8;
+
+            u = yuyv[1] - 128;
+            v = yuyv[3] - 128;
+
+            r = (y + (359 * v)) >> 8;
+            g = (y - (88 * u) - (183 * v)) >> 8;
+            b = (y + (454 * u)) >> 8;
+
+            *(ptr++) = (r > 255) ? 255 : ((r < 0) ? 0 : r);
+            *(ptr++) = (g > 255) ? 255 : ((g < 0) ? 0 : g);
+            *(ptr++) = (b > 255) ? 255 : ((b < 0) ? 0 : b);
+
+            if (z++) {
+                z = 0;
+                yuyv += 4;
+            }
+        }
+
+        row_pointer[0] = line_buffer;
+        jpeg_write_scanlines (&cinfo, row_pointer, 1);
+    }
+
+    jpeg_finish_compress (&cinfo);
+    fileSize = ftell(file);
+    jpeg_destroy_compress (&cinfo);
+
+    free (line_buffer);
+
+    return fileSize;
+}
+
+void V4L2Camera::convert(unsigned char *buf, unsigned char *rgb, int width, int height)
+{
+    int x,y,z=0;
+    int blocks;
+
+    blocks = (width * height) * 2;
+
+    for (y = 0; y < blocks; y+=4) {
+        unsigned char Y1, Y2, U, V;
+
+        Y1 = buf[y + 0];
+        U = buf[y + 1];
+        Y2 = buf[y + 2];
+        V = buf[y + 3];
+
+        yuv_to_rgb16(Y1, U, V, &rgb[y]);
+        yuv_to_rgb16(Y2, U, V, &rgb[y + 2]);
+    }
+
+}
+
+void V4L2Camera::yuv_to_rgb16(unsigned char y, unsigned char u, unsigned char v, unsigned char *rgb)
+{
+    int r,g,b;
+    int z;
+    int rgb16;
+
+    z = 0;
+
+    r = 1.164 * (y - 16) + 1.596 * (v - 128);
+    g = 1.164 * (y - 16) - 0.813 * (v - 128) - 0.391 * (u -128);
+    b = 1.164 * (y - 16) + 2.018 * (u - 128);
+
+    if (r > 255) r = 255;
+    if (g > 255) g = 255;
+    if (b > 255) b = 255;
+
+    if (r < 0) r = 0;
+    if (g < 0) g = 0;
+    if (b < 0) b = 0;
+
+    rgb16 = (int)(((r >> 3)<<11) | ((g >> 2) << 5)| ((b >> 3) << 0));
+
+    *rgb = (unsigned char)(rgb16 & 0xFF);
+    rgb++;
+    *rgb = (unsigned char)((rgb16 & 0xFF00) >> 8);
+
+}
+
+
+}; // namespace android
diff --git a/libcamera/V4L2Camera.h b/libcamera/V4L2Camera.h
new file mode 100644
index 0000000..a4cf55b
--- /dev/null
+++ b/libcamera/V4L2Camera.h
@@ -0,0 +1,70 @@
+/*
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      Author: Niels Keeman <nielskeeman@gmail.com>
+ *
+ */
+
+#ifndef _V4L2CAMERA_H
+#define _V4L2CAMERA_H
+
+#define NB_BUFFER 4
+
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <linux/videodev.h>
+
+namespace android {
+
+struct vdIn {
+    struct v4l2_capability cap;
+    struct v4l2_format format;
+    struct v4l2_buffer buf;
+    struct v4l2_requestbuffers rb;
+    void *mem[NB_BUFFER];
+    bool isStreaming;
+    int width;
+    int height;
+    int formatIn;
+    int framesizeIn;
+};
+
+class V4L2Camera {
+
+public:
+    V4L2Camera();
+    ~V4L2Camera();
+
+    int Open (const char *device, int width, int height, int pixelformat);
+    void Close ();
+
+    int Init ();
+    void Uninit ();
+
+    int StartStreaming ();
+    int StopStreaming ();
+
+    void GrabPreviewFrame (void *previewBuffer);
+    void GrabRecordFrame (void *recordBuffer);
+    sp<IMemory> GrabRawFrame ();
+    sp<IMemory> GrabJpegFrame ();
+
+private:
+    struct vdIn *videoIn;
+    int fd;
+
+    int nQueued;
+    int nDequeued;
+
+    int saveYUYVtoJPEG (unsigned char *inputBuffer, int width, int height, FILE *file, int quality);
+
+    void convert(unsigned char *buf, unsigned char *rgb, int width, int height);
+    void yuv_to_rgb16(unsigned char y, unsigned char u, unsigned char v, unsigned char *rgb);
+};
+
+}; // namespace android
+
+#endif
diff --git a/libcamera/converter.cpp b/libcamera/converter.cpp
new file mode 100644
index 0000000..f0dc54d
--- /dev/null
+++ b/libcamera/converter.cpp
@@ -0,0 +1,261 @@
+/*
+**
+** Copyright (C) 2009 0xlab.org - http://0xlab.org/
+** Copyright 2008, The Android Open Source Project
+**
+** This work is based on yuvconverter 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.
+*/
+
+#include "converter.h"
+
+void
+yuyv422_to_yuv420(unsigned char *bufsrc, unsigned char *bufdest, int width, int height)
+{
+    unsigned char *ptrsrcy1, *ptrsrcy2;
+    unsigned char *ptrsrcy3, *ptrsrcy4;
+    unsigned char *ptrsrccb1, *ptrsrccb2;
+    unsigned char *ptrsrccb3, *ptrsrccb4;
+    unsigned char *ptrsrccr1, *ptrsrccr2;
+    unsigned char *ptrsrccr3, *ptrsrccr4;
+    int srcystride, srcccstride;
+
+    ptrsrcy1  = bufsrc ;
+    ptrsrcy2  = bufsrc + (width<<1) ;
+    ptrsrcy3  = bufsrc + (width<<1)*2 ;
+    ptrsrcy4  = bufsrc + (width<<1)*3 ;
+
+    ptrsrccb1 = bufsrc + 1;
+    ptrsrccb2 = bufsrc + (width<<1) + 1;
+    ptrsrccb3 = bufsrc + (width<<1)*2 + 1;
+    ptrsrccb4 = bufsrc + (width<<1)*3 + 1;
+
+    ptrsrccr1 = bufsrc + 3;
+    ptrsrccr2 = bufsrc + (width<<1) + 3;
+    ptrsrccr3 = bufsrc + (width<<1)*2 + 3;
+    ptrsrccr4 = bufsrc + (width<<1)*3 + 3;
+
+    srcystride  = (width<<1)*3;
+    srcccstride = (width<<1)*3;
+
+    unsigned char *ptrdesty1, *ptrdesty2;
+    unsigned char *ptrdesty3, *ptrdesty4;
+    unsigned char *ptrdestcb1, *ptrdestcb2;
+    unsigned char *ptrdestcr1, *ptrdestcr2;
+    int destystride, destccstride;
+
+    ptrdesty1 = bufdest;
+    ptrdesty2 = bufdest + width;
+    ptrdesty3 = bufdest + width*2;
+    ptrdesty4 = bufdest + width*3;
+
+    ptrdestcb1 = bufdest + width*height;
+    ptrdestcb2 = bufdest + width*height + (width>>1);
+
+    ptrdestcr1 = bufdest + width*height + ((width*height) >> 2);
+    ptrdestcr2 = bufdest + width*height + ((width*height) >> 2) + (width>>1);
+
+    destystride  = (width)*3;
+    destccstride = (width>>1);
+
+    int i, j;
+
+    for(j=0; j<(height/4); j++)
+    {
+        for(i=0;i<(width/2);i++)
+        {
+            (*ptrdesty1++) = (*ptrsrcy1);
+            (*ptrdesty2++) = (*ptrsrcy2);
+            (*ptrdesty3++) = (*ptrsrcy3);
+            (*ptrdesty4++) = (*ptrsrcy4);
+
+            ptrsrcy1 += 2;
+            ptrsrcy2 += 2;
+            ptrsrcy3 += 2;
+            ptrsrcy4 += 2;
+
+            (*ptrdesty1++) = (*ptrsrcy1);
+            (*ptrdesty2++) = (*ptrsrcy2);
+            (*ptrdesty3++) = (*ptrsrcy3);
+            (*ptrdesty4++) = (*ptrsrcy4);
+
+            ptrsrcy1 += 2;
+            ptrsrcy2 += 2;
+            ptrsrcy3 += 2;
+            ptrsrcy4 += 2;
+
+            (*ptrdestcb1++) = (*ptrsrccb1);
+            (*ptrdestcb2++) = (*ptrsrccb3);
+
+            ptrsrccb1 += 4;
+            ptrsrccb3 += 4;
+
+            (*ptrdestcr1++) = (*ptrsrccr1);
+            (*ptrdestcr2++) = (*ptrsrccr3);
+
+            ptrsrccr1 += 4;
+            ptrsrccr3 += 4;
+
+        }
+
+
+        /* Update src pointers */
+        ptrsrcy1  += srcystride;
+        ptrsrcy2  += srcystride;
+        ptrsrcy3  += srcystride;
+        ptrsrcy4  += srcystride;
+
+        ptrsrccb1 += srcccstride;
+        ptrsrccb3 += srcccstride;
+
+        ptrsrccr1 += srcccstride;
+        ptrsrccr3 += srcccstride;
+
+
+        /* Update dest pointers */
+        ptrdesty1 += destystride;
+        ptrdesty2 += destystride;
+        ptrdesty3 += destystride;
+        ptrdesty4 += destystride;
+
+        ptrdestcb1 += destccstride;
+        ptrdestcb2 += destccstride;
+
+        ptrdestcr1 += destccstride;
+        ptrdestcr2 += destccstride;
+
+    }
+}
+
+void
+yuyv422_to_yuv420sp(unsigned char *bufsrc, unsigned char *bufdest, int width, int height)
+{
+    unsigned char *ptrsrcy1, *ptrsrcy2;
+    unsigned char *ptrsrcy3, *ptrsrcy4;
+    unsigned char *ptrsrccb1, *ptrsrccb2;
+    unsigned char *ptrsrccb3, *ptrsrccb4;
+    unsigned char *ptrsrccr1, *ptrsrccr2;
+    unsigned char *ptrsrccr3, *ptrsrccr4;
+    int srcystride, srcccstride;
+
+    ptrsrcy1  = bufsrc ;
+    ptrsrcy2  = bufsrc + (width<<1) ;
+    ptrsrcy3  = bufsrc + (width<<1)*2 ;
+    ptrsrcy4  = bufsrc + (width<<1)*3 ;
+
+    ptrsrccb1 = bufsrc + 1;
+    ptrsrccb2 = bufsrc + (width<<1) + 1;
+    ptrsrccb3 = bufsrc + (width<<1)*2 + 1;
+    ptrsrccb4 = bufsrc + (width<<1)*3 + 1;
+
+    ptrsrccr1 = bufsrc + 3;
+    ptrsrccr2 = bufsrc + (width<<1) + 3;
+    ptrsrccr3 = bufsrc + (width<<1)*2 + 3;
+    ptrsrccr4 = bufsrc + (width<<1)*3 + 3;
+
+    srcystride  = (width<<1)*3;
+    srcccstride = (width<<1)*3;
+
+    unsigned char *ptrdesty1, *ptrdesty2;
+    unsigned char *ptrdesty3, *ptrdesty4;
+    unsigned char *ptrdestcb1, *ptrdestcb2;
+    unsigned char *ptrdestcr1, *ptrdestcr2;
+    int destystride, destccstride;
+
+    ptrdesty1 = bufdest;
+    ptrdesty2 = bufdest + width;
+    ptrdesty3 = bufdest + width*2;
+    ptrdesty4 = bufdest + width*3;
+
+    ptrdestcb1 = bufdest + width*height;
+    ptrdestcb2 = bufdest + width*height + width;
+
+    ptrdestcr1 = bufdest + width*height + 1;
+    ptrdestcr2 = bufdest + width*height + width + 1;
+
+    destystride  = (width)*3;
+    destccstride = width;
+
+    int i, j;
+
+    for(j=0; j<(height/4); j++)
+    {
+        for(i=0;i<(width/2);i++)
+        {
+            (*ptrdesty1++) = (*ptrsrcy1);
+            (*ptrdesty2++) = (*ptrsrcy2);
+            (*ptrdesty3++) = (*ptrsrcy3);
+            (*ptrdesty4++) = (*ptrsrcy4);
+
+            ptrsrcy1 += 2;
+            ptrsrcy2 += 2;
+            ptrsrcy3 += 2;
+            ptrsrcy4 += 2;
+
+            (*ptrdesty1++) = (*ptrsrcy1);
+            (*ptrdesty2++) = (*ptrsrcy2);
+            (*ptrdesty3++) = (*ptrsrcy3);
+            (*ptrdesty4++) = (*ptrsrcy4);
+
+            ptrsrcy1 += 2;
+            ptrsrcy2 += 2;
+            ptrsrcy3 += 2;
+            ptrsrcy4 += 2;
+
+            (*ptrdestcb1) = (*ptrsrccb1);
+            (*ptrdestcb2) = (*ptrsrccb3);
+            ptrdestcb1 += 2;
+            ptrdestcb2 += 2;
+
+            ptrsrccb1 += 4;
+            ptrsrccb3 += 4;
+
+            (*ptrdestcr1) = (*ptrsrccr1);
+            (*ptrdestcr2) = (*ptrsrccr3);
+            ptrdestcr1 += 2;
+            ptrdestcr2 += 2;
+
+            ptrsrccr1 += 4;
+            ptrsrccr3 += 4;
+
+        }
+
+
+        /* Update src pointers */
+        ptrsrcy1  += srcystride;
+        ptrsrcy2  += srcystride;
+        ptrsrcy3  += srcystride;
+        ptrsrcy4  += srcystride;
+
+        ptrsrccb1 += srcccstride;
+        ptrsrccb3 += srcccstride;
+
+        ptrsrccr1 += srcccstride;
+        ptrsrccr3 += srcccstride;
+
+
+        /* Update dest pointers */
+        ptrdesty1 += destystride;
+        ptrdesty2 += destystride;
+        ptrdesty3 += destystride;
+        ptrdesty4 += destystride;
+
+        ptrdestcb1 += destccstride;
+        ptrdestcb2 += destccstride;
+
+        ptrdestcr1 += destccstride;
+        ptrdestcr2 += destccstride;
+
+    }
+}
diff --git a/libcamera/converter.h b/libcamera/converter.h
new file mode 100644
index 0000000..e7ecf40
--- /dev/null
+++ b/libcamera/converter.h
@@ -0,0 +1,25 @@
+/*
+**
+** 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.
+*/
+
+#ifndef CONVERTER_H
+#define CONVERTER_H
+
+void yuyv422_to_yuv420(unsigned char *bufsrc, unsigned char *bufdest, int width, int height);
+void yuyv422_to_yuv420sp(unsigned char *bufsrc, unsigned char *bufdest, int width, int height);
+
+#endif