OSDN Git Service

make camcorder ok
authorSwan Wang <swandle@gmail.com>
Wed, 20 Jan 2010 09:59:50 +0000 (17:59 +0800)
committerChih-Wei Huang <cwhuang@linux.org.tw>
Fri, 29 Oct 2010 07:45:15 +0000 (15:45 +0800)
camera/libcameraservice/Android.mk
camera/libcameraservice/CameraHardware.cpp
camera/libcameraservice/CameraHardware.h
camera/libcameraservice/V4L2Camera.cpp
camera/libcameraservice/V4L2Camera.h
camera/libcameraservice/converter.cpp [new file with mode: 0755]
camera/libcameraservice/converter.h [new file with mode: 0755]

index 7fc4b54..f76df84 100644 (file)
@@ -37,7 +37,8 @@ else
 
 LOCAL_SRC_FILES:=               \
     CameraHardware.cpp          \
-    V4L2Camera.cpp
+    V4L2Camera.cpp              \
+    converter.cpp
 
 LOCAL_CFLAGS += -Iexternal/jpeg
 
index 258c8a3..6668b25 100644 (file)
@@ -39,9 +39,11 @@ CameraHardware::CameraHardware()
                   : mParameters(),
                     mHeap(0),
                     mPreviewHeap(0),
+                    mRecordHeap(0),
                     mRawHeap(0),
                     mPreviewFrameSize(0),
                     mCurrentPreviewFrame(0),
+                    mRecordRunning(false),
                     previewStopped(true),
                     nQueued(0),
                     nDequeued(0),
@@ -122,8 +124,15 @@ int CameraHardware::previewThread()
     if (!previewStopped) {
         // Get preview frame
         camera.GrabPreviewFrame(mHeap->getBase());
-        if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
+        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;
@@ -190,16 +199,23 @@ bool CameraHardware::previewEnabled()
 
 status_t CameraHardware::startRecording()
 {
-    return UNKNOWN_ERROR;
+    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 false;
+    return mRecordRunning;
 }
 
 void CameraHardware::releaseRecordingFrame(const sp<IMemory>& mem)
index 7f05255..8e7714c 100644 (file)
@@ -122,8 +122,11 @@ private:
 
     sp<MemoryHeapBase>      mPreviewHeap;
     sp<MemoryHeapBase>      mRawHeap;
+    sp<MemoryHeapBase>      mRecordHeap;
+    sp<MemoryBase>          mRecordBuffer;
 
     bool                    mPreviewRunning;
+    bool                    mRecordRunning;
     int                     mPreviewFrameSize;
 
     // protected by mLock
index 0fdc146..46ef365 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <linux/videodev.h>
 
+#include "converter.h"
 #include "V4L2Camera.h"
 
 extern "C" { /* Android jpeglib.h missed extern "C" */
@@ -243,6 +244,40 @@ void V4L2Camera::GrabPreviewFrame (void *previewBuffer)
     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);
index 97255ec..a4cf55b 100644 (file)
@@ -48,6 +48,7 @@ public:
     int StopStreaming ();
 
     void GrabPreviewFrame (void *previewBuffer);
+    void GrabRecordFrame (void *recordBuffer);
     sp<IMemory> GrabRawFrame ();
     sp<IMemory> GrabJpegFrame ();
 
diff --git a/camera/libcameraservice/converter.cpp b/camera/libcameraservice/converter.cpp
new file mode 100755 (executable)
index 0000000..f0dc54d
--- /dev/null
@@ -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/camera/libcameraservice/converter.h b/camera/libcameraservice/converter.h
new file mode 100755 (executable)
index 0000000..e7ecf40
--- /dev/null
@@ -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