• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_NNDEBUG 0
19 #define LOG_TAG "EmulatedCamera2_Sensor"
20 
21 #ifdef LOG_NNDEBUG
22 #define ALOGVV(...) ALOGV(__VA_ARGS__)
23 #else
24 #define ALOGVV(...) ((void)0)
25 #endif
26 
27 #include <utils/Log.h>
28 
29 #include <cmath>
30 #include <cstdlib>
31 #include "../EmulatedFakeCamera2.h"
32 #include "Sensor.h"
33 #include "guest/libs/platform_support/api_level_fixes.h"
34 #include "system/camera_metadata.h"
35 
36 namespace android {
37 
38 // const nsecs_t Sensor::kExposureTimeRange[2] =
39 //    {1000L, 30000000000L} ; // 1 us - 30 sec
40 // const nsecs_t Sensor::kFrameDurationRange[2] =
41 //    {33331760L, 30000000000L}; // ~1/30 s - 30 sec
42 const nsecs_t Sensor::kExposureTimeRange[2] = {1000L,
43                                                300000000L};  // 1 us - 0.3 sec
44 const nsecs_t Sensor::kFrameDurationRange[2] = {
45     33331760L, 300000000L};  // ~1/30 s - 0.3 sec
46 
47 const nsecs_t Sensor::kMinVerticalBlank = 10000L;
48 
49 const uint8_t Sensor::kColorFilterArrangement =
50     ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB;
51 
52 // Output image data characteristics
53 const uint32_t Sensor::kMaxRawValue = 4000;
54 const uint32_t Sensor::kBlackLevel = 1000;
55 
56 // Sensor sensitivity
57 const float Sensor::kSaturationVoltage = 0.520f;
58 const uint32_t Sensor::kSaturationElectrons = 2000;
59 const float Sensor::kVoltsPerLuxSecond = 0.100f;
60 
61 const float Sensor::kElectronsPerLuxSecond = Sensor::kSaturationElectrons /
62                                              Sensor::kSaturationVoltage *
63                                              Sensor::kVoltsPerLuxSecond;
64 
65 const float Sensor::kBaseGainFactor =
66     (float)Sensor::kMaxRawValue / Sensor::kSaturationElectrons;
67 
68 const float Sensor::kReadNoiseStddevBeforeGain = 1.177;  // in electrons
69 const float Sensor::kReadNoiseStddevAfterGain = 2.100;   // in digital counts
70 const float Sensor::kReadNoiseVarBeforeGain =
71     Sensor::kReadNoiseStddevBeforeGain * Sensor::kReadNoiseStddevBeforeGain;
72 const float Sensor::kReadNoiseVarAfterGain =
73     Sensor::kReadNoiseStddevAfterGain * Sensor::kReadNoiseStddevAfterGain;
74 
75 const int32_t Sensor::kSensitivityRange[2] = {100, 1600};
76 const uint32_t Sensor::kDefaultSensitivity = 100;
77 
78 /** A few utility functions for math, normal distributions */
79 
80 // Take advantage of IEEE floating-point format to calculate an approximate
81 // square root. Accurate to within +-3.6%
82 float sqrtf_approx(float r) {
83   // Modifier is based on IEEE floating-point representation; the
84   // manipulations boil down to finding approximate log2, dividing by two, and
85   // then inverting the log2. A bias is added to make the relative error
86   // symmetric about the real answer.
87   const int32_t modifier = 0x1FBB4000;
88 
89   int32_t r_i = *(int32_t *)(&r);
90   r_i = (r_i >> 1) + modifier;
91 
92   return *(float *)(&r_i);
93 }
94 
95 Sensor::Sensor(uint32_t width, uint32_t height)
96     : Thread(false),
97       mResolution{width, height},
98       mActiveArray{0, 0, width, height},
99       mRowReadoutTime(kFrameDurationRange[0] / height),
100       mGotVSync(false),
101       mExposureTime(kFrameDurationRange[0] - kMinVerticalBlank),
102       mFrameDuration(kFrameDurationRange[0]),
103       mGainFactor(kDefaultSensitivity),
104       mNextBuffers(NULL),
105       mFrameNumber(0),
106       mCapturedBuffers(NULL),
107       mListener(NULL),
108       mScene(width, height, kElectronsPerLuxSecond) {
109   ALOGV("Sensor created with pixel array %d x %d", width, height);
110 }
111 
112 Sensor::~Sensor() { shutDown(); }
113 
114 status_t Sensor::startUp() {
115   ALOGV("%s: E", __FUNCTION__);
116 
117   int res;
118   mCapturedBuffers = NULL;
119   res = run("EmulatedFakeCamera2::Sensor", ANDROID_PRIORITY_URGENT_DISPLAY);
120 
121   if (res != OK) {
122     ALOGE("Unable to start up sensor capture thread: %d", res);
123   }
124   return res;
125 }
126 
127 status_t Sensor::shutDown() {
128   ALOGV("%s: E", __FUNCTION__);
129 
130   int res;
131   res = requestExitAndWait();
132   if (res != OK) {
133     ALOGE("Unable to shut down sensor capture thread: %d", res);
134   }
135   return res;
136 }
137 
138 Scene &Sensor::getScene() { return mScene; }
139 
140 void Sensor::setExposureTime(uint64_t ns) {
141   Mutex::Autolock lock(mControlMutex);
142   ALOGVV("Exposure set to %f", ns / 1000000.f);
143   mExposureTime = ns;
144 }
145 
146 void Sensor::setFrameDuration(uint64_t ns) {
147   Mutex::Autolock lock(mControlMutex);
148   ALOGVV("Frame duration set to %f", ns / 1000000.f);
149   mFrameDuration = ns;
150 }
151 
152 void Sensor::setSensitivity(uint32_t gain) {
153   Mutex::Autolock lock(mControlMutex);
154   ALOGVV("Gain set to %d", gain);
155   mGainFactor = gain;
156 }
157 
158 void Sensor::setDestinationBuffers(Buffers *buffers) {
159   Mutex::Autolock lock(mControlMutex);
160   mNextBuffers = buffers;
161 }
162 
163 void Sensor::setFrameNumber(uint32_t frameNumber) {
164   Mutex::Autolock lock(mControlMutex);
165   mFrameNumber = frameNumber;
166 }
167 
168 bool Sensor::waitForVSync(nsecs_t reltime) {
169   int res;
170   Mutex::Autolock lock(mControlMutex);
171 
172   mGotVSync = false;
173   res = mVSync.waitRelative(mControlMutex, reltime);
174   if (res != OK && res != TIMED_OUT) {
175     ALOGE("%s: Error waiting for VSync signal: %d", __FUNCTION__, res);
176     return false;
177   }
178   return mGotVSync;
179 }
180 
181 bool Sensor::waitForNewFrame(nsecs_t reltime, nsecs_t *captureTime) {
182   Mutex::Autolock lock(mReadoutMutex);
183 
184   if (mCapturedBuffers == NULL) {
185     int res;
186     res = mReadoutAvailable.waitRelative(mReadoutMutex, reltime);
187     if (res == TIMED_OUT) {
188       return false;
189     } else if (res != OK || mCapturedBuffers == NULL) {
190       ALOGE("Error waiting for sensor readout signal: %d", res);
191       return false;
192     }
193   }
194   mReadoutComplete.signal();
195 
196   *captureTime = mCaptureTime;
197   mCapturedBuffers = NULL;
198   return true;
199 }
200 
201 Sensor::SensorListener::~SensorListener() {}
202 
203 void Sensor::setSensorListener(SensorListener *listener) {
204   Mutex::Autolock lock(mControlMutex);
205   mListener = listener;
206 }
207 
208 status_t Sensor::readyToRun() {
209   ALOGV("Starting up sensor thread");
210   mStartupTime = systemTime();
211   mNextCaptureTime = 0;
212   mNextCapturedBuffers = NULL;
213   return OK;
214 }
215 
216 bool Sensor::threadLoop() {
217   /**
218    * Sensor capture operation main loop.
219    *
220    * Stages are out-of-order relative to a single frame's processing, but
221    * in-order in time.
222    */
223 
224   /**
225    * Stage 1: Read in latest control parameters
226    */
227   uint64_t exposureDuration;
228   uint64_t frameDuration;
229   uint32_t gain;
230   Buffers *nextBuffers;
231   uint32_t frameNumber;
232   SensorListener *listener = NULL;
233   {
234     Mutex::Autolock lock(mControlMutex);
235     exposureDuration = mExposureTime;
236     frameDuration = mFrameDuration;
237     gain = mGainFactor;
238     nextBuffers = mNextBuffers;
239     frameNumber = mFrameNumber;
240     listener = mListener;
241     // Don't reuse a buffer set
242     mNextBuffers = NULL;
243 
244     // Signal VSync for start of readout
245     ALOGVV("Sensor VSync");
246     mGotVSync = true;
247     mVSync.signal();
248   }
249 
250   /**
251    * Stage 3: Read out latest captured image
252    */
253 
254   Buffers *capturedBuffers = NULL;
255   nsecs_t captureTime = 0;
256 
257   nsecs_t startRealTime = systemTime();
258   // Stagefright cares about system time for timestamps, so base simulated
259   // time on that.
260   nsecs_t simulatedTime = startRealTime;
261   nsecs_t frameEndRealTime = startRealTime + frameDuration;
262 
263   if (mNextCapturedBuffers != NULL) {
264     ALOGVV("Sensor starting readout");
265     // Pretend we're doing readout now; will signal once enough time has elapsed
266     capturedBuffers = mNextCapturedBuffers;
267     captureTime = mNextCaptureTime;
268   }
269   simulatedTime += mRowReadoutTime + kMinVerticalBlank;
270 
271   // TODO: Move this signal to another thread to simulate readout
272   // time properly
273   if (capturedBuffers != NULL) {
274     ALOGVV("Sensor readout complete");
275     Mutex::Autolock lock(mReadoutMutex);
276     if (mCapturedBuffers != NULL) {
277       ALOGV("Waiting for readout thread to catch up!");
278       mReadoutComplete.wait(mReadoutMutex);
279     }
280 
281     mCapturedBuffers = capturedBuffers;
282     mCaptureTime = captureTime;
283     mReadoutAvailable.signal();
284     capturedBuffers = NULL;
285   }
286 
287   /**
288    * Stage 2: Capture new image
289    */
290   mNextCaptureTime = simulatedTime;
291   mNextCapturedBuffers = nextBuffers;
292 
293   if (mNextCapturedBuffers != NULL) {
294     if (listener != NULL) {
295       listener->onSensorEvent(frameNumber, SensorListener::EXPOSURE_START,
296                               mNextCaptureTime);
297     }
298     ALOGVV("Starting next capture: Exposure: %f ms, gain: %d",
299            (float)exposureDuration / 1e6, gain);
300     mScene.setExposureDuration((float)exposureDuration / 1e9);
301     mScene.calculateScene(mNextCaptureTime);
302 
303     // Might be adding more buffers, so size isn't constant
304     for (size_t i = 0; i < mNextCapturedBuffers->size(); i++) {
305       const StreamBuffer &b = (*mNextCapturedBuffers)[i];
306       ALOGVV(
307           "Sensor capturing buffer %d: stream %d,"
308           " %d x %d, format %x, stride %d, buf %p, img %p",
309           i, b.streamId, b.width, b.height, b.format, b.stride, b.buffer,
310           b.img);
311       switch (b.format) {
312 #if VSOC_PLATFORM_SDK_AFTER(K)
313         case HAL_PIXEL_FORMAT_RAW16:
314           captureRaw(b.img, gain, b.stride);
315           break;
316 #endif
317         case HAL_PIXEL_FORMAT_RGB_888:
318           captureRGB(b.img, gain, b.stride);
319           break;
320         case HAL_PIXEL_FORMAT_RGBA_8888:
321           captureRGBA(b.img, gain, b.stride);
322           break;
323         case HAL_PIXEL_FORMAT_BLOB:
324 #if defined HAL_DATASPACE_DEPTH
325           if (b.dataSpace != HAL_DATASPACE_DEPTH) {
326 #endif
327             // Add auxillary buffer of the right size
328             // Assumes only one BLOB (JPEG) buffer in
329             // mNextCapturedBuffers
330             StreamBuffer bAux;
331             bAux.streamId = 0;
332             bAux.width = b.width;
333             bAux.height = b.height;
334             bAux.format = HAL_PIXEL_FORMAT_RGB_888;
335             bAux.stride = b.width;
336             bAux.buffer = NULL;
337             // TODO: Reuse these
338             bAux.img = new uint8_t[b.width * b.height * 3];
339             mNextCapturedBuffers->push_back(bAux);
340 #if defined HAL_DATASPACE_DEPTH
341           } else {
342             captureDepthCloud(b.img);
343           }
344 #endif
345           break;
346         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
347         case HAL_PIXEL_FORMAT_YCbCr_420_888:
348           captureNV21(b.img, gain, b.stride);
349           break;
350         case HAL_PIXEL_FORMAT_YV12:
351           // TODO:
352           ALOGE("%s: Format %x is TODO", __FUNCTION__, b.format);
353           break;
354         case HAL_PIXEL_FORMAT_Y16:
355           captureDepth(b.img, gain, b.stride);
356           break;
357         default:
358           ALOGE("%s: Unknown format %x, no output", __FUNCTION__, b.format);
359           break;
360       }
361     }
362   }
363 
364   ALOGVV("Sensor vertical blanking interval");
365   nsecs_t workDoneRealTime = systemTime();
366   const nsecs_t timeAccuracy = 2e6;  // 2 ms of imprecision is ok
367   if (workDoneRealTime < frameEndRealTime - timeAccuracy) {
368     timespec t;
369     t.tv_sec = (frameEndRealTime - workDoneRealTime) / 1000000000L;
370     t.tv_nsec = (frameEndRealTime - workDoneRealTime) % 1000000000L;
371 
372     int ret;
373     do {
374       ret = nanosleep(&t, &t);
375     } while (ret != 0);
376   }
377   nsecs_t endRealTime __unused = systemTime();
378   ALOGVV("Frame cycle took %d ms, target %d ms",
379          (int)((endRealTime - startRealTime) / 1000000),
380          (int)(frameDuration / 1000000));
381   return true;
382 };
383 
384 void Sensor::captureRaw(uint8_t *img, uint32_t gain, uint32_t stride) {
385   float totalGain = gain / 100.0 * kBaseGainFactor;
386   float noiseVarGain = totalGain * totalGain;
387   float readNoiseVar =
388       kReadNoiseVarBeforeGain * noiseVarGain + kReadNoiseVarAfterGain;
389 
390   int bayerSelect[4] = {Scene::R, Scene::Gr, Scene::Gb, Scene::B};  // RGGB
391   mScene.setReadoutPixel(0, 0);
392   for (unsigned int y = 0; y < mResolution[1]; y++) {
393     int *bayerRow = bayerSelect + (y & 0x1) * 2;
394     uint16_t *px = (uint16_t *)img + y * stride;
395     for (unsigned int x = 0; x < mResolution[0]; x++) {
396       uint32_t electronCount;
397       electronCount = mScene.getPixelElectrons()[bayerRow[x & 0x1]];
398 
399       // TODO: Better pixel saturation curve?
400       electronCount = (electronCount < kSaturationElectrons)
401                           ? electronCount
402                           : kSaturationElectrons;
403 
404       // TODO: Better A/D saturation curve?
405       uint16_t rawCount = electronCount * totalGain;
406       rawCount = (rawCount < kMaxRawValue) ? rawCount : kMaxRawValue;
407 
408       // Calculate noise value
409       // TODO: Use more-correct Gaussian instead of uniform noise
410       float photonNoiseVar = electronCount * noiseVarGain;
411       float noiseStddev = sqrtf_approx(readNoiseVar + photonNoiseVar);
412       // Scaled to roughly match gaussian/uniform noise stddev
413       float noiseSample = std::rand() * (2.5 / (1.0 + RAND_MAX)) - 1.25;
414 
415       rawCount += kBlackLevel;
416       rawCount += noiseStddev * noiseSample;
417 
418       *px++ = rawCount;
419     }
420     // TODO: Handle this better
421     // simulatedTime += mRowReadoutTime;
422   }
423   ALOGVV("Raw sensor image captured");
424 }
425 
426 void Sensor::captureRGBA(uint8_t *img, uint32_t gain, uint32_t stride) {
427   float totalGain = gain / 100.0 * kBaseGainFactor;
428   // In fixed-point math, calculate total scaling from electrons to 8bpp
429   int scale64x = 64 * totalGain * 255 / kMaxRawValue;
430   uint32_t inc = ceil((float)mResolution[0] / stride);
431 
432   for (unsigned int y = 0, outY = 0; y < mResolution[1]; y += inc, outY++) {
433     uint8_t *px = img + outY * stride * 4;
434     mScene.setReadoutPixel(0, y);
435     for (unsigned int x = 0; x < mResolution[0]; x += inc) {
436       uint32_t rCount, gCount, bCount;
437       // TODO: Perfect demosaicing is a cheat
438       const uint32_t *pixel = mScene.getPixelElectrons();
439       rCount = pixel[Scene::R] * scale64x;
440       gCount = pixel[Scene::Gr] * scale64x;
441       bCount = pixel[Scene::B] * scale64x;
442 
443       *px++ = rCount < 255 * 64 ? rCount / 64 : 255;
444       *px++ = gCount < 255 * 64 ? gCount / 64 : 255;
445       *px++ = bCount < 255 * 64 ? bCount / 64 : 255;
446       *px++ = 255;
447       for (unsigned int j = 1; j < inc; j++) mScene.getPixelElectrons();
448     }
449     // TODO: Handle this better
450     // simulatedTime += mRowReadoutTime;
451   }
452   ALOGVV("RGBA sensor image captured");
453 }
454 
455 void Sensor::captureRGB(uint8_t *img, uint32_t gain, uint32_t stride) {
456   float totalGain = gain / 100.0 * kBaseGainFactor;
457   // In fixed-point math, calculate total scaling from electrons to 8bpp
458   int scale64x = 64 * totalGain * 255 / kMaxRawValue;
459   uint32_t inc = ceil((float)mResolution[0] / stride);
460 
461   for (unsigned int y = 0, outY = 0; y < mResolution[1]; y += inc, outY++) {
462     mScene.setReadoutPixel(0, y);
463     uint8_t *px = img + outY * stride * 3;
464     for (unsigned int x = 0; x < mResolution[0]; x += inc) {
465       uint32_t rCount, gCount, bCount;
466       // TODO: Perfect demosaicing is a cheat
467       const uint32_t *pixel = mScene.getPixelElectrons();
468       rCount = pixel[Scene::R] * scale64x;
469       gCount = pixel[Scene::Gr] * scale64x;
470       bCount = pixel[Scene::B] * scale64x;
471 
472       *px++ = rCount < 255 * 64 ? rCount / 64 : 255;
473       *px++ = gCount < 255 * 64 ? gCount / 64 : 255;
474       *px++ = bCount < 255 * 64 ? bCount / 64 : 255;
475       for (unsigned int j = 1; j < inc; j++) mScene.getPixelElectrons();
476     }
477     // TODO: Handle this better
478     // simulatedTime += mRowReadoutTime;
479   }
480   ALOGVV("RGB sensor image captured");
481 }
482 
483 void Sensor::captureNV21(uint8_t *img, uint32_t gain, uint32_t stride) {
484   float totalGain = gain / 100.0 * kBaseGainFactor;
485   // Using fixed-point math with 6 bits of fractional precision.
486   // In fixed-point math, calculate total scaling from electrons to 8bpp
487   const int scale64x = 64 * totalGain * 255 / kMaxRawValue;
488   // In fixed-point math, saturation point of sensor after gain
489   const int saturationPoint = 64 * 255;
490   // Fixed-point coefficients for RGB-YUV transform
491   // Based on JFIF RGB->YUV transform.
492   // Cb/Cr offset scaled by 64x twice since they're applied post-multiply
493   const int rgbToY[] = {19, 37, 7};
494   const int rgbToCb[] = {-10, -21, 32, 524288};
495   const int rgbToCr[] = {32, -26, -5, 524288};
496   // Scale back to 8bpp non-fixed-point
497   const int scaleOut = 64;
498   const int scaleOutSq = scaleOut * scaleOut;  // after multiplies
499 
500   // inc = how many pixels to skip while reading every next pixel
501   // horizontally.
502   uint32_t inc = ceil((float)mResolution[0] / stride);
503   // outH = projected vertical resolution based on stride.
504   uint32_t outH = mResolution[1] / inc;
505   for (unsigned int y = 0, outY = 0; y < mResolution[1]; y += inc, outY++) {
506     uint8_t *pxY = img + outY * stride;
507     uint8_t *pxVU = img + (outH + outY / 2) * stride;
508     mScene.setReadoutPixel(0, y);
509     for (unsigned int outX = 0; outX < stride; outX++) {
510       int32_t rCount, gCount, bCount;
511       // TODO: Perfect demosaicing is a cheat
512       const uint32_t *pixel = mScene.getPixelElectrons();
513       rCount = pixel[Scene::R] * scale64x;
514       rCount = rCount < saturationPoint ? rCount : saturationPoint;
515       gCount = pixel[Scene::Gr] * scale64x;
516       gCount = gCount < saturationPoint ? gCount : saturationPoint;
517       bCount = pixel[Scene::B] * scale64x;
518       bCount = bCount < saturationPoint ? bCount : saturationPoint;
519 
520       *pxY++ = (rgbToY[0] * rCount + rgbToY[1] * gCount + rgbToY[2] * bCount) /
521                scaleOutSq;
522       if (outY % 2 == 0 && outX % 2 == 0) {
523         *pxVU++ = (rgbToCb[0] * rCount + rgbToCb[1] * gCount +
524                    rgbToCb[2] * bCount + rgbToCb[3]) /
525                   scaleOutSq;
526         *pxVU++ = (rgbToCr[0] * rCount + rgbToCr[1] * gCount +
527                    rgbToCr[2] * bCount + rgbToCr[3]) /
528                   scaleOutSq;
529       }
530 
531       // Skip unprocessed pixels from sensor.
532       for (unsigned int j = 1; j < inc; j++) mScene.getPixelElectrons();
533     }
534   }
535   ALOGVV("NV21 sensor image captured");
536 }
537 
538 void Sensor::captureDepth(uint8_t *img, uint32_t gain, uint32_t stride) {
539   float totalGain = gain / 100.0 * kBaseGainFactor;
540   // In fixed-point math, calculate scaling factor to 13bpp millimeters
541   int scale64x = 64 * totalGain * 8191 / kMaxRawValue;
542   uint32_t inc = ceil((float)mResolution[0] / stride);
543 
544   for (unsigned int y = 0, outY = 0; y < mResolution[1]; y += inc, outY++) {
545     mScene.setReadoutPixel(0, y);
546     uint16_t *px = ((uint16_t *)img) + outY * stride;
547     for (unsigned int x = 0; x < mResolution[0]; x += inc) {
548       uint32_t depthCount;
549       // TODO: Make up real depth scene instead of using green channel
550       // as depth
551       const uint32_t *pixel = mScene.getPixelElectrons();
552       depthCount = pixel[Scene::Gr] * scale64x;
553 
554       *px++ = depthCount < 8191 * 64 ? depthCount / 64 : 0;
555       for (unsigned int j = 1; j < inc; j++) mScene.getPixelElectrons();
556     }
557     // TODO: Handle this better
558     // simulatedTime += mRowReadoutTime;
559   }
560   ALOGVV("Depth sensor image captured");
561 }
562 
563 void Sensor::captureDepthCloud(uint8_t * /*img*/) {
564 #if defined HAL_DATASPACE_DEPTH
565   android_depth_points *cloud = reinterpret_cast<android_depth_points *>(img);
566 
567   cloud->num_points = 16;
568 
569   // TODO: Create point cloud values that match RGB scene
570   const int FLOATS_PER_POINT = 4;
571   const float JITTER_STDDEV = 0.1f;
572   for (size_t y = 0, i = 0; y < 4; y++) {
573     for (size_t x = 0; x < 4; x++, i++) {
574       float randSampleX = std::rand() * (2.5f / (1.0f + RAND_MAX)) - 1.25f;
575       randSampleX *= JITTER_STDDEV;
576 
577       float randSampleY = std::rand() * (2.5f / (1.0f + RAND_MAX)) - 1.25f;
578       randSampleY *= JITTER_STDDEV;
579 
580       float randSampleZ = std::rand() * (2.5f / (1.0f + RAND_MAX)) - 1.25f;
581       randSampleZ *= JITTER_STDDEV;
582 
583       cloud->xyzc_points[i * FLOATS_PER_POINT + 0] = x - 1.5f + randSampleX;
584       cloud->xyzc_points[i * FLOATS_PER_POINT + 1] = y - 1.5f + randSampleY;
585       cloud->xyzc_points[i * FLOATS_PER_POINT + 2] = 3.f + randSampleZ;
586       cloud->xyzc_points[i * FLOATS_PER_POINT + 3] = 0.8f;
587     }
588   }
589 
590   ALOGVV("Depth point cloud captured");
591 #endif
592 }
593 
594 }  // namespace android
595