omx cam: do not select sensor for stereo mode
[glsdk/omapdrmtest.git] / omx_cam / VisionCamSimpleTest.cpp
1 /** Copyright (C) 2010 Texas Instruments, Inc. All rights reserved */
3 /** This is a simple, dumbed down version of the vcam_test which only uses
4     command line paramters and simple settings in order to test out system
5     connectivity, this is *not* intended to replace the more complicated
6     VisionCamTest.cpp. Use export VCAM_SIMPLE=1 to use this version.
7 */
9 #include <limits.h>
11 #include <autolock.h>
12 #include <output.h>
14 #include <OMXVisionCam.h>
16 /** The default number of display buffers */
17 #define DISPLAY_NUM_BUFFERS (5)
19 #define STATUS_FAILED(x)    (x < 0)
21 #define CAMERA_NAME MODULE_NAME("vcam")
23 typedef enum _option_type_e {
24     OPTION_TYPE_BOOL,
25     OPTION_TYPE_INT,
26     OPTION_TYPE_HEX,
27     OPTION_TYPE_FLOAT,
28     OPTION_TYPE_STRING,
29 } option_type_e;
31 typedef struct _option_t {
32     option_type_e type;
33     void *datum;
34     size_t size;
35     const char *short_switch;
36     const char *long_switch;
37     const char *description;
38 } option_t;
40 size_t option_process(int argc, char *argv[], option_t *opts, size_t numOpts)
41 {
42     int i;
43     size_t j,c = 0;
44     for (i = 0; i < argc; i++)
45     {
46         for (j = 0; j < numOpts; j++)
47         {
48             if ((opts[j].short_switch && strcmp(opts[j].short_switch, argv[i]) == 0) ||
49                 (opts[j].long_switch && strcmp(opts[j].long_switch, argv[i]) == 0))
50             {
51                 switch (opts[j].type)
52                 {
53                     case OPTION_TYPE_BOOL:
54                         *(bool *)opts[j].datum = true;
55                         c++;
56                         break;
57                     case OPTION_TYPE_INT:
58                         if (i+1 < argc && opts[j].size == sizeof(int)) {
59                             i += 1;
60                             sscanf(argv[i],"%d",(int *)opts[j].datum);
61                             c++;
62                         }
63                         break;
64                     case OPTION_TYPE_HEX:
65                         if (i+1 < argc && opts[j].size == sizeof(uint32_t)) {
66                             i += 1;
67                             sscanf(argv[i],"%x",(uint32_t *)opts[j].datum);
68                             c++;
69                         }
70                         break;
71                     case OPTION_TYPE_FLOAT:
72                         if (i+1 < argc && opts[j].size == sizeof(float)) {
73                             i += 1;
74                             sscanf(argv[i],"%f",(float *)opts[j].datum);
75                             c++;
76                         }
77                         break;
78                     case OPTION_TYPE_STRING:
79                         if (i+1 < argc) {
80                             i += 1;
81                             strncpy(static_cast<char*>(opts[j].datum), argv[i], opts[j].size);
82                             c++;
83                         }
84                         break;
85                 }
86                 break; // process next argv
87             }
88         }
89     }
90     return c;
91 }
93 int32_t display_width;
94 int32_t display_height;
95 int32_t width;
96 int32_t height;
97 int32_t fps;
98 uint32_t color;
99 char fourcc_str[5];
100 int32_t numImages;
101 int32_t recvFrames;
102 int32_t numFrames;
103 int32_t sensor;
104 int32_t frameLock;
105 int32_t focusDepth;
106 int32_t mode;
107 int32_t camera_rotation;
108 uint32_t screen_rotation;
109 uint32_t dw,sw;
110 uint32_t dh,sh;
111 int32_t subsample;
112 bool twoD;
113 bool topBottom;
114 bool file_ouput;
115 char name[PATH_MAX];
116 uint32_t numTimeouts;
117 uint32_t white;
118 uint32_t brightness;
119 uint32_t iso;
120 uint32_t exposure;
121 bool manual;
122 uint32_t repeats;
123 option_t opts[] = {
124     {OPTION_TYPE_INT, &display_width, sizeof(display_width), "-dw",  "--display_width", "Width of display"},
125     {OPTION_TYPE_INT, &display_height, sizeof(display_height), "-dh",  "--display_height", "Height of display"},
126     {OPTION_TYPE_INT, &width, sizeof(width),              "-w",  "--width", "Width of image"},
127     {OPTION_TYPE_INT, &height, sizeof(height),            "-h",  "--height", "Height of image"},
128     {OPTION_TYPE_INT, &fps, sizeof(fps),                  "-f",  "--fps", "Frame Rate"},
129     {OPTION_TYPE_BOOL, &twoD, sizeof(twoD),               "-2d", "--two-d", "Use 2D buffers"},
130     {OPTION_TYPE_BOOL, &topBottom, sizeof(topBottom),     "-tb", "--topbottom", "Orient the stereo image as top/bottom"},
131     {OPTION_TYPE_STRING, &fourcc_str, sizeof(fourcc_str), "-c",  "--fourcc", "FOURCC Code as string (UYVY) "},
132     {OPTION_TYPE_STRING, name, sizeof(name),              "-n",  "--name", "Name of file to read"},
133     {OPTION_TYPE_INT, &numImages, sizeof(numImages),      "-i",  "--images", "Number of images to use"},
134     {OPTION_TYPE_INT, &numFrames, sizeof(numFrames),      "-#",  "--frames", "Number of frames to process"},
135     {OPTION_TYPE_INT, &sensor, sizeof(sensor),            "-s",  "--sensor", "Selects the sensor (0,1,2)"},
136     {OPTION_TYPE_INT, &frameLock, sizeof(frameLock),      "-l",  "--lock-after", "Locks AE/AWB after specified frame count"},
137     {OPTION_TYPE_INT, &focusDepth, sizeof(focusDepth),    "-fd", "--focus-depth", "Specific Focus Depth [0-150]"},
138     {OPTION_TYPE_INT, &mode, sizeof(mode),                "-p",  "--mode", "Capture Mode"},
139     {OPTION_TYPE_INT, &camera_rotation, sizeof(camera_rotation),"-cr", "--camera_rotation", "Rotates the captured image in the camera"},
140     {OPTION_TYPE_INT, &screen_rotation, sizeof(screen_rotation),"-sr", "--screen_rotation", "Rotates the display image"},
141     {OPTION_TYPE_INT, &subsample, sizeof(subsample),      "-sb", "--subsample", "Subsampled ratio, defaults to 1"},
142     {OPTION_TYPE_BOOL, &file_ouput, sizeof(file_ouput),   "-o",  "--out", "Write to file instead of display"},
143     {OPTION_TYPE_BOOL, &manual, sizeof(manual),           "-m",  "--manual", "Use manual settings"},
144     {OPTION_TYPE_INT, &white, sizeof(white),              "-wb", "--white", "White Balance Mode"},
145     {OPTION_TYPE_INT, &brightness, sizeof(brightness),    "-br", "--bright", "Brightness Value"},
146     {OPTION_TYPE_INT, &iso, sizeof(iso),                  "-is", "--iso", "ISO Value"},
147     {OPTION_TYPE_INT, &exposure, sizeof(exposure),        "-ex", "--exposure", "Manual Exposure Value"},
148     {OPTION_TYPE_INT, &numTimeouts, sizeof(numTimeouts),  "-to", "--timeouts", "Set the number of frame timeout which can occur before the camera halts"},
149     {OPTION_TYPE_INT, &repeats, sizeof(repeats),          "-r",  "--repeat", "Sets the number of repeat iterations, default is 1."},
150 };
152 struct CallbackData {
153   pthread_mutex_t            mutex;
154   std::list<VisionCamFrame*> frames;
155   CallbackData() {
156     pthread_mutex_init(&mutex, NULL);
157   }
158   ~CallbackData() {
159     pthread_mutex_destroy(&mutex);
160   }
161 };
163 void VisionCamTestCallback(VisionCamFrame* frame) {
164   CallbackData* cb_data = static_cast<CallbackData*>(frame->mCookie);
166   MSG("New frame received; offset=%ux%u", frame->mOffsetX, frame->mOffsetY);
167   AutoLock(&cb_data->mutex);
168   cb_data->frames.push_back(frame);
171 int main(int argc, char *argv[]) {
172   uint32_t r = 0;
173   int32_t i = 0;
174   VisionCamSensorSelection sensorIndex = VCAM_SENSOR_SECONDARY;
175   VisionCamCaptureMode capmode = VCAM_VIDEO_NORMAL;
176   VisionCamFlickerType flicker = FLICKER_60Hz;
177   VisionCamFocusMode focus = VCAM_FOCUS_CONTROL_AUTO;
178   VisionCamStereoInfo info;
180   // default values
181   white = VCAM_WHITE_BAL_CONTROL_AUTO;
182   brightness = 50; // [0-200]
183   iso = 100;       // [100-1600]
184   exposure = 50;   // [0-100]
185   manual = false;
186   recvFrames = 0;
187   display_width = 640;
188   display_height = 480;
189   width = 640;
190   height = 480;
191   fps = 30;
192   strcpy(fourcc_str, "NV12");
193   color = FOURCC_STR(fourcc_str);
194   strcpy(name, "car");
195   numImages = DISPLAY_NUM_BUFFERS;
196   sensor = OMX_TI_StereoSensor;
197   numFrames = 100;
198   frameLock = 0xFFFFFFFF;
199   focusDepth = -1;
200   mode = VCAM_VIDEO_NORMAL;
201   camera_rotation = 0;
202   screen_rotation = 0;
203   dw = 0;
204   dh = 0;
205   sw = 0;
206   sh = 0;
207   twoD = false;
208   topBottom = false;
209   subsample = 1;
210   file_ouput = false;
211   numTimeouts = 10;
212   repeats = 1;
214   option_process(argc, argv, opts, sizeof(opts)/sizeof(opts[0]));
216   // check for bad input
217   if (width <= 0) width = 160;
218   if (height <= 0) height = 120;
219   if (sw <= 0) sw = width;
220   if (sh <= 0) sh = height;
221   if (numImages <= 2) numImages = 2;
222   if (fps <= 15) fps = 15;
223   if (numFrames <= 10) numFrames = 10;
224   if (frameLock > numFrames) frameLock = -1;
225   if (focusDepth > 150) focusDepth = 75;
226   if (mode >= VCAM_CAP_MODE_MAX) mode = VCAM_GESTURE_MODE;
227   if (sensor > 2) sensor = 2;
228   if (camera_rotation != 0 && camera_rotation != 90 && camera_rotation != 180 && camera_rotation != 270)
229       camera_rotation = 0;
230   else if (camera_rotation == 90 || camera_rotation == 270)
231   {
232       uint32_t t = sw;
233       sw = sh;
234       sh = t;
235   }
236   if (subsample <= 0 || subsample > 4)
237       subsample = 1;
238   if (brightness > 200)
239       brightness = 200;
240   if (iso < 100) iso = 100;
241   if (iso > 1600) iso = 1600;
242   if (exposure > 100) exposure = 100;
243   if (repeats == 0)
244       repeats = 1;
246   color = FOURCC_STR(fourcc_str);
248   MSG("Requested Color %08x", color);
250   switch (sensor)
251   {
252     case 2:
253       sensorIndex = VCAM_SENSOR_STEREO;
254       mode = VCAM_STEREO_MODE;
255       memset(&info, 0, sizeof(info));
256       if (topBottom) {
257         MSG("Enabling Stereo Use Case (top/bottom)!");
258         info.layout = VCAM_STEREO_LAYOUT_TOPBOTTOM;
259         height *= 2;
260       } else {
261         MSG("Enabling Stereo Use Case (side by side)!");
262         info.layout = VCAM_STEREO_LAYOUT_LEFTRIGHT;
263         width *= 2;
264       }
265       info.subsampling = subsample;
266       if (color != FOURCC('N','V','1','2')) {
267         ERROR("Only NV12 is supported for stereo");
268         exit(1);
269       }
270       break;
271     case 1:
272       MSG("Enabling Vision Mode on Front Camera");
273       sensorIndex = VCAM_SENSOR_SECONDARY;
274       mode = VCAM_VIDEO_NORMAL;
275       break;
276     default:
277       MSG("Enabling Vision Mode on Back Camera!");
278       sensorIndex = VCAM_SENSOR_PRIMARY;
279   }
280   capmode = (VisionCamCaptureMode)mode;
282   // using 1 to <= so prints will make sense
283   for (r = 1; r <= repeats; r++)
284   {
285     MSG("Iteration %u of %u", r, repeats);
286     recvFrames = 0;
287     OMXVisionCam omx_cam;
288     VisionCam *pCam = &omx_cam;
289     int greError = 0;
291     CallbackData cb_data;
292     VCAM_RETURN_IF_FAILED(greError, pCam->init(&cb_data));
293     VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_WIDTH, &width, sizeof(width)));
294     VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_HEIGHT, &height, sizeof(height)));
295     VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_COLOR_SPACE_FOURCC, &color, sizeof(color)));
296     // Can't set ROTATION here, see below
297     VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_FPS_FIXED, &fps, sizeof(fps)));
298     VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_CAP_MODE, &capmode, sizeof(capmode)));
299     if ((sensorIndex >= 0) && (sensorIndex <= 1))
300     {
301         VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_SENSOR_SELECT, &sensorIndex, sizeof(sensorIndex)));
302     }
303     if (capmode == VCAM_STEREO_MODE)
304     {
305         VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_STEREO_INFO, &info, sizeof(info)));
306     }
308     // VCAM_PARAM_2DBUFFER_DIM should only be called after resolutions, color space, cap mode, and
309     //   optionally stereo information is set.
310     VisionCamResType res = { VCAM_RESOL_MAX, width, height };
311     VCAM_COMPLAIN_IF_FAILED(greError, pCam->getParameter(VCAM_PARAM_2DBUFFER_DIM, &res, sizeof(res)));
312     MSG("Image: %ux%u, buffer: %ux%u", width, height, res.mWidth, res.mHeight);
314     Output* output = new Output(display_width, display_height, width, height,
315         res.mWidth, res.mHeight, color, numImages, twoD, file_ouput);
316     if (output->open() == 0)
317     {
318         VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_FLICKER, &flicker, sizeof(flicker)));
319         VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_AWB_MODE, &white, sizeof(white)));
320         if (manual)
321         {
322             VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_BRIGHTNESS, &brightness, sizeof(brightness)));
323             VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_EXPOSURE_ISO, &iso, sizeof(iso)));
324             VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_MANUAL_EXPOSURE, &exposure, sizeof(exposure)));
325         }
326         VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_NAME, name, sizeof(name)));
328         struct buffer* images[numImages];
329         BufferMeta meta[numImages];
330         for (i = 0; i < numImages; i++)
331         {
332             images[i] = output->alloc(&meta[i]);
333         }
334         // tell the camera to use all the camera index buffers
335         VCAM_COMPLAIN_IF_FAILED(greError, pCam->useBuffers(meta, numImages));
337         /** @todo Since the OMX Camera is probably being used by
338             the VCAM_SIMPLE test, we have to understand that
339             the OMX-CAMERA has a bug in the camera_rotation when used
340             during LOADED state. We have to wait until IDLE
341             (post useBuffers) or EXECUTING (post PREVIEW)
342             before rotating. */
343         /** @todo Additionally, OMX-CAMERA STEREO mode can't handle the rotation values! */
344         if (capmode != VCAM_STEREO_MODE)
345             VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_ROTATION, &camera_rotation, sizeof(camera_rotation)));
347         // register the engine callback with the camera
348         VCAM_COMPLAIN_IF_FAILED(greError,  pCam->enablePreviewCbk(VisionCamTestCallback));
349         VCAM_COMPLAIN_IF_FAILED(greError,  pCam->sendCommand(VCAM_CMD_PREVIEW_START));
351         if (focusDepth == -1) { // begin auto-focus
352             VCAM_COMPLAIN_IF_FAILED(greError,  pCam->setParameter(VCAM_PARAM_DO_AUTOFOCUS, &focus, sizeof(focus)));
353         }
355         if (greError == 0)
356         {
357             uint32_t timeouts = 0;
358             usleep(1000000/fps); // wait 1 frame period.
359             MSG("VisionCam is initialized, entering queue read loop!");
360             // read from the queue and display the images
361             do {
362               if (cb_data.frames.empty()) {
363                 ERROR("Timedout waiting for buffer from Camera!");
364                 timeouts++;
365                 usleep(1000000/fps);
366                 continue;
367               }
368               VisionCamFrame* frame;
369               {
370                 AutoLock(&cb_data.mutex);
371                 frame = cb_data.frames.front();
372                 cb_data.frames.pop_front();
373               }
374               if (frame != NULL) {
375                 BufferMeta* meta = static_cast<BufferMeta*>(frame->mFrameBuff);
376                 timeouts = 0;
377                 output->render(meta);
378                 pCam->returnFrame(frame);
379                 recvFrames++;
380                 if (recvFrames >= numFrames) {
381                   break;
382                 }
383                 if (focusDepth >= 0) {
384                   if (recvFrames == fps) { // after 1 second
385                       VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_DO_MANUALFOCUS, &focusDepth, sizeof(focusDepth)));
386                   }
387                 }
388                 if (frameLock > 0) {
389                   if (recvFrames == frameLock) {
390                       bool lock = true;
391                       VCAM_COMPLAIN_IF_FAILED(greError, pCam->sendCommand(VCAM_CMD_LOCK_AE, &lock, sizeof(lock)));
392                       VCAM_COMPLAIN_IF_FAILED(greError, pCam->sendCommand(VCAM_CMD_LOCK_AWB, &lock, sizeof(lock)));
393                   }
394                 }
395               }
396             } while (timeouts < numTimeouts);
397         }
398         else
399         {
400             ERROR("VCAM_TEST Failed during initialization (greError = %d, 0x%08x)!", greError, greError);
401         }
403         // destroy the camera
404         VCAM_COMPLAIN_IF_FAILED(greError, pCam->sendCommand(VCAM_CMD_PREVIEW_STOP));
405         VCAM_COMPLAIN_IF_FAILED(greError, pCam->disablePreviewCbk(VisionCamTestCallback));
406         VCAM_COMPLAIN_IF_FAILED(greError, pCam->releaseBuffers());
407         VCAM_COMPLAIN_IF_FAILED(greError, pCam->deinit());
409         // free the images
410         for (i = 0; i < numImages; i++){
411             output->free(&meta[i]);
412         }
414         output->close();
415         delete output;
416     }
417   }
418   return 0;