]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/omapdrmtest.git/blobdiff - omx_cam/VisionCamSimpleTest.cpp
omx cam: add test app
[glsdk/omapdrmtest.git] / omx_cam / VisionCamSimpleTest.cpp
diff --git a/omx_cam/VisionCamSimpleTest.cpp b/omx_cam/VisionCamSimpleTest.cpp
new file mode 100644 (file)
index 0000000..db556d6
--- /dev/null
@@ -0,0 +1,416 @@
+/** Copyright (C) 2010 Texas Instruments, Inc. All rights reserved */
+
+/** This is a simple, dumbed down version of the vcam_test which only uses
+    command line paramters and simple settings in order to test out system
+    connectivity, this is *not* intended to replace the more complicated
+    VisionCamTest.cpp. Use export VCAM_SIMPLE=1 to use this version.
+*/
+
+#include <limits.h>
+
+#include <autolock.h>
+#include <output.h>
+
+#include <OMXVisionCam.h>
+
+/** The default number of display buffers */
+#define DISPLAY_NUM_BUFFERS (5)
+
+#define STATUS_FAILED(x)    (x < 0)
+
+#define CAMERA_NAME MODULE_NAME("vcam")
+
+typedef enum _option_type_e {
+    OPTION_TYPE_BOOL,
+    OPTION_TYPE_INT,
+    OPTION_TYPE_HEX,
+    OPTION_TYPE_FLOAT,
+    OPTION_TYPE_STRING,
+} option_type_e;
+
+typedef struct _option_t {
+    option_type_e type;
+    void *datum;
+    size_t size;
+    const char *short_switch;
+    const char *long_switch;
+    const char *description;
+} option_t;
+
+size_t option_process(int argc, char *argv[], option_t *opts, size_t numOpts)
+{
+    int i;
+    size_t j,c = 0;
+    for (i = 0; i < argc; i++)
+    {
+        for (j = 0; j < numOpts; j++)
+        {
+            if ((opts[j].short_switch && strcmp(opts[j].short_switch, argv[i]) == 0) ||
+                (opts[j].long_switch && strcmp(opts[j].long_switch, argv[i]) == 0))
+            {
+                switch (opts[j].type)
+                {
+                    case OPTION_TYPE_BOOL:
+                        *(bool *)opts[j].datum = true;
+                        c++;
+                        break;
+                    case OPTION_TYPE_INT:
+                        if (i+1 < argc && opts[j].size == sizeof(int)) {
+                            i += 1;
+                            sscanf(argv[i],"%d",(int *)opts[j].datum);
+                            c++;
+                        }
+                        break;
+                    case OPTION_TYPE_HEX:
+                        if (i+1 < argc && opts[j].size == sizeof(uint32_t)) {
+                            i += 1;
+                            sscanf(argv[i],"%x",(uint32_t *)opts[j].datum);
+                            c++;
+                        }
+                        break;
+                    case OPTION_TYPE_FLOAT:
+                        if (i+1 < argc && opts[j].size == sizeof(float)) {
+                            i += 1;
+                            sscanf(argv[i],"%f",(float *)opts[j].datum);
+                            c++;
+                        }
+                        break;
+                    case OPTION_TYPE_STRING:
+                        if (i+1 < argc) {
+                            i += 1;
+                            strncpy(static_cast<char*>(opts[j].datum), argv[i], opts[j].size);
+                            c++;
+                        }
+                        break;
+                }
+                break; // process next argv
+            }
+        }
+    }
+    return c;
+}
+
+int32_t display_width;
+int32_t display_height;
+int32_t width;
+int32_t height;
+int32_t fps;
+uint32_t color;
+char fourcc_str[5];
+int32_t numImages;
+int32_t recvFrames;
+int32_t numFrames;
+int32_t sensor;
+int32_t frameLock;
+int32_t focusDepth;
+int32_t mode;
+int32_t camera_rotation;
+uint32_t screen_rotation;
+uint32_t dw,sw;
+uint32_t dh,sh;
+int32_t subsample;
+bool twoD;
+bool topBottom;
+bool file_ouput;
+char name[PATH_MAX];
+uint32_t numTimeouts;
+uint32_t white;
+uint32_t brightness;
+uint32_t iso;
+uint32_t exposure;
+bool manual;
+uint32_t repeats;
+option_t opts[] = {
+    {OPTION_TYPE_INT, &display_width, sizeof(display_width), "-dw",  "--display_width", "Width of display"},
+    {OPTION_TYPE_INT, &display_height, sizeof(display_height), "-dh",  "--display_height", "Height of display"},
+    {OPTION_TYPE_INT, &width, sizeof(width),              "-w",  "--width", "Width of image"},
+    {OPTION_TYPE_INT, &height, sizeof(height),            "-h",  "--height", "Height of image"},
+    {OPTION_TYPE_INT, &fps, sizeof(fps),                  "-f",  "--fps", "Frame Rate"},
+    {OPTION_TYPE_BOOL, &twoD, sizeof(twoD),               "-2d", "--two-d", "Use 2D buffers"},
+    {OPTION_TYPE_BOOL, &topBottom, sizeof(topBottom),     "-tb", "--topbottom", "Orient the stereo image as top/bottom"},
+    {OPTION_TYPE_STRING, &fourcc_str, sizeof(fourcc_str), "-c",  "--fourcc", "FOURCC Code as string (UYVY) "},
+    {OPTION_TYPE_STRING, name, sizeof(name),              "-n",  "--name", "Name of file to read"},
+    {OPTION_TYPE_INT, &numImages, sizeof(numImages),      "-i",  "--images", "Number of images to use"},
+    {OPTION_TYPE_INT, &numFrames, sizeof(numFrames),      "-#",  "--frames", "Number of frames to process"},
+    {OPTION_TYPE_INT, &sensor, sizeof(sensor),            "-s",  "--sensor", "Selects the sensor (0,1,2)"},
+    {OPTION_TYPE_INT, &frameLock, sizeof(frameLock),      "-l",  "--lock-after", "Locks AE/AWB after specified frame count"},
+    {OPTION_TYPE_INT, &focusDepth, sizeof(focusDepth),    "-fd", "--focus-depth", "Specific Focus Depth [0-150]"},
+    {OPTION_TYPE_INT, &mode, sizeof(mode),                "-p",  "--mode", "Capture Mode"},
+    {OPTION_TYPE_INT, &camera_rotation, sizeof(camera_rotation),"-cr", "--camera_rotation", "Rotates the captured image in the camera"},
+    {OPTION_TYPE_INT, &screen_rotation, sizeof(screen_rotation),"-sr", "--screen_rotation", "Rotates the display image"},
+    {OPTION_TYPE_INT, &subsample, sizeof(subsample),      "-sb", "--subsample", "Subsampled ratio, defaults to 1"},
+    {OPTION_TYPE_BOOL, &file_ouput, sizeof(file_ouput),   "-o",  "--out", "Write to file instead of display"},
+    {OPTION_TYPE_BOOL, &manual, sizeof(manual),           "-m",  "--manual", "Use manual settings"},
+    {OPTION_TYPE_INT, &white, sizeof(white),              "-wb", "--white", "White Balance Mode"},
+    {OPTION_TYPE_INT, &brightness, sizeof(brightness),    "-br", "--bright", "Brightness Value"},
+    {OPTION_TYPE_INT, &iso, sizeof(iso),                  "-is", "--iso", "ISO Value"},
+    {OPTION_TYPE_INT, &exposure, sizeof(exposure),        "-ex", "--exposure", "Manual Exposure Value"},
+    {OPTION_TYPE_INT, &numTimeouts, sizeof(numTimeouts),  "-to", "--timeouts", "Set the number of frame timeout which can occur before the camera halts"},
+    {OPTION_TYPE_INT, &repeats, sizeof(repeats),          "-r",  "--repeat", "Sets the number of repeat iterations, default is 1."},
+};
+
+struct CallbackData {
+  pthread_mutex_t            mutex;
+  std::list<VisionCamFrame*> frames;
+  CallbackData() {
+    pthread_mutex_init(&mutex, NULL);
+  }
+  ~CallbackData() {
+    pthread_mutex_destroy(&mutex);
+  }
+};
+
+void VisionCamTestCallback(VisionCamFrame* frame) {
+  CallbackData* cb_data = static_cast<CallbackData*>(frame->mCookie);
+
+  MSG("New frame received; offset=%ux%u", frame->mOffsetX, frame->mOffsetY);
+  AutoLock(&cb_data->mutex);
+  cb_data->frames.push_back(frame);
+}
+
+int main(int argc, char *argv[]) {
+  uint32_t r = 0;
+  int32_t i = 0;
+  VisionCamSensorSelection sensorIndex = VCAM_SENSOR_SECONDARY;
+  VisionCamCaptureMode capmode = VCAM_VIDEO_NORMAL;
+  VisionCamFlickerType flicker = FLICKER_60Hz;
+  VisionCamFocusMode focus = VCAM_FOCUS_CONTROL_AUTO;
+  VisionCamStereoInfo info;
+
+  // default values
+  white = VCAM_WHITE_BAL_CONTROL_AUTO;
+  brightness = 50; // [0-200]
+  iso = 100;       // [100-1600]
+  exposure = 50;   // [0-100]
+  manual = false;
+  recvFrames = 0;
+  display_width = 640;
+  display_height = 480;
+  width = 640;
+  height = 480;
+  fps = 30;
+  strcpy(fourcc_str, "NV12");
+  color = FOURCC_STR(fourcc_str);
+  strcpy(name, "car");
+  numImages = DISPLAY_NUM_BUFFERS;
+  sensor = OMX_TI_StereoSensor;
+  numFrames = 100;
+  frameLock = 0xFFFFFFFF;
+  focusDepth = -1;
+  mode = VCAM_VIDEO_NORMAL;
+  camera_rotation = 0;
+  screen_rotation = 0;
+  dw = 0;
+  dh = 0;
+  sw = 0;
+  sh = 0;
+  twoD = false;
+  topBottom = false;
+  subsample = 1;
+  file_ouput = false;
+  numTimeouts = 10;
+  repeats = 1;
+
+  option_process(argc, argv, opts, sizeof(opts)/sizeof(opts[0]));
+
+  // check for bad input
+  if (width <= 0) width = 160;
+  if (height <= 0) height = 120;
+  if (sw <= 0) sw = width;
+  if (sh <= 0) sh = height;
+  if (numImages <= 2) numImages = 2;
+  if (fps <= 15) fps = 15;
+  if (numFrames <= 10) numFrames = 10;
+  if (frameLock > numFrames) frameLock = -1;
+  if (focusDepth > 150) focusDepth = 75;
+  if (mode >= VCAM_CAP_MODE_MAX) mode = VCAM_GESTURE_MODE;
+  if (sensor > 2) sensor = 2;
+  if (camera_rotation != 0 && camera_rotation != 90 && camera_rotation != 180 && camera_rotation != 270)
+      camera_rotation = 0;
+  else if (camera_rotation == 90 || camera_rotation == 270)
+  {
+      uint32_t t = sw;
+      sw = sh;
+      sh = t;
+  }
+  if (subsample <= 0 || subsample > 4)
+      subsample = 1;
+  if (brightness > 200)
+      brightness = 200;
+  if (iso < 100) iso = 100;
+  if (iso > 1600) iso = 1600;
+  if (exposure > 100) exposure = 100;
+  if (repeats == 0)
+      repeats = 1;
+
+  color = FOURCC_STR(fourcc_str);
+
+  MSG("Requested Color %08x", color);
+
+  switch (sensor)
+  {
+    case 2:
+      sensorIndex = VCAM_SENSOR_STEREO;
+      mode = VCAM_STEREO_MODE;
+      memset(&info, 0, sizeof(info));
+      if (topBottom) {
+        MSG("Enabling Stereo Use Case (top/bottom)!");
+        info.layout = VCAM_STEREO_LAYOUT_TOPBOTTOM;
+        height *= 2;
+      } else {
+        MSG("Enabling Stereo Use Case (side by side)!");
+        info.layout = VCAM_STEREO_LAYOUT_LEFTRIGHT;
+        width *= 2;
+      }
+      info.subsampling = subsample;
+      if (color != FOURCC('N','V','1','2')) {
+        ERROR("Only NV12 is supported for stereo");
+        exit(1);
+      }
+      break;
+    case 1:
+      MSG("Enabling Vision Mode on Front Camera");
+      sensorIndex = VCAM_SENSOR_SECONDARY;
+      mode = VCAM_VIDEO_NORMAL;
+      break;
+    default:
+      MSG("Enabling Vision Mode on Back Camera!");
+      sensorIndex = VCAM_SENSOR_PRIMARY;
+  }
+  capmode = (VisionCamCaptureMode)mode;
+
+  // using 1 to <= so prints will make sense
+  for (r = 1; r <= repeats; r++)
+  {
+    MSG("Iteration %u of %u", r, repeats);
+    recvFrames = 0;
+    OMXVisionCam omx_cam;
+    VisionCam *pCam = &omx_cam;
+    int greError = 0;
+
+    CallbackData cb_data;
+    VCAM_RETURN_IF_FAILED(greError, pCam->init(&cb_data));
+    VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_WIDTH, &width, sizeof(width)));
+    VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_HEIGHT, &height, sizeof(height)));
+    VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_COLOR_SPACE_FOURCC, &color, sizeof(color)));
+    // Can't set ROTATION here, see below
+    VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_FPS_FIXED, &fps, sizeof(fps)));
+    VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_CAP_MODE, &capmode, sizeof(capmode)));
+    VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_SENSOR_SELECT, &sensorIndex, sizeof(sensorIndex)));
+    if (capmode == VCAM_STEREO_MODE)
+    {
+        VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_STEREO_INFO, &info, sizeof(info)));
+    }
+
+    // VCAM_PARAM_2DBUFFER_DIM should only be called after resolutions, color space, cap mode, and
+    //   optionally stereo information is set.
+    VisionCamResType res = { VCAM_RESOL_MAX, width, height };
+    VCAM_COMPLAIN_IF_FAILED(greError, pCam->getParameter(VCAM_PARAM_2DBUFFER_DIM, &res, sizeof(res)));
+    MSG("Image: %ux%u, buffer: %ux%u", width, height, res.mWidth, res.mHeight);
+
+    Output* output = new Output(display_width, display_height, width, height,
+        res.mWidth, res.mHeight, color, numImages, twoD, file_ouput);
+    if (output->open() == 0)
+    {
+        VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_FLICKER, &flicker, sizeof(flicker)));
+        VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_AWB_MODE, &white, sizeof(white)));
+        if (manual)
+        {
+            VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_BRIGHTNESS, &brightness, sizeof(brightness)));
+            VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_EXPOSURE_ISO, &iso, sizeof(iso)));
+            VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_MANUAL_EXPOSURE, &exposure, sizeof(exposure)));
+        }
+        VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_NAME, name, sizeof(name)));
+
+        struct buffer* images[numImages];
+        BufferMeta meta[numImages];
+        for (i = 0; i < numImages; i++)
+        {
+            images[i] = output->alloc(&meta[i]);
+        }
+        // tell the camera to use all the camera index buffers
+        VCAM_COMPLAIN_IF_FAILED(greError, pCam->useBuffers(meta, numImages));
+
+        /** @todo Since the OMX Camera is probably being used by
+            the VCAM_SIMPLE test, we have to understand that
+            the OMX-CAMERA has a bug in the camera_rotation when used
+            during LOADED state. We have to wait until IDLE
+            (post useBuffers) or EXECUTING (post PREVIEW)
+            before rotating. */
+        /** @todo Additionally, OMX-CAMERA STEREO mode can't handle the rotation values! */
+        if (capmode != VCAM_STEREO_MODE)
+            VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_ROTATION, &camera_rotation, sizeof(camera_rotation)));
+
+        // register the engine callback with the camera
+        VCAM_COMPLAIN_IF_FAILED(greError,  pCam->enablePreviewCbk(VisionCamTestCallback));
+        VCAM_COMPLAIN_IF_FAILED(greError,  pCam->sendCommand(VCAM_CMD_PREVIEW_START));
+
+        if (focusDepth == -1) { // begin auto-focus
+            VCAM_COMPLAIN_IF_FAILED(greError,  pCam->setParameter(VCAM_PARAM_DO_AUTOFOCUS, &focus, sizeof(focus)));
+        }
+
+        if (greError == 0)
+        {
+            uint32_t timeouts = 0;
+            usleep(1000000/fps); // wait 1 frame period.
+            MSG("VisionCam is initialized, entering queue read loop!");
+            // read from the queue and display the images
+            do {
+              if (cb_data.frames.empty()) {
+                ERROR("Timedout waiting for buffer from Camera!");
+                timeouts++;
+                usleep(1000000/fps);
+                continue;
+              }
+              VisionCamFrame* frame;
+              {
+                AutoLock(&cb_data.mutex);
+                frame = cb_data.frames.front();
+                cb_data.frames.pop_front();
+              }
+              if (frame != NULL) {
+                BufferMeta* meta = static_cast<BufferMeta*>(frame->mFrameBuff);
+                timeouts = 0;
+                output->render(meta);
+                pCam->returnFrame(frame);
+                recvFrames++;
+                if (recvFrames >= numFrames) {
+                  break;
+                }
+                if (focusDepth >= 0) {
+                  if (recvFrames == fps) { // after 1 second
+                      VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_DO_MANUALFOCUS, &focusDepth, sizeof(focusDepth)));
+                  }
+                }
+                if (frameLock > 0) {
+                  if (recvFrames == frameLock) {
+                      bool lock = true;
+                      VCAM_COMPLAIN_IF_FAILED(greError, pCam->sendCommand(VCAM_CMD_LOCK_AE, &lock, sizeof(lock)));
+                      VCAM_COMPLAIN_IF_FAILED(greError, pCam->sendCommand(VCAM_CMD_LOCK_AWB, &lock, sizeof(lock)));
+                  }
+                }
+              }
+            } while (timeouts < numTimeouts);
+        }
+        else
+        {
+            ERROR("VCAM_TEST Failed during initialization (greError = %d, 0x%08x)!", greError, greError);
+        }
+
+        // destroy the camera
+        VCAM_COMPLAIN_IF_FAILED(greError, pCam->sendCommand(VCAM_CMD_PREVIEW_STOP));
+        VCAM_COMPLAIN_IF_FAILED(greError, pCam->disablePreviewCbk(VisionCamTestCallback));
+        VCAM_COMPLAIN_IF_FAILED(greError, pCam->releaseBuffers());
+        VCAM_COMPLAIN_IF_FAILED(greError, pCam->deinit());
+
+        // free the images
+        for (i = 0; i < numImages; i++){
+            output->free(&meta[i]);
+        }
+
+        output->close();
+        delete output;
+    }
+  }
+  return 0;
+}