EmulatedFakeCamera2: Add features needed for recording support for 320x240, NV21

- Support 320x240 in addition to 640x480
- Support NV21 (monochrome only right now)
- Base simulated time on system time,
  since stagefright cares about timestamp base
- Use emulator magic gralloc format to enable gralloc to pick format based on
  destination.

Bug: 6243944
Change-Id: I3ea56bca726c69b51e03233ce86d4881401a3ffd
diff --git a/tools/emulator/system/camera/Android.mk b/tools/emulator/system/camera/Android.mk
index ee08f94..3843c1d 100755
--- a/tools/emulator/system/camera/Android.mk
+++ b/tools/emulator/system/camera/Android.mk
@@ -39,6 +39,7 @@
 	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)
 
 LOCAL_SRC_FILES := \
diff --git a/tools/emulator/system/camera/EmulatedFakeCamera2.cpp b/tools/emulator/system/camera/EmulatedFakeCamera2.cpp
index 2e46d1e..711c2d2 100644
--- a/tools/emulator/system/camera/EmulatedFakeCamera2.cpp
+++ b/tools/emulator/system/camera/EmulatedFakeCamera2.cpp
@@ -27,6 +27,7 @@
 #include "EmulatedCameraFactory.h"
 #include <ui/Rect.h>
 #include <ui/GraphicBufferMapper.h>
+#include "gralloc_cb.h"
 
 namespace android {
 
@@ -47,8 +48,8 @@
     Sensor::kFrameDurationRange[0]
 };
 
-const uint32_t EmulatedFakeCamera2::kAvailableProcessedSizes[2] = {
-    640, 480
+const uint32_t EmulatedFakeCamera2::kAvailableProcessedSizes[4] = {
+    640, 480, 320, 240
     //    Sensor::kResolution[0], Sensor::kResolution[1]
 };
 
@@ -251,8 +252,9 @@
             return BAD_VALUE;
         }
     } else {
-        // Emulator's opaque format is RGBA
-        format = HAL_PIXEL_FORMAT_RGBA_8888;
+        // Translate to emulator's magic format.
+        // Note: It is assumed that this is a processed format (not raw or JPEG).
+        format = GRALLOC_EMULATOR_PIXEL_FORMAT_AUTO;
     }
 
     const uint32_t *availableSizes;
@@ -266,6 +268,7 @@
             availableSizes = kAvailableJpegSizes;
             availableSizeCount = sizeof(kAvailableJpegSizes)/sizeof(uint32_t);
             break;
+        case GRALLOC_EMULATOR_PIXEL_FORMAT_AUTO:
         case HAL_PIXEL_FORMAT_RGBA_8888:
         case HAL_PIXEL_FORMAT_YV12:
         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
@@ -326,7 +329,7 @@
 
     *stream_id = mNextStreamId;
     if (format_actual) *format_actual = format;
-    *usage = GRALLOC_USAGE_SW_WRITE_OFTEN;
+    *usage = GRALLOC_USAGE_HW_CAMERA_WRITE;
     *max_buffers = 4;
 
     ALOGV("Stream allocated: %d, %d x %d, 0x%x. U: %x, B: %d",
@@ -340,9 +343,42 @@
             uint32_t stream_id,
             int num_buffers,
             buffer_handle_t *buffers) {
-    // Emulator doesn't need to register these with V4L2, etc.
+    Mutex::Autolock l(mMutex);
+
     ALOGV("%s: Stream %d registering %d buffers", __FUNCTION__,
             stream_id, num_buffers);
+    // Need to find out what the final concrete pixel format for our stream is
+    // Assumes that all buffers have the same format.
+    if (num_buffers < 1) {
+        ALOGE("%s: Stream %d only has %d buffers!",
+                __FUNCTION__, stream_id, num_buffers);
+        return BAD_VALUE;
+    }
+    const cb_handle_t *streamBuffer =
+            reinterpret_cast<const cb_handle_t*>(buffers[0]);
+
+    int finalFormat = streamBuffer->format;
+
+    if (finalFormat == GRALLOC_EMULATOR_PIXEL_FORMAT_AUTO) {
+        ALOGE("%s: Stream %d: Bad final pixel format "
+                "GRALLOC_EMULATOR_PIXEL_FORMAT_AUTO; "
+                "concrete pixel format required!", __FUNCTION__, stream_id);
+        return BAD_VALUE;
+    }
+
+    ssize_t streamIndex = mStreams.indexOfKey(stream_id);
+    if (streamIndex < 0) {
+        ALOGE("%s: Unknown stream id %d!", __FUNCTION__, stream_id);
+        return BAD_VALUE;
+    }
+
+    Stream &stream = mStreams.editValueAt(streamIndex);
+
+    ALOGV("%s: Stream %d format set to %x, previously %x",
+            __FUNCTION__, stream_id, finalFormat, stream.format);
+
+    stream.format = finalFormat;
+
     return NO_ERROR;
 }
 
@@ -593,7 +629,14 @@
         mNextNeedsJpeg = false;
         ALOGV("Setting up buffers for capture");
         for (size_t i = 0; i < streams.count; i++) {
-            const Stream &s = mParent->getStreamInfo(streams.data.u8[i]);
+            int streamId = streams.data.u8[i];
+            const Stream &s = mParent->getStreamInfo(streamId);
+            if (s.format == GRALLOC_EMULATOR_PIXEL_FORMAT_AUTO) {
+                ALOGE("%s: Stream %d does not have a concrete pixel format, but "
+                        "is included in a request!", __FUNCTION__, streamId);
+                mParent->signalError();
+                return false;
+            }
             StreamBuffer b;
             b.streamId = streams.data.u8[i];
             b.width  = s.width;
@@ -708,7 +751,7 @@
         const Rect rect(s.width, s.height);
 
         res = GraphicBufferMapper::get().lock(*(b.buffer),
-                GRALLOC_USAGE_SW_WRITE_OFTEN,
+                GRALLOC_USAGE_HW_CAMERA_WRITE,
                 rect, (void**)&(b.img) );
 
         if (res != NO_ERROR) {
@@ -1220,7 +1263,7 @@
             sizeof(exposureCompensationRange)/sizeof(int32_t));
 
     static const int32_t availableTargetFpsRanges[] = {
-            5, 30
+            5, 30, 15, 30
     };
     ADD_OR_SIZE(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
             availableTargetFpsRanges,
diff --git a/tools/emulator/system/camera/fake-pipeline2/Base.h b/tools/emulator/system/camera/fake-pipeline2/Base.h
index 7f6be16..f7ef9b1 100644
--- a/tools/emulator/system/camera/fake-pipeline2/Base.h
+++ b/tools/emulator/system/camera/fake-pipeline2/Base.h
@@ -43,7 +43,7 @@
 struct Stream {
     const camera2_stream_ops_t *ops;
     uint32_t width, height;
-    uint32_t format;
+    int32_t format;
     uint32_t stride;
 };
 
diff --git a/tools/emulator/system/camera/fake-pipeline2/Sensor.cpp b/tools/emulator/system/camera/fake-pipeline2/Sensor.cpp
index 29898b8..ca6908d 100644
--- a/tools/emulator/system/camera/fake-pipeline2/Sensor.cpp
+++ b/tools/emulator/system/camera/fake-pipeline2/Sensor.cpp
@@ -247,7 +247,9 @@
     nsecs_t captureTime = 0;
 
     nsecs_t startRealTime  = systemTime();
-    nsecs_t simulatedTime    = startRealTime - mStartupTime;
+    // Stagefright cares about system time for timestamps, so base simulated
+    // time on that.
+    nsecs_t simulatedTime    = startRealTime;
     nsecs_t frameEndRealTime = startRealTime + frameDuration;
     nsecs_t frameReadoutEndRealTime = startRealTime +
             kRowReadoutTime * kResolution[1];
@@ -312,8 +314,10 @@
                     captureRGB(bAux.img, gain, b.stride);
                     mNextCapturedBuffers->push_back(bAux);
                     break;
-                case HAL_PIXEL_FORMAT_YV12:
                 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+                    captureNV21(b.img, gain, b.stride);
+                    break;
+                case HAL_PIXEL_FORMAT_YV12:
                     // TODO:
                     ALOGE("%s: Format %x is TODO", __FUNCTION__, b.format);
                     break;
@@ -390,11 +394,12 @@
     float totalGain = gain/100.0 * kBaseGainFactor;
     // In fixed-point math, calculate total scaling from electrons to 8bpp
     int scale64x = 64 * totalGain * 255 / kMaxRawValue;
-    mScene.setReadoutPixel(0,0);
+    uint32_t inc = (stride == 320) ? 2 : 1;
 
-    for (unsigned int y = 0; y < kResolution[1]; y++ ) {
-        uint8_t *px = img + y * stride * 4;
-        for (unsigned int x = 0; x < kResolution[0]; x++) {
+    for (unsigned int y = 0, outY = 0; y < kResolution[1]; y+=inc, outY++ ) {
+        uint8_t *px = img + outY * stride * 4;
+        mScene.setReadoutPixel(0, y);
+        for (unsigned int x = 0; x < kResolution[0]; x+=inc) {
             uint32_t rCount, gCount, bCount;
             // TODO: Perfect demosaicing is a cheat
             const uint32_t *pixel = mScene.getPixelElectrons();
@@ -406,6 +411,7 @@
             *px++ = gCount < 255*64 ? gCount / 64 : 255;
             *px++ = bCount < 255*64 ? bCount / 64 : 255;
             *px++ = 255;
+            if (inc == 2) mScene.getPixelElectrons();
         }
         // TODO: Handle this better
         //simulatedTime += kRowReadoutTime;
@@ -417,11 +423,12 @@
     float totalGain = gain/100.0 * kBaseGainFactor;
     // In fixed-point math, calculate total scaling from electrons to 8bpp
     int scale64x = 64 * totalGain * 255 / kMaxRawValue;
-    mScene.setReadoutPixel(0,0);
+    uint32_t inc = (stride == 320) ? 2 : 1;
 
-    for (unsigned int y = 0; y < kResolution[1]; y++ ) {
-        uint8_t *px = img + y * stride * 3;
-        for (unsigned int x = 0; x < kResolution[0]; x++) {
+    for (unsigned int y = 0, outY = 0; y < kResolution[1]; y += inc, outY++ ) {
+        mScene.setReadoutPixel(0, y);
+        uint8_t *px = img + outY * stride * 3;
+        for (unsigned int x = 0; x < kResolution[0]; x += inc) {
             uint32_t rCount, gCount, bCount;
             // TODO: Perfect demosaicing is a cheat
             const uint32_t *pixel = mScene.getPixelElectrons();
@@ -432,6 +439,7 @@
             *px++ = rCount < 255*64 ? rCount / 64 : 255;
             *px++ = gCount < 255*64 ? gCount / 64 : 255;
             *px++ = bCount < 255*64 ? bCount / 64 : 255;
+            if (inc == 2) mScene.getPixelElectrons();
         }
         // TODO: Handle this better
         //simulatedTime += kRowReadoutTime;
@@ -439,4 +447,39 @@
     ALOGVV("RGB sensor image captured");
 }
 
+void Sensor::captureNV21(uint8_t *img, uint32_t gain, uint32_t stride) {
+    float totalGain = gain/100.0 * kBaseGainFactor;
+    // In fixed-point math, calculate total scaling from electrons to 8bpp
+    int scale64x = 64 * totalGain * 255 / kMaxRawValue;
+
+    // TODO: Make full-color
+    uint32_t inc = (stride == 320) ? 2 : 1;
+    uint32_t outH = kResolution[1] / inc;
+    for (unsigned int y = 0, outY = 0, outUV = outH;
+         y < kResolution[1]; y+=inc, outY++, outUV ) {
+        uint8_t *pxY = img + outY * stride;
+        mScene.setReadoutPixel(0,y);
+        for (unsigned int x = 0; x < kResolution[0]; x+=inc) {
+            uint32_t rCount, gCount, bCount;
+            // TODO: Perfect demosaicing is a cheat
+            const uint32_t *pixel = mScene.getPixelElectrons();
+            rCount = pixel[Scene::R]  * scale64x;
+            gCount = pixel[Scene::Gr] * scale64x;
+            bCount = pixel[Scene::B]  * scale64x;
+            uint32_t avg = (rCount + gCount + bCount) / 3;
+            *pxY++ = avg < 255*64 ? avg / 64 : 255;
+            if (inc == 2) mScene.getPixelElectrons();
+        }
+    }
+    for (unsigned int y = 0, outY = outH; y < kResolution[1]/2; y+=inc, outY++) {
+        uint8_t *px = img + outY * stride;
+        for (unsigned int x = 0; x < kResolution[0]; x+=inc) {
+            // UV to neutral
+            *px++ = 128;
+            *px++ = 128;
+        }
+    }
+    ALOGVV("NV21 sensor image captured");
+}
+
 } // namespace android
diff --git a/tools/emulator/system/camera/fake-pipeline2/Sensor.h b/tools/emulator/system/camera/fake-pipeline2/Sensor.h
index a666cc3..2919be4 100644
--- a/tools/emulator/system/camera/fake-pipeline2/Sensor.h
+++ b/tools/emulator/system/camera/fake-pipeline2/Sensor.h
@@ -212,7 +212,7 @@
     void captureRaw(uint8_t *img, uint32_t gain, uint32_t stride);
     void captureRGBA(uint8_t *img, uint32_t gain, uint32_t stride);
     void captureRGB(uint8_t *img, uint32_t gain, uint32_t stride);
-
+    void captureNV21(uint8_t *img, uint32_t gain, uint32_t stride);
 };
 
 }