void BbVideoDeviceSelectorControl::enumerateDevices(QList<QByteArray> *devices, QStringList *descriptions) { devices->clear(); descriptions->clear(); camera_unit_t cameras[10]; unsigned int knownCameras = 0; const camera_error_t result = camera_get_supported_cameras(10, &knownCameras, cameras); if (result != CAMERA_EOK) { qWarning() << "Unable to retrieve supported camera types:" << result; return; } for (unsigned int i = 0; i < knownCameras; ++i) { switch (cameras[i]) { case CAMERA_UNIT_FRONT: devices->append(BbCameraSession::cameraIdentifierFront()); descriptions->append(tr("Front Camera")); break; case CAMERA_UNIT_REAR: devices->append(BbCameraSession::cameraIdentifierRear()); descriptions->append(tr("Rear Camera")); break; case CAMERA_UNIT_DESKTOP: devices->append(BbCameraSession::cameraIdentifierDesktop()); descriptions->append(tr("Desktop Camera")); break; default: break; } } }
// NOTE, in this code I am purposely ignoring error return codes for the sake of clarity while // walking through the code. Normally, you should check the return codes for errors, as this // will greatly help to isolate bugs. static int init_camera() { camera_error_t err; unsigned int num; unsigned int i; camera_unit_t cams[CAMERA_UNIT_NUM_UNITS]; camera_unit_t unit; // here are 2 ways to determine which cameras are available on a given device... #if 0 // METHOD 1 // inventory the available camera units // NOTE: to just find the number of available cameras: camera_get_cameras(0, &num, NULL); camera_get_supported_cameras(CAMERA_UNIT_NUM_UNITS, &num, cams); for (i=0; i<num; i++) { fprintf(stderr, "found camera unit %d\n", cams[i]); } #else // METHOD 2 // inventory cameras which support a given feature set - in this case PHOTO & BURST camera_feature_t features[] = { CAMERA_FEATURE_PHOTO, CAMERA_FEATURE_BURST }; camera_unit_t next = CAMERA_UNIT_NONE; num = 0; // note that this is an iterating function call which returns only one "next" unit at a time while (camera_find_capable(features, sizeof(features)/sizeof(*features), next, &next) == CAMERA_EOK) { cams[num++] = next; fprintf(stderr, "camera unit %d supports the required features\n", next); } #endif // open the first camera found unit = cams[0]; fprintf(stderr, "selecting camera unit %d\n", unit); err = camera_open(unit, CAMERA_MODE_RW | CAMERA_MODE_ROLL, &handle); if (err != CAMERA_EOK) { fprintf(stderr, "camera_open() failed: %d\n", err); return err; } // This is the minimal required configuration for a viewfinder. // NOTE: we need to enable burst mode when starting the viewfinder. // the maximum burst framerate is 15fps. don't trust me? you can query // camera_get_photo_vf_framerates() to determine the capabilities. err = camera_set_photovf_property(handle, CAMERA_IMGPROP_WIN_GROUPID, vf_group, CAMERA_IMGPROP_WIN_ID, "my_viewfinder", CAMERA_IMGPROP_BURSTMODE, 1, CAMERA_IMGPROP_FRAMERATE, (double)15.0); // max for burst is 15fps. if (err != CAMERA_EOK) { // NOTE: if you need to narrow down which setting is causing an error, // consider breaking the above command down into multiple calls. // be aware that some values must be changed together though (eg. height & width) // in order to pass range-checking fprintf(stderr, "camera_set_photovf_property() failed: %d\n", err); } else { // a valid photovf and photo configuration are required before starting // the viewfinder. // the defaults for both will always be sane, however if certain properties // are changed in one, they may need to be changed in the other. // resolution is one such example (aspect ratios must match). // here is an example configuration for photo properties - setting up the burst divisor. // this is only valid in burst viewfinder mode, and will cause the camera service to // only deliver every 3rd frame. (note that fractional rates are allowed). // why provide a divisor instead of just setting 5fps? camera_set_photo_property(handle, CAMERA_IMGPROP_BURSTDIVISOR, (double)3.0); // DOUBLE! // callbacks are optional, however status callback is useful for detecting asynchronous events // unless your application requires processing of viewfinder frame data, don't bother with // a viewfinder callback, as it incurs some additional ipc overhead. remember, the viewfinder // window itself is already rendered by the camera service, not your app. // NOTE: we are passing main_bps_chid as the void* arg which will then // be delivered to all callbacks. main_bps_chid is already a global variable, // so this isn't necessary, but is just done here to illustrate the convention. err = camera_start_photo_viewfinder(handle, NULL, //&viewfinder_callback, &status_callback, (void*)main_bps_chid); // user-defined arg. if (err != CAMERA_EOK) { fprintf(stderr, "camera_start_photo_viewfinder() failed: %d\n", err); } else { // successfully started viewfinder // if it's a front-facing camera, we should mirror the viewfinder once // we receive it. if (unit == CAMERA_UNIT_FRONT) { shouldmirror = true; } return 0; } } // clean up on error camera_close(handle); handle = CAMERA_HANDLE_INVALID; return err; }
// NOTE, in this code I am purposely ignoring error return codes for the sake of clarity while // walking through the code. Normally, you should check the return codes for errors, as this // will greatly help to isolate bugs. static int init_camera() { camera_error_t err; unsigned int num; unsigned int i; camera_unit_t cams[CAMERA_UNIT_NUM_UNITS]; camera_unit_t unit; // here are 2 ways to determine which cameras are available on a given device... #if 1 // METHOD 1 // inventory the available camera units // NOTE: to just find the number of available cameras: camera_get_cameras(0, &num, NULL); camera_get_supported_cameras(CAMERA_UNIT_NUM_UNITS, &num, cams); for (i=0; i<num; i++) { fprintf(stderr, "found camera unit %d\n", cams[i]); } #else // METHOD 2 // inventory cameras which support a given feature set - in this case PHOTO & VIDEO camera_feature_t features[] = { CAMERA_FEATURE_PHOTO, CAMERA_FEATURE_VIDEO }; camera_unit_t next = CAMERA_UNIT_NONE; num = 0; // note that this is an iterating function call which returns only one "next" unit at a time while (camera_find_capable(features, sizeof(features)/sizeof(*features), next, &next) == CAMERA_EOK) { cams[num++] = next; fprintf(stderr, "camera unit %d supports the required features\n", next); } #endif // open the first camera found unit = cams[0]; fprintf(stderr, "selecting camera unit %d\n", unit); err = camera_open(unit, CAMERA_MODE_RW | CAMERA_MODE_ROLL, &handle); if (err != CAMERA_EOK) { fprintf(stderr, "camera_open() failed: %d\n", err); return err; } // This is the minimal required configuration for a viewfinder. err = camera_set_photovf_property(handle, CAMERA_IMGPROP_WIN_GROUPID, vf_group, CAMERA_IMGPROP_WIN_ID, "my_viewfinder"); #if 0 // here is a more complex example configuration: err = camera_set_photovf_property(handle, CAMERA_IMGPROP_WIN_GROUPID, vfWndGroupId, CAMERA_IMGPROP_WIN_ID, vfWndWindowId, CAMERA_IMGPROP_WIDTH, w, CAMERA_IMGPROP_HEIGHT, h, CAMERA_IMGPROP_HWOVERLAY, 1, #ifdef DO_PHOTO_180 CAMERA_IMGPROP_ROTATION, (rotation+180) % 360, #else CAMERA_IMGPROP_ROTATION, rotation, #endif #ifdef DO_BURST CAMERA_IMGPROP_BURSTMODE, 1, #endif CAMERA_IMGPROP_FRAMERATE, 15.0); #endif if (err != CAMERA_EOK) { // NOTE: if you need to narrow down which setting is causing an error, // consider breaking the above command down into multiple calls. // be aware that some values must be changed together though (eg. height & width) // in order to pass range-checking fprintf(stderr, "camera_set_photovf_property() failed: %d\n", err); } else { // a valid photovf and photo configuration are required before starting // the viewfinder. // the defaults for both will always be sane, however if certain properties // are changed in one, they may need to be changed in the other. // resolution is one such example (aspect ratios must match). // here is an example configuration for photo properties. (just updating rotation) camera_set_photo_property(handle, CAMERA_IMGPROP_ROTATION, 180); // callbacks are optional, however status callback is useful for detecting asynchronous events // unless your application requires processing of viewfinder frame data, don't bother with // a viewfinder callback, as it incurs some additional ipc overhead. remember, the viewfinder // window itself is already rendered by the camera service, not your app. err = camera_start_photo_viewfinder(handle, &viewfinder_callback, &status_callback, (void*)123); // arbitrary user argument if (err != CAMERA_EOK) { fprintf(stderr, "camera_start_photo_viewfinder() failed: %d\n", err); } else { // successfully started viewfinder // if it's a front-facing camera, we should mirror the viewfinder once // we receive it. if (unit == CAMERA_UNIT_FRONT) { shouldmirror = true; } return 0; } } // clean up on error camera_close(handle); handle = CAMERA_HANDLE_INVALID; return err; }