introduce camera.goldfish.jpeg to allow building emulator camera HAL in PDK

- it only do JPEG encoding, but separated due to dependency on libskia and
  libandroid_runtime, which are not in PDK
- camera.goldfish.jpeg will be included to platform.zip

Change-Id: I71758c8bb3e05831094ccb268bfc20c5a160f0c9
diff --git a/camera/Android.mk b/camera/Android.mk
index 2428092..f3201ab 100755
--- a/camera/Android.mk
+++ b/camera/Android.mk
@@ -25,18 +25,15 @@
     libcutils \
     libcamera_client \
     libui \
+    libdl
 
 # JPEG conversion libraries and includes.
 LOCAL_SHARED_LIBRARIES += \
 	libjpeg \
-	libskia \
-	libandroid_runtime \
 	libcamera_metadata
 
 LOCAL_C_INCLUDES += external/jpeg \
-	external/skia/include/core/ \
 	frameworks/native/include/media/hardware \
-	frameworks/base/core/jni/android/graphics \
 	$(LOCAL_PATH)/../opengl/system/OpenglSystemCommon \
 	$(call include-path-for, camera)
 
@@ -70,3 +67,28 @@
 endif
 
 include $(BUILD_SHARED_LIBRARY)
+
+#################################################################
+ifneq ($(TARGET_BUILD_PDK),true)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_CFLAGS += -fno-short-enums -DQEMU_HARDWARE
+LOCAL_SHARED_LIBRARIES:= \
+    libcutils \
+    libskia \
+    libandroid_runtime
+
+LOCAL_C_INCLUDES += external/jpeg \
+                    external/skia/include/core/ \
+                    frameworks/base/core/jni/android/graphics \
+                    frameworks/native/include
+
+LOCAL_SRC_FILES := JpegStub.cpp
+
+LOCAL_MODULE := camera.goldfish.jpeg
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif # !PDK
diff --git a/camera/JpegCompressor.cpp b/camera/JpegCompressor.cpp
index 8eec52d..8014ccf 100644
--- a/camera/JpegCompressor.cpp
+++ b/camera/JpegCompressor.cpp
@@ -22,17 +22,44 @@
 #define LOG_NDEBUG 0
 #define LOG_TAG "EmulatedCamera_JPEG"
 #include <cutils/log.h>
+#include <assert.h>
+#include <dlfcn.h>
 #include "JpegCompressor.h"
 
 namespace android {
 
+void* NV21JpegCompressor::mDl = NULL;
+
+static void* getSymbol(void* dl, const char* signature) {
+    void* res = dlsym(dl, signature);
+    assert (res != NULL);
+
+    return res;
+}
+
+typedef void (*InitFunc)(JpegStub* stub, int* strides);
+typedef void (*CleanupFunc)(JpegStub* stub);
+typedef int (*CompressFunc)(JpegStub* stub, const void* image,
+        int width, int height, int quality);
+typedef void (*GetCompressedImageFunc)(JpegStub* stub, void* buff);
+typedef size_t (*GetCompressedSizeFunc)(JpegStub* stub);
+
 NV21JpegCompressor::NV21JpegCompressor()
-    : Yuv420SpToJpegEncoder(mStrides)
 {
+    const char dlName[] = "/system/lib/hw/camera.goldfish.jpeg.so";
+    if (mDl == NULL) {
+        mDl = dlopen(dlName, RTLD_NOW);
+    }
+    assert(mDl != NULL);
+
+    InitFunc f = (InitFunc)getSymbol(mDl, "JpegStub_init");
+    (*f)(&mStub, mStrides);
 }
 
 NV21JpegCompressor::~NV21JpegCompressor()
 {
+    CleanupFunc f = (CleanupFunc)getSymbol(mDl, "JpegStub_cleanup");
+    (*f)(&mStub);
 }
 
 /****************************************************************************
@@ -44,21 +71,25 @@
                                               int height,
                                               int quality)
 {
-    ALOGV("%s: %p[%dx%d]", __FUNCTION__, image, width, height);
-    void* pY = const_cast<void*>(image);
-    int offsets[2];
-    offsets[0] = 0;
-    offsets[1] = width * height;
     mStrides[0] = width;
     mStrides[1] = width;
-    if (encode(&mStream, pY, width, height, offsets, quality)) {
-        ALOGV("%s: Compressed JPEG: %d[%dx%d] -> %d bytes",
-             __FUNCTION__, (width * height * 12) / 8, width, height, mStream.getOffset());
-        return NO_ERROR;
-    } else {
-        ALOGE("%s: JPEG compression failed", __FUNCTION__);
-        return errno ? errno : EINVAL;
-    }
+    CompressFunc f = (CompressFunc)getSymbol(mDl, "JpegStub_compress");
+    return (status_t)(*f)(&mStub, image, width, height, quality);
+}
+
+
+size_t NV21JpegCompressor::getCompressedSize()
+{
+    GetCompressedSizeFunc f = (GetCompressedSizeFunc)getSymbol(mDl,
+            "JpegStub_getCompressedSize");
+    return (*f)(&mStub);
+}
+
+void NV21JpegCompressor::getCompressedImage(void* buff)
+{
+    GetCompressedImageFunc f = (GetCompressedImageFunc)getSymbol(mDl,
+            "JpegStub_getCompressedImage");
+    (*f)(&mStub, buff);
 }
 
 }; /* namespace android */
diff --git a/camera/JpegCompressor.h b/camera/JpegCompressor.h
index 504ffcd..a6454d2 100644
--- a/camera/JpegCompressor.h
+++ b/camera/JpegCompressor.h
@@ -22,14 +22,14 @@
  * converter between YV21, and JPEG formats.
  */
 
-#include <YuvToJpegEncoder.h>
+#include "JpegStub.h"
 #include <utils/threads.h>
 
 namespace android {
 
 /* Encapsulates a converter between YV12, and JPEG formats.
  */
-class NV21JpegCompressor : protected Yuv420SpToJpegEncoder
+class NV21JpegCompressor
 {
 public:
     /* Constructs JpegCompressor instance. */
@@ -65,10 +65,7 @@
      * Return:
      *  Size of the compressed JPEG buffer.
      */
-    size_t getCompressedSize() const
-    {
-        return mStream.getOffset();
-    }
+    size_t getCompressedSize();
 
     /* Copies out compressed JPEG buffer.
      * This method must be called only after a successful completion of
@@ -77,20 +74,20 @@
      *  buff - Buffer where to copy the JPEG. Must be large enough to contain the
      *      entire image.
      */
-    void getCompressedImage(void* buff) const
-    {
-        mStream.copyTo(buff);
-    }
+    void getCompressedImage(void* buff);
 
     /****************************************************************************
      * Class data
      ***************************************************************************/
 
 protected:
-    /* Memory stream where converted JPEG is saved. */
-    SkDynamicMemoryWStream  mStream;
     /* Strides for Y (the first element), and UV (the second one) panes. */
     int                     mStrides[2];
+
+private:
+    // library handle to dlopen
+    static void* mDl;
+    JpegStub mStub;
 };
 
 }; /* namespace android */
diff --git a/camera/JpegStub.cpp b/camera/JpegStub.cpp
new file mode 100644
index 0000000..ce7ca89
--- /dev/null
+++ b/camera/JpegStub.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2013 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_NDEBUG 0
+#define LOG_TAG "EmulatedCamera_JPEGStub"
+#include <errno.h>
+#include <cutils/log.h>
+#include <YuvToJpegEncoder.h>
+
+#include "JpegStub.h"
+
+
+extern "C" void JpegStub_init(JpegStub* stub, int* strides) {
+    stub->mInternalEncoder = (void*) new Yuv420SpToJpegEncoder(strides);
+    stub->mInternalStream = (void*)new SkDynamicMemoryWStream();
+}
+
+extern "C" void JpegStub_cleanup(JpegStub* stub) {
+    delete((Yuv420SpToJpegEncoder*)stub->mInternalEncoder);
+    delete((SkDynamicMemoryWStream*)stub->mInternalStream);
+}
+
+extern "C" int JpegStub_compress(JpegStub* stub, const void* image,
+        int width, int height, int quality)
+{
+    void* pY = const_cast<void*>(image);
+    int offsets[2];
+    offsets[0] = 0;
+    offsets[1] = width * height;
+
+    Yuv420SpToJpegEncoder* encoder =
+        (Yuv420SpToJpegEncoder*)stub->mInternalEncoder;
+    SkDynamicMemoryWStream* stream =
+        (SkDynamicMemoryWStream*)stub->mInternalStream;
+    if (encoder->encode(stream, pY, width, height, offsets, quality)) {
+        ALOGV("%s: Compressed JPEG: %d[%dx%d] -> %d bytes",
+              __FUNCTION__, (width * height * 12) / 8,
+              width, height, stream->getOffset());
+        return 0;
+    } else {
+        ALOGE("%s: JPEG compression failed", __FUNCTION__);
+        return errno ? errno: EINVAL;
+    }
+}
+
+extern "C" void JpegStub_getCompressedImage(JpegStub* stub, void* buff) {
+    SkDynamicMemoryWStream* stream =
+        (SkDynamicMemoryWStream*)stub->mInternalStream;
+    stream->copyTo(buff);
+}
+
+extern "C" size_t JpegStub_getCompressedSize(JpegStub* stub) {
+    SkDynamicMemoryWStream* stream =
+        (SkDynamicMemoryWStream*)stub->mInternalStream;
+    return stream->getOffset();
+}
diff --git a/camera/JpegStub.h b/camera/JpegStub.h
new file mode 100644
index 0000000..ad00a54
--- /dev/null
+++ b/camera/JpegStub.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013 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 JPEGSTUB_H_
+#define JPEGSTUB_H_
+
+extern "C" {
+
+struct JpegStub {
+    void* mInternalEncoder;
+    void* mInternalStream;
+};
+
+void JpegStub_init(JpegStub* stub, int* strides);
+void JpegStub_cleanup(JpegStub* stub);
+int JpegStub_compress(JpegStub* stub, const void* image,
+        int width, int height, int quality);
+void JpegStub_getCompressedImage(JpegStub* stub, void* buff);
+size_t JpegStub_getCompressedSize(JpegStub* stub);
+
+};
+#endif // JPEGSTUB_H_