Home | History | Annotate | Download | only in fake-pipeline2
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "EmulatedCamera_Scene"
     19 #include <utils/Log.h>
     20 #include <stdlib.h>
     21 #include <cmath>
     22 #include "Scene.h"
     23 
     24 // TODO: This should probably be done host-side in OpenGL for speed and better
     25 // quality
     26 
     27 namespace android {
     28 
     29 // Define single-letter shortcuts for scene definition, for directly indexing
     30 // mCurrentColors
     31 #define G (Scene::GRASS * Scene::NUM_CHANNELS)
     32 #define S (Scene::GRASS_SHADOW * Scene::NUM_CHANNELS)
     33 #define H (Scene::HILL * Scene::NUM_CHANNELS)
     34 #define W (Scene::WALL * Scene::NUM_CHANNELS)
     35 #define R (Scene::ROOF * Scene::NUM_CHANNELS)
     36 #define D (Scene::DOOR * Scene::NUM_CHANNELS)
     37 #define C (Scene::CHIMNEY * Scene::NUM_CHANNELS)
     38 #define I (Scene::WINDOW * Scene::NUM_CHANNELS)
     39 #define U (Scene::SUN * Scene::NUM_CHANNELS)
     40 #define K (Scene::SKY * Scene::NUM_CHANNELS)
     41 #define M (Scene::MOON * Scene::NUM_CHANNELS)
     42 
     43 const int Scene::kSceneWidth = 20;
     44 const int Scene::kSceneHeight = 20;
     45 
     46 const uint8_t Scene::kScene[Scene::kSceneWidth * Scene::kSceneHeight] = {
     47     //      5         10        15        20
     48     K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,
     49     K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,
     50     K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,
     51     K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,
     52     K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K, // 5
     53     K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,
     54     K,K,K,K,K,K,K,K,H,H,H,H,H,H,H,H,H,H,H,H,
     55     K,K,K,K,K,K,K,K,H,H,H,H,H,H,H,C,C,H,H,H,
     56     K,K,K,K,K,K,H,H,H,H,H,H,H,H,H,C,C,H,H,H,
     57     H,K,K,K,K,K,H,R,R,R,R,R,R,R,R,R,R,R,R,H, // 10
     58     H,K,K,K,K,H,H,R,R,R,R,R,R,R,R,R,R,R,R,H,
     59     H,H,H,K,K,H,H,R,R,R,R,R,R,R,R,R,R,R,R,H,
     60     H,H,H,K,K,H,H,H,W,W,W,W,W,W,W,W,W,W,H,H,
     61     S,S,S,G,G,S,S,S,W,W,W,W,W,W,W,W,W,W,S,S,
     62     S,G,G,G,G,S,S,S,W,I,I,W,D,D,W,I,I,W,S,S, // 15
     63     G,G,G,G,G,G,S,S,W,I,I,W,D,D,W,I,I,W,S,S,
     64     G,G,G,G,G,G,G,G,W,W,W,W,D,D,W,W,W,W,G,G,
     65     G,G,G,G,G,G,G,G,W,W,W,W,D,D,W,W,W,W,G,G,
     66     G,G,G,G,G,G,G,G,S,S,S,S,S,S,S,S,S,S,G,G,
     67     G,G,G,G,G,G,G,G,S,S,S,S,S,S,S,S,S,S,G,G, // 20
     68     //      5         10        15        20
     69 };
     70 
     71 #undef G
     72 #undef S
     73 #undef H
     74 #undef W
     75 #undef R
     76 #undef D
     77 #undef C
     78 #undef I
     79 #undef U
     80 #undef K
     81 #undef M
     82 
     83 Scene::Scene(
     84     int sensorWidthPx,
     85     int sensorHeightPx,
     86     float sensorSensitivity):
     87         mSensorWidth(sensorWidthPx),
     88         mSensorHeight(sensorHeightPx),
     89         mHour(12),
     90         mExposureDuration(0.033f),
     91         mSensorSensitivity(sensorSensitivity)
     92 {
     93     // Map scene to sensor pixels
     94     if (mSensorWidth > mSensorHeight) {
     95         mMapDiv = (mSensorWidth / (kSceneWidth + 1) ) + 1;
     96     } else {
     97         mMapDiv = (mSensorHeight / (kSceneHeight + 1) ) + 1;
     98     }
     99     mOffsetX = (kSceneWidth * mMapDiv - mSensorWidth) / 2;
    100     mOffsetY = (kSceneHeight * mMapDiv - mSensorHeight) / 2;
    101 
    102     // Assume that sensor filters are sRGB primaries to start
    103     mFilterR[0]  =  3.2406f; mFilterR[1]  = -1.5372f; mFilterR[2]  = -0.4986f;
    104     mFilterGr[0] = -0.9689f; mFilterGr[1] =  1.8758f; mFilterGr[2] =  0.0415f;
    105     mFilterGb[0] = -0.9689f; mFilterGb[1] =  1.8758f; mFilterGb[2] =  0.0415f;
    106     mFilterB[0]  =  0.0557f; mFilterB[1]  = -0.2040f; mFilterB[2]  =  1.0570f;
    107 
    108 
    109 }
    110 
    111 Scene::~Scene() {
    112 }
    113 
    114 void Scene::setColorFilterXYZ(
    115         float rX, float rY, float rZ,
    116         float grX, float grY, float grZ,
    117         float gbX, float gbY, float gbZ,
    118         float bX, float bY, float bZ) {
    119     mFilterR[0]  = rX;  mFilterR[1]  = rY;  mFilterR[2]  = rZ;
    120     mFilterGr[0] = grX; mFilterGr[1] = grY; mFilterGr[2] = grZ;
    121     mFilterGb[0] = gbX; mFilterGb[1] = gbY; mFilterGb[2] = gbZ;
    122     mFilterB[0]  = bX;  mFilterB[1]  = bY;  mFilterB[2]  = bZ;
    123 }
    124 
    125 void Scene::setHour(int hour) {
    126     ALOGV("Hour set to: %d", hour);
    127     mHour = hour % 24;
    128 }
    129 
    130 int Scene::getHour() {
    131     return mHour;
    132 }
    133 
    134 void Scene::setExposureDuration(float seconds) {
    135     mExposureDuration = seconds;
    136 }
    137 
    138 void Scene::calculateScene(nsecs_t time) {
    139     // Calculate time fractions for interpolation
    140     int timeIdx = mHour / kTimeStep;
    141     int nextTimeIdx = (timeIdx + 1) % (24 / kTimeStep);
    142     const nsecs_t kOneHourInNsec = 1e9 * 60 * 60;
    143     nsecs_t timeSinceIdx = (mHour - timeIdx * kTimeStep) * kOneHourInNsec + time;
    144     float timeFrac = timeSinceIdx / (float)(kOneHourInNsec * kTimeStep);
    145 
    146     // Determine overall sunlight levels
    147     float sunLux =
    148             kSunlight[timeIdx] * (1 - timeFrac) +
    149             kSunlight[nextTimeIdx] * timeFrac;
    150     ALOGV("Sun lux: %f", sunLux);
    151 
    152     float sunShadeLux = sunLux * (kDaylightShadeIllum / kDirectSunIllum);
    153 
    154     // Determine sun/shade illumination chromaticity
    155     float currentSunXY[2];
    156     float currentShadeXY[2];
    157 
    158     const float *prevSunXY, *nextSunXY;
    159     const float *prevShadeXY, *nextShadeXY;
    160     if (kSunlight[timeIdx] == kSunsetIllum ||
    161             kSunlight[timeIdx] == kTwilightIllum) {
    162         prevSunXY = kSunsetXY;
    163         prevShadeXY = kSunsetXY;
    164     } else {
    165         prevSunXY = kDirectSunlightXY;
    166         prevShadeXY = kDaylightXY;
    167     }
    168     if (kSunlight[nextTimeIdx] == kSunsetIllum ||
    169             kSunlight[nextTimeIdx] == kTwilightIllum) {
    170         nextSunXY = kSunsetXY;
    171         nextShadeXY = kSunsetXY;
    172     } else {
    173         nextSunXY = kDirectSunlightXY;
    174         nextShadeXY = kDaylightXY;
    175     }
    176     currentSunXY[0] = prevSunXY[0] * (1 - timeFrac) +
    177             nextSunXY[0] * timeFrac;
    178     currentSunXY[1] = prevSunXY[1] * (1 - timeFrac) +
    179             nextSunXY[1] * timeFrac;
    180 
    181     currentShadeXY[0] = prevShadeXY[0] * (1 - timeFrac) +
    182             nextShadeXY[0] * timeFrac;
    183     currentShadeXY[1] = prevShadeXY[1] * (1 - timeFrac) +
    184             nextShadeXY[1] * timeFrac;
    185 
    186     ALOGV("Sun XY: %f, %f, Shade XY: %f, %f",
    187             currentSunXY[0], currentSunXY[1],
    188             currentShadeXY[0], currentShadeXY[1]);
    189 
    190     // Converting for xyY to XYZ:
    191     // X = Y / y * x
    192     // Y = Y
    193     // Z = Y / y * (1 - x - y);
    194     float sunXYZ[3] = {
    195         sunLux / currentSunXY[1] * currentSunXY[0],
    196         sunLux,
    197         sunLux / currentSunXY[1] *
    198         (1 - currentSunXY[0] - currentSunXY[1])
    199     };
    200     float sunShadeXYZ[3] = {
    201         sunShadeLux / currentShadeXY[1] * currentShadeXY[0],
    202         sunShadeLux,
    203         sunShadeLux / currentShadeXY[1] *
    204         (1 - currentShadeXY[0] - currentShadeXY[1])
    205     };
    206     ALOGV("Sun XYZ: %f, %f, %f",
    207             sunXYZ[0], sunXYZ[1], sunXYZ[2]);
    208     ALOGV("Sun shade XYZ: %f, %f, %f",
    209             sunShadeXYZ[0], sunShadeXYZ[1], sunShadeXYZ[2]);
    210 
    211     // Determine moonlight levels
    212     float moonLux =
    213             kMoonlight[timeIdx] * (1 - timeFrac) +
    214             kMoonlight[nextTimeIdx] * timeFrac;
    215     float moonShadeLux = moonLux * (kDaylightShadeIllum / kDirectSunIllum);
    216 
    217     float moonXYZ[3] = {
    218         moonLux / kMoonlightXY[1] * kMoonlightXY[0],
    219         moonLux,
    220         moonLux / kMoonlightXY[1] *
    221         (1 - kMoonlightXY[0] - kMoonlightXY[1])
    222     };
    223     float moonShadeXYZ[3] = {
    224         moonShadeLux / kMoonlightXY[1] * kMoonlightXY[0],
    225         moonShadeLux,
    226         moonShadeLux / kMoonlightXY[1] *
    227         (1 - kMoonlightXY[0] - kMoonlightXY[1])
    228     };
    229 
    230     // Determine starlight level
    231     const float kClearNightXYZ[3] = {
    232         kClearNightIllum / kMoonlightXY[1] * kMoonlightXY[0],
    233         kClearNightIllum,
    234         kClearNightIllum / kMoonlightXY[1] *
    235             (1 - kMoonlightXY[0] - kMoonlightXY[1])
    236     };
    237 
    238     // Calculate direct and shaded light
    239     float directIllumXYZ[3] = {
    240         sunXYZ[0] + moonXYZ[0] + kClearNightXYZ[0],
    241         sunXYZ[1] + moonXYZ[1] + kClearNightXYZ[1],
    242         sunXYZ[2] + moonXYZ[2] + kClearNightXYZ[2],
    243     };
    244 
    245     float shadeIllumXYZ[3] = {
    246         kClearNightXYZ[0],
    247         kClearNightXYZ[1],
    248         kClearNightXYZ[2]
    249     };
    250 
    251     shadeIllumXYZ[0] += (mHour < kSunOverhead) ? sunXYZ[0] : sunShadeXYZ[0];
    252     shadeIllumXYZ[1] += (mHour < kSunOverhead) ? sunXYZ[1] : sunShadeXYZ[1];
    253     shadeIllumXYZ[2] += (mHour < kSunOverhead) ? sunXYZ[2] : sunShadeXYZ[2];
    254 
    255     // Moon up period covers 23->0 transition, shift for simplicity
    256     int adjHour = (mHour + 12) % 24;
    257     int adjMoonOverhead = (kMoonOverhead + 12 ) % 24;
    258     shadeIllumXYZ[0] += (adjHour < adjMoonOverhead) ?
    259             moonXYZ[0] : moonShadeXYZ[0];
    260     shadeIllumXYZ[1] += (adjHour < adjMoonOverhead) ?
    261             moonXYZ[1] : moonShadeXYZ[1];
    262     shadeIllumXYZ[2] += (adjHour < adjMoonOverhead) ?
    263             moonXYZ[2] : moonShadeXYZ[2];
    264 
    265     ALOGV("Direct XYZ: %f, %f, %f",
    266             directIllumXYZ[0],directIllumXYZ[1],directIllumXYZ[2]);
    267     ALOGV("Shade XYZ: %f, %f, %f",
    268             shadeIllumXYZ[0], shadeIllumXYZ[1], shadeIllumXYZ[2]);
    269 
    270     for (int i = 0; i < NUM_MATERIALS; i++) {
    271         // Converting for xyY to XYZ:
    272         // X = Y / y * x
    273         // Y = Y
    274         // Z = Y / y * (1 - x - y);
    275         float matXYZ[3] = {
    276             kMaterials_xyY[i][2] / kMaterials_xyY[i][1] *
    277               kMaterials_xyY[i][0],
    278             kMaterials_xyY[i][2],
    279             kMaterials_xyY[i][2] / kMaterials_xyY[i][1] *
    280               (1 - kMaterials_xyY[i][0] - kMaterials_xyY[i][1])
    281         };
    282 
    283         if (kMaterialsFlags[i] == 0 || kMaterialsFlags[i] & kSky) {
    284             matXYZ[0] *= directIllumXYZ[0];
    285             matXYZ[1] *= directIllumXYZ[1];
    286             matXYZ[2] *= directIllumXYZ[2];
    287         } else if (kMaterialsFlags[i] & kShadowed) {
    288             matXYZ[0] *= shadeIllumXYZ[0];
    289             matXYZ[1] *= shadeIllumXYZ[1];
    290             matXYZ[2] *= shadeIllumXYZ[2];
    291         } // else if (kMaterialsFlags[i] * kSelfLit), do nothing
    292 
    293         ALOGV("Mat %d XYZ: %f, %f, %f", i, matXYZ[0], matXYZ[1], matXYZ[2]);
    294         //float luxToElectrons = mSensorSensitivity * mExposureDuration /
    295         //        (kAperture * kAperture);
    296         // Hack, fixed value to avoid over exposure and produce more
    297         // colors to pass CTS jpeg size check
    298         float luxToElectrons = 0.490581;
    299         mCurrentColors[i*NUM_CHANNELS + 0] =
    300                 (mFilterR[0] * matXYZ[0] +
    301                  mFilterR[1] * matXYZ[1] +
    302                  mFilterR[2] * matXYZ[2])
    303                 * luxToElectrons;
    304         mCurrentColors[i*NUM_CHANNELS + 1] =
    305                 (mFilterGr[0] * matXYZ[0] +
    306                  mFilterGr[1] * matXYZ[1] +
    307                  mFilterGr[2] * matXYZ[2])
    308                 * luxToElectrons;
    309         mCurrentColors[i*NUM_CHANNELS + 2] =
    310                 (mFilterGb[0] * matXYZ[0] +
    311                  mFilterGb[1] * matXYZ[1] +
    312                  mFilterGb[2] * matXYZ[2])
    313                 * luxToElectrons;
    314         mCurrentColors[i*NUM_CHANNELS + 3] =
    315                 (mFilterB[0] * matXYZ[0] +
    316                  mFilterB[1] * matXYZ[1] +
    317                  mFilterB[2] * matXYZ[2])
    318                 * luxToElectrons;
    319 
    320         ALOGV("Color %d RGGB: %d, %d, %d, %d", i,
    321                 mCurrentColors[i*NUM_CHANNELS + 0],
    322                 mCurrentColors[i*NUM_CHANNELS + 1],
    323                 mCurrentColors[i*NUM_CHANNELS + 2],
    324                 mCurrentColors[i*NUM_CHANNELS + 3]);
    325     }
    326     // Shake viewpoint; horizontal and vertical sinusoids at roughly
    327     // human handshake frequencies
    328     mHandshakeX =
    329             ( kFreq1Magnitude * std::sin(kHorizShakeFreq1 * timeSinceIdx) +
    330               kFreq2Magnitude * std::sin(kHorizShakeFreq2 * timeSinceIdx) ) *
    331             mMapDiv * kShakeFraction;
    332 
    333     mHandshakeY =
    334             ( kFreq1Magnitude * std::sin(kVertShakeFreq1 * timeSinceIdx) +
    335               kFreq2Magnitude * std::sin(kVertShakeFreq2 * timeSinceIdx) ) *
    336             mMapDiv * kShakeFraction;
    337 
    338     // Set starting pixel
    339     setReadoutPixel(0,0);
    340 }
    341 
    342 void Scene::setReadoutPixel(int x, int y) {
    343     mCurrentX = x;
    344     mCurrentY = y;
    345     mSubX = (x + mOffsetX + mHandshakeX) % mMapDiv;
    346     mSubY = (y + mOffsetY + mHandshakeY) % mMapDiv;
    347     mSceneX = (x + mOffsetX + mHandshakeX) / mMapDiv;
    348     mSceneY = (y + mOffsetY + mHandshakeY) / mMapDiv;
    349     mSceneIdx = mSceneY * kSceneWidth + mSceneX;
    350     mCurrentSceneMaterial = &(mCurrentColors[kScene[mSceneIdx]]);
    351 }
    352 
    353 const uint32_t* Scene::getPixelElectrons() {
    354     const uint32_t *pixel = mCurrentSceneMaterial;
    355     mCurrentX++;
    356     mSubX++;
    357     if (mCurrentX >= mSensorWidth) {
    358         mCurrentX = 0;
    359         mCurrentY++;
    360         if (mCurrentY >= mSensorHeight) mCurrentY = 0;
    361         setReadoutPixel(mCurrentX, mCurrentY);
    362     } else if (mSubX > mMapDiv) {
    363         mSceneIdx++;
    364         mSceneX++;
    365         mCurrentSceneMaterial = &(mCurrentColors[kScene[mSceneIdx]]);
    366         mSubX = 0;
    367     }
    368     return pixel;
    369 }
    370 
    371 // Handshake model constants.
    372 // Frequencies measured in a nanosecond timebase
    373 const float Scene::kHorizShakeFreq1 = 2 * M_PI * 2  / 1e9; // 2 Hz
    374 const float Scene::kHorizShakeFreq2 = 2 * M_PI * 13 / 1e9; // 13 Hz
    375 const float Scene::kVertShakeFreq1  = 2 * M_PI * 3  / 1e9; // 3 Hz
    376 const float Scene::kVertShakeFreq2  = 2 * M_PI * 11 / 1e9; // 1 Hz
    377 const float Scene::kFreq1Magnitude  = 5;
    378 const float Scene::kFreq2Magnitude  = 1;
    379 const float Scene::kShakeFraction   = 0.03; // As a fraction of a scene tile
    380 
    381 // RGB->YUV, Jpeg standard
    382 const float Scene::kRgb2Yuv[12] = {
    383        0.299f,    0.587f,    0.114f,    0.f,
    384     -0.16874f, -0.33126f,      0.5f, -128.f,
    385          0.5f, -0.41869f, -0.08131f, -128.f,
    386 };
    387 
    388 // Aperture of imaging lens
    389 const float Scene::kAperture = 2.8;
    390 
    391 // Sun illumination levels through the day
    392 const float Scene::kSunlight[24/kTimeStep] =
    393 {
    394     0, // 00:00
    395     0,
    396     0,
    397     kTwilightIllum, // 06:00
    398     kDirectSunIllum,
    399     kDirectSunIllum,
    400     kDirectSunIllum, // 12:00
    401     kDirectSunIllum,
    402     kDirectSunIllum,
    403     kSunsetIllum, // 18:00
    404     kTwilightIllum,
    405     0
    406 };
    407 
    408 // Moon illumination levels through the day
    409 const float Scene::kMoonlight[24/kTimeStep] =
    410 {
    411     kFullMoonIllum, // 00:00
    412     kFullMoonIllum,
    413     0,
    414     0, // 06:00
    415     0,
    416     0,
    417     0, // 12:00
    418     0,
    419     0,
    420     0, // 18:00
    421     0,
    422     kFullMoonIllum
    423 };
    424 
    425 const int Scene::kSunOverhead = 12;
    426 const int Scene::kMoonOverhead = 0;
    427 
    428 // Used for sun illumination levels
    429 const float Scene::kDirectSunIllum     = 100000;
    430 const float Scene::kSunsetIllum        = 400;
    431 const float Scene::kTwilightIllum      = 4;
    432 // Used for moon illumination levels
    433 const float Scene::kFullMoonIllum      = 1;
    434 // Other illumination levels
    435 const float Scene::kDaylightShadeIllum = 20000;
    436 const float Scene::kClearNightIllum    = 2e-3;
    437 const float Scene::kStarIllum          = 2e-6;
    438 const float Scene::kLivingRoomIllum    = 50;
    439 
    440 const float Scene::kIncandescentXY[2]   = { 0.44757f, 0.40745f};
    441 const float Scene::kDirectSunlightXY[2] = { 0.34842f, 0.35161f};
    442 const float Scene::kDaylightXY[2]       = { 0.31271f, 0.32902f};
    443 const float Scene::kNoonSkyXY[2]        = { 0.346f,   0.359f};
    444 const float Scene::kMoonlightXY[2]      = { 0.34842f, 0.35161f};
    445 const float Scene::kSunsetXY[2]         = { 0.527f,   0.413f};
    446 
    447 const uint8_t Scene::kSelfLit  = 0x01;
    448 const uint8_t Scene::kShadowed = 0x02;
    449 const uint8_t Scene::kSky      = 0x04;
    450 
    451 // For non-self-lit materials, the Y component is normalized with 1=full
    452 // reflectance; for self-lit materials, it's the constant illuminance in lux.
    453 const float Scene::kMaterials_xyY[Scene::NUM_MATERIALS][3] = {
    454     { 0.3688f, 0.4501f, .1329f }, // GRASS
    455     { 0.3688f, 0.4501f, .1329f }, // GRASS_SHADOW
    456     { 0.3986f, 0.5002f, .4440f }, // HILL
    457     { 0.3262f, 0.5040f, .2297f }, // WALL
    458     { 0.4336f, 0.3787f, .1029f }, // ROOF
    459     { 0.3316f, 0.2544f, .0639f }, // DOOR
    460     { 0.3425f, 0.3577f, .0887f }, // CHIMNEY
    461     { kIncandescentXY[0], kIncandescentXY[1], kLivingRoomIllum }, // WINDOW
    462     { kDirectSunlightXY[0], kDirectSunlightXY[1], kDirectSunIllum }, // SUN
    463     { kNoonSkyXY[0], kNoonSkyXY[1], kDaylightShadeIllum / kDirectSunIllum }, // SKY
    464     { kMoonlightXY[0], kMoonlightXY[1], kFullMoonIllum } // MOON
    465 };
    466 
    467 const uint8_t Scene::kMaterialsFlags[Scene::NUM_MATERIALS] = {
    468     0,
    469     kShadowed,
    470     kShadowed,
    471     kShadowed,
    472     kShadowed,
    473     kShadowed,
    474     kShadowed,
    475     kSelfLit,
    476     kSelfLit,
    477     kSky,
    478     kSelfLit,
    479 };
    480 
    481 } // namespace android
    482