* Setting powerline to 60Hz

* Fixed Linux Break

* Added exposure mapping support for Linux and Windows

* updated comment

* minor cleanup

* Updated Throughput_perf to support exposure

* fixing build break on Linux with Clang

* fixed Linux Clang build break

* Fixed Linux Clang build break
This commit is contained in:
wes-b 2019-07-18 16:34:03 -07:00 коммит произвёл GitHub
Родитель cdcbbb37ce
Коммит 9afcd78957
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 347 добавлений и 134 удалений

Просмотреть файл

@ -21,6 +21,44 @@ typedef struct _color_control_cap_t
bool valid;
} color_control_cap_t;
typedef struct _exposure_mapping
{
int exponent;
int exposure_usec;
int exposure_mapped_50Hz_usec;
int exposure_mapped_60Hz_usec;
} color_exposure_mapping_t;
#ifdef _WIN32
#define KSELECTANY __declspec(selectany)
#else
#define KSELECTANY __attribute__((weak))
#endif
extern color_exposure_mapping_t device_exposure_mapping[];
KSELECTANY color_exposure_mapping_t device_exposure_mapping[] = {
// clang-format off
//exp, 2^exp, 50Hz, 60Hz,
{ -11, 488, 500, 500},
{ -10, 977, 1250, 1250},
{ -9, 1953, 2500, 2500},
{ -8, 3906, 10000, 8330},
{ -7, 7813, 20000, 16670},
{ -6, 15625, 30000, 33330},
{ -5, 31250, 40000, 41670},
{ -4, 62500, 50000, 50000},
{ -3, 125000, 60000, 66670},
{ -2, 250000, 80000, 83330},
{ -1, 500000, 100000, 100000},
{ 0, 1000000, 120000, 116670},
{ 1, 2000000, 130000, 133330}
// clang-format on
};
#define MAX_EXPOSURE(is_using_60hz) \
(is_using_60hz ? device_exposure_mapping[COUNTOF(device_exposure_mapping) - 1].exposure_mapped_60Hz_usec : \
device_exposure_mapping[COUNTOF(device_exposure_mapping) - 1].exposure_mapped_50Hz_usec)
/** Delivers a sample to the registered callback function when a capture is ready for processing.
*
* \param result

Просмотреть файл

@ -564,9 +564,9 @@ k4a_result_t CMFCameraReader::GetCameraControlCapabilities(const k4a_color_contr
&defaultValue);
// Convert KSProperty exposure time value to micro-second unit
minValue = (LONG)(exp2f((float)minValue) * 1000000.0f);
maxValue = (LONG)(exp2f((float)maxValue) * 1000000.0f);
defaultValue = (LONG)(exp2f((float)defaultValue) * 1000000.0f);
minValue = MapMfExponentToK4a(minValue);
maxValue = MapMfExponentToK4a(maxValue);
defaultValue = MapMfExponentToK4a(defaultValue);
defaultMode = K4A_COLOR_CONTROL_MODE_AUTO;
// Windows KsProperty uses exposure time value as log base 2 seconds, which is not linear.
@ -719,7 +719,7 @@ k4a_result_t CMFCameraReader::GetCameraControl(const k4a_color_control_command_t
nullptr);
// Convert KSProperty exposure time value to micro-second unit
propertyValue = (LONG)(exp2f((float)propertyValue) * 1000000.0f);
propertyValue = MapMfExponentToK4a(propertyValue);
}
break;
case K4A_COLOR_CONTROL_BRIGHTNESS:
@ -848,7 +848,7 @@ k4a_result_t CMFCameraReader::SetCameraControl(const k4a_color_control_command_t
// Convert micro-second unit to KSProperty exposure time value
hr = SetCameraControlValue(PROPSETID_VIDCAP_CAMERACONTROL,
KSPROPERTY_CAMERACONTROL_EXPOSURE,
(LONG)log2f((float)newValue * 0.000001f),
MapK4aExposureToMf(newValue),
flags);
}
break;
@ -911,6 +911,11 @@ k4a_result_t CMFCameraReader::SetCameraControl(const k4a_color_control_command_t
KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY,
(LONG)newValue,
flags);
if (SUCCEEDED(hr))
{
m_using_60hz_power = (newValue == 2);
}
}
break;
case K4A_COLOR_CONTROL_AUTO_EXPOSURE_PRIORITY:
@ -1449,3 +1454,38 @@ CMFCameraReader::SetCameraControlValue(const GUID PropertySet, const ULONG Prope
sizeof(videoControl),
&retSize);
}
LONG CMFCameraReader::MapK4aExposureToMf(int K4aExposure)
{
for (int x = 0; x < COUNTOF(device_exposure_mapping); x++)
{
if ((m_using_60hz_power && K4aExposure <= device_exposure_mapping[x].exposure_mapped_60Hz_usec) ||
(!m_using_60hz_power && K4aExposure <= device_exposure_mapping[x].exposure_mapped_50Hz_usec))
{
return device_exposure_mapping[x].exponent;
}
}
// Default to longest capture in the event mapping failed.
return device_exposure_mapping[COUNTOF(device_exposure_mapping) - 1].exponent;
}
LONG CMFCameraReader::MapMfExponentToK4a(LONG MfExponent)
{
for (int x = 0; x < COUNTOF(device_exposure_mapping); x++)
{
if (MfExponent <= device_exposure_mapping[x].exponent)
{
if (m_using_60hz_power)
{
return device_exposure_mapping[x].exposure_mapped_60Hz_usec;
}
else
{
return device_exposure_mapping[x].exposure_mapped_50Hz_usec;
}
}
}
// Default to longest capture in the event mapping failed.
return MAX_EXPOSURE(m_using_60hz_power);
}

Просмотреть файл

@ -147,12 +147,17 @@ private:
k4a_result_t CreateImage(CFrameContext *pFrameContext, k4a_image_t *image);
k4a_result_t CreateImageCopy(CFrameContext *pFrameContext, k4a_image_t *image);
LONG CMFCameraReader::MapK4aExposureToMf(int K4aExposure);
LONG CMFCameraReader::MapMfExponentToK4a(LONG MfExponent);
private:
Microsoft::WRL::Wrappers::SRWLock m_lock;
bool m_mfStarted = false;
bool m_started = false;
bool m_flushing = false;
bool m_use_mf_buffer = true;
bool m_using_60hz_power = true;
HANDLE m_hStreamFlushed = NULL;
Microsoft::WRL::ComPtr<IMFSourceReader> m_spSourceReader;

Просмотреть файл

@ -11,6 +11,8 @@
#define UVC_AUTO_EXPOSURE_MODE_SHUTTER_PRIORITY 4 // manual exposure time, auto iris
#define UVC_AUTO_EXPOSURE_MODE_APERTURE_PRIORITY 8 // auto exposure time, manual iris
#define CONV_100USEC_TO_USEC (100)
// libUVC frame callback
static void UVCFrameCallback(uvc_frame_t *frame, void *ptr)
{
@ -292,10 +294,10 @@ k4a_result_t UVCCameraReader::GetCameraControlCapabilities(const k4a_color_contr
// 0.0001 sec to uSec
capabilities->supportAuto = true;
capabilities->minValue = (int32_t)(min_exposure_time * 100);
capabilities->maxValue = (int32_t)(max_exposure_time * 100);
capabilities->stepValue = (int32_t)(step_exposure_time * 100);
capabilities->defaultValue = (int32_t)(default_exposure_time * 100);
capabilities->stepValue = (int32_t)(step_exposure_time * CONV_100USEC_TO_USEC);
capabilities->minValue = MapLinuxExposureToK4a((int32_t)min_exposure_time);
capabilities->maxValue = MapLinuxExposureToK4a((int32_t)max_exposure_time);
capabilities->defaultValue = MapLinuxExposureToK4a((int32_t)default_exposure_time);
capabilities->valid = true;
}
break;
@ -743,7 +745,7 @@ k4a_result_t UVCCameraReader::GetCameraControl(const k4a_color_control_command_t
return K4A_RESULT_FAILED;
}
*pValue = (int32_t)(exposure_time * 100); // 0.0001 sec to uSec
*pValue = MapLinuxExposureToK4a((int32_t)exposure_time);
}
break;
case K4A_COLOR_CONTROL_BRIGHTNESS:
@ -897,8 +899,6 @@ k4a_result_t UVCCameraReader::SetCameraControl(const k4a_color_control_command_t
case K4A_COLOR_CONTROL_EXPOSURE_TIME_ABSOLUTE:
if (mode == K4A_COLOR_CONTROL_MODE_MANUAL)
{
uint32_t exposure_time = (uint32_t)(newValue / 100); // uSec to 0.0001 sec
res = uvc_set_ae_mode(m_pDeviceHandle, UVC_AUTO_EXPOSURE_MODE_MANUAL);
if (res < 0)
{
@ -906,7 +906,7 @@ k4a_result_t UVCCameraReader::SetCameraControl(const k4a_color_control_command_t
return K4A_RESULT_FAILED;
}
res = uvc_set_exposure_abs(m_pDeviceHandle, exposure_time);
res = uvc_set_exposure_abs(m_pDeviceHandle, (uint32_t)MapK4aExposureToLinux(newValue));
if (res < 0)
{
LOG_ERROR("Failed to set exposure time abs: %s", uvc_strerror(res));
@ -1074,6 +1074,10 @@ k4a_result_t UVCCameraReader::SetCameraControl(const k4a_color_control_command_t
LOG_ERROR("Failed to set powerline frequency: %s", uvc_strerror(res));
return K4A_RESULT_FAILED;
}
else
{
m_using_60hz_power = (newValue == 2);
}
}
else
{
@ -1290,3 +1294,47 @@ UVCCameraReader::DecodeMJPEGtoBGRA32(uint8_t *in_buf, const size_t in_size, uint
return K4A_RESULT_SUCCEEDED;
}
// Returns exposure in 100us time base
int32_t UVCCameraReader::MapK4aExposureToLinux(int32_t K4aExposure_usec)
{
// We map to the expected exposure then convert to 100us time base to ensure we roll over to the next exposure
// setting in the same way Windows does.
for (uint32_t x = 0; x < COUNTOF(device_exposure_mapping); x++)
{
int32_t mapped_exposure = device_exposure_mapping[x].exposure_mapped_50Hz_usec;
if (m_using_60hz_power)
{
mapped_exposure = device_exposure_mapping[x].exposure_mapped_60Hz_usec;
}
if (K4aExposure_usec <= mapped_exposure)
{
return mapped_exposure / CONV_100USEC_TO_USEC;
}
}
// Default to longest capture in the event mapping failed.
return MAX_EXPOSURE(m_using_60hz_power) / CONV_100USEC_TO_USEC;
}
int32_t UVCCameraReader::MapLinuxExposureToK4a(int32_t LinuxExposure)
{
LinuxExposure *= CONV_100USEC_TO_USEC; // Convert Linux 100us units to us.
for (uint32_t x = 0; x < COUNTOF(device_exposure_mapping); x++)
{
int32_t mapped_exposure = device_exposure_mapping[x].exposure_mapped_50Hz_usec;
if (m_using_60hz_power)
{
mapped_exposure = device_exposure_mapping[x].exposure_mapped_60Hz_usec;
}
if (LinuxExposure <= mapped_exposure)
{
return mapped_exposure;
}
}
// Default to longest capture in the event mapping failed.
return MAX_EXPOSURE(m_using_60hz_power);
}

Просмотреть файл

@ -53,6 +53,9 @@ private:
k4a_result_t DecodeMJPEGtoBGRA32(uint8_t *in_buf, const size_t in_size, uint8_t *out_buf, const size_t out_size);
int32_t MapK4aExposureToLinux(int32_t K4aExposure);
int32_t MapLinuxExposureToK4a(int32_t LinuxExposure);
private:
// Lock
std::mutex m_mutex;
@ -62,6 +65,7 @@ private:
uvc_device_t *m_pDevice = nullptr;
uvc_device_handle_t *m_pDeviceHandle = nullptr;
bool m_streaming = false;
bool m_using_60hz_power = true;
// Image format cache
uint32_t m_width_pixels;

Просмотреть файл

@ -3,6 +3,8 @@
//************************ Includes *****************************
#include <k4a/k4a.h>
#include <k4ainternal/common.h>
#include <k4ainternal/../../src/color/color_priv.h>
#include <utcommon.h>
#include <gtest/gtest.h>
#include <azure_c_shared_utility/tickcounter.h>
@ -25,9 +27,28 @@
#define K4A_COLOR_MODE_EXPECTED_FPS_5 5
//************************ Typedefs *****************************
typedef enum _power_line_t
{
K4A_POWER_LINE_50HZ = 1,
K4A_POWER_LINE_60HZ = 2
} power_line_t;
//************ Declarations (Statics and globals) ***************
#define EXPOSURE_TIME_ABSOLUTE_CONTROL_DEFAULT_60_HZ_VALUE 33330 // 60Hz
#define EXPOSURE_TIME_ABSOLUTE_CONTROL_DEFAULT_50_HZ_VALUE 30000 // 50Hz
#define SET_POWER_LINE_FREQ(val) \
{ \
int32_t value; \
const k4a_color_control_command_t power_cmd = K4A_COLOR_CONTROL_POWERLINE_FREQUENCY; \
k4a_color_control_mode_t mode = K4A_COLOR_CONTROL_MODE_MANUAL; \
ASSERT_EQ(K4A_RESULT_SUCCEEDED, k4a_device_set_color_control(m_device, power_cmd, mode, val)); \
\
/*Verify Results */ \
ASSERT_EQ(K4A_RESULT_SUCCEEDED, k4a_device_get_color_control(m_device, power_cmd, &mode, &value)); \
ASSERT_EQ(mode, K4A_COLOR_CONTROL_MODE_MANUAL); \
ASSERT_EQ(value, val); \
}
//******************* Function Prototypes ***********************
//*********************** Functions *****************************
@ -150,16 +171,16 @@ TEST_P(color_functional_test, color_streaming_test)
switch (as.color_format)
{
case K4A_IMAGE_FORMAT_COLOR_MJPG:
EXPECT_EQ(0, k4a_image_get_stride_bytes(image));
ASSERT_EQ(0, k4a_image_get_stride_bytes(image));
break;
case K4A_IMAGE_FORMAT_COLOR_NV12:
EXPECT_EQ(k4a_image_get_width_pixels(image), k4a_image_get_stride_bytes(image));
ASSERT_EQ(k4a_image_get_width_pixels(image), k4a_image_get_stride_bytes(image));
break;
case K4A_IMAGE_FORMAT_COLOR_YUY2:
EXPECT_EQ(k4a_image_get_width_pixels(image) * 2, k4a_image_get_stride_bytes(image));
ASSERT_EQ(k4a_image_get_width_pixels(image) * 2, k4a_image_get_stride_bytes(image));
break;
case K4A_IMAGE_FORMAT_COLOR_BGRA32:
EXPECT_EQ(k4a_image_get_width_pixels(image) * 4, k4a_image_get_stride_bytes(image));
ASSERT_EQ(k4a_image_get_width_pixels(image) * 4, k4a_image_get_stride_bytes(image));
break;
default:
break;
@ -496,7 +517,7 @@ TEST_F(color_functional_test, colorModeChange)
k4a_image_t image = k4a_capture_get_color_image(capture);
ASSERT_NE(image, (k4a_image_t)NULL);
ASSERT_NE((uint8_t *)NULL, k4a_image_get_buffer(image));
EXPECT_EQ(config_expected_image_size, k4a_image_get_size(image)) << "Failed due to invalid frame size\n";
ASSERT_EQ(config_expected_image_size, k4a_image_get_size(image)) << "Failed due to invalid frame size\n";
k4a_image_release(image);
k4a_capture_release(capture);
@ -511,7 +532,7 @@ TEST_F(color_functional_test, colorModeChange)
image = k4a_capture_get_color_image(capture);
ASSERT_NE(image, (k4a_image_t)NULL);
ASSERT_NE((uint8_t *)NULL, k4a_image_get_buffer(image));
EXPECT_EQ(config2_expected_image_size, k4a_image_get_size(image)) << "Failed due to invalid frame size\n";
ASSERT_EQ(config2_expected_image_size, k4a_image_get_size(image)) << "Failed due to invalid frame size\n";
k4a_image_release(image);
k4a_capture_release(capture);
@ -552,14 +573,14 @@ TEST_F(color_functional_test, colorExposureTest)
config.depth_mode = K4A_DEPTH_MODE_OFF;
// Exposure set test
EXPECT_EQ(K4A_RESULT_SUCCEEDED,
ASSERT_EQ(K4A_RESULT_SUCCEEDED,
k4a_device_set_color_control(m_device,
K4A_COLOR_CONTROL_EXPOSURE_TIME_ABSOLUTE,
K4A_COLOR_CONTROL_MODE_MANUAL,
15625));
// Exposure get test
EXPECT_EQ(K4A_RESULT_SUCCEEDED,
ASSERT_EQ(K4A_RESULT_SUCCEEDED,
k4a_device_get_color_control(m_device, K4A_COLOR_CONTROL_EXPOSURE_TIME_ABSOLUTE, &control_mode, &value));
std::cout << "control_mode = " << (control_mode == K4A_COLOR_CONTROL_MODE_AUTO ? "auto" : "manual")
<< ", value = " << value << " uSec\n";
@ -570,8 +591,8 @@ TEST_F(color_functional_test, colorExposureTest)
// Verify exposure metadata
ASSERT_NE(image = k4a_capture_get_color_image(capture), (k4a_image_t)NULL);
EXPECT_GT(exposure_time = k4a_image_get_exposure_usec(image), 0);
EXPECT_LT(exposure_time, 33333); // At a min, this should be smaller than the frame rate
ASSERT_GT(exposure_time = k4a_image_get_exposure_usec(image), 0);
ASSERT_LT(exposure_time, 33333); // At a min, this should be smaller than the frame rate
std::cout << "exposure_time applied = " << exposure_time << " uSec\n";
@ -579,7 +600,7 @@ TEST_F(color_functional_test, colorExposureTest)
k4a_capture_release(capture);
// Reset exposure time to default
EXPECT_EQ(K4A_RESULT_SUCCEEDED,
ASSERT_EQ(K4A_RESULT_SUCCEEDED,
k4a_device_get_color_control_capabilities(m_device,
K4A_COLOR_CONTROL_EXPOSURE_TIME_ABSOLUTE,
&supports_auto,
@ -588,7 +609,7 @@ TEST_F(color_functional_test, colorExposureTest)
&step_value,
&default_value,
&default_mode));
EXPECT_EQ(K4A_RESULT_SUCCEEDED,
ASSERT_EQ(K4A_RESULT_SUCCEEDED,
k4a_device_set_color_control(m_device,
K4A_COLOR_CONTROL_EXPOSURE_TIME_ABSOLUTE,
K4A_COLOR_CONTROL_MODE_MANUAL,
@ -597,7 +618,7 @@ TEST_F(color_functional_test, colorExposureTest)
// If default mode is not manual, recover color control mode as well
if (default_mode != K4A_COLOR_CONTROL_MODE_MANUAL)
{
EXPECT_EQ(K4A_RESULT_SUCCEEDED,
ASSERT_EQ(K4A_RESULT_SUCCEEDED,
k4a_device_set_color_control(m_device,
K4A_COLOR_CONTROL_EXPOSURE_TIME_ABSOLUTE,
default_mode,
@ -660,124 +681,130 @@ public:
}
}
void control_test_worker(const k4a_color_control_command_t command,
const k4a_color_control_mode_t default_mode,
const int32_t default_value);
k4a_device_t m_device = nullptr;
private:
int32_t map_manual_exposure(int32_t value, bool sixty_hertz);
};
TEST_P(color_control_test, control_test)
int32_t color_control_test::map_manual_exposure(int32_t value, bool sixty_hertz)
{
for (uint32_t x = 0; x < COUNTOF(device_exposure_mapping); x++)
{
int32_t exposure = device_exposure_mapping[x].exposure_mapped_50Hz_usec;
if (sixty_hertz)
{
exposure = device_exposure_mapping[x].exposure_mapped_60Hz_usec;
}
if (value <= exposure)
{
return exposure;
}
}
return MAX_EXPOSURE(sixty_hertz);
}
void color_control_test::control_test_worker(const k4a_color_control_command_t command,
const k4a_color_control_mode_t default_mode,
const int32_t default_value)
{
auto as = GetParam();
k4a_color_control_mode_t control_mode = K4A_COLOR_CONTROL_MODE_AUTO;
int32_t min_value;
int32_t max_value;
int32_t step_value;
int32_t default_value;
k4a_color_control_mode_t default_mode = K4A_COLOR_CONTROL_MODE_AUTO;
int32_t default_value_read;
k4a_color_control_mode_t default_mode_read = K4A_COLOR_CONTROL_MODE_AUTO;
int32_t current_value;
k4a_color_control_mode_t current_mode = K4A_COLOR_CONTROL_MODE_MANUAL;
bool supports_auto;
int32_t value = 0;
// Invalid device handle test
EXPECT_EQ(K4A_RESULT_FAILED, k4a_device_get_color_control(nullptr, as.command, &control_mode, &value));
EXPECT_EQ(K4A_RESULT_FAILED, k4a_device_set_color_control(nullptr, as.command, control_mode, value));
ASSERT_EQ(K4A_RESULT_FAILED, k4a_device_get_color_control(nullptr, command, &default_mode_read, &value));
ASSERT_EQ(K4A_RESULT_FAILED, k4a_device_set_color_control(nullptr, command, default_mode_read, value));
// Read control capabilities
EXPECT_EQ(K4A_RESULT_SUCCEEDED,
ASSERT_EQ(K4A_RESULT_SUCCEEDED,
k4a_device_get_color_control_capabilities(m_device,
as.command,
command,
&supports_auto,
&min_value,
&max_value,
&step_value,
&default_value,
&default_mode));
&default_value_read,
&default_mode_read));
EXPECT_EQ(K4A_RESULT_SUCCEEDED, k4a_device_get_color_control(m_device, as.command, &current_mode, &current_value));
ASSERT_EQ(K4A_RESULT_SUCCEEDED, k4a_device_get_color_control(m_device, command, &current_mode, &current_value));
// Verify default values
EXPECT_EQ(default_mode, as.default_mode);
EXPECT_EQ(default_value, as.default_value);
if (current_mode != default_mode)
ASSERT_EQ(default_mode_read, default_mode);
if (default_mode == K4A_COLOR_CONTROL_MODE_MANUAL)
{
std::cout << "Current mode (" << current_mode << ") is not equal to default mode (" << default_mode
<< "), please reset device before running test.\n";
}
if (current_value != default_value)
{
std::cout << "Current value (" << current_value << ") is not equal to default value (" << default_value
<< "), please reset device before running test.\n";
ASSERT_EQ(default_value_read, default_value);
}
if (supports_auto)
{
EXPECT_EQ(K4A_RESULT_SUCCEEDED,
k4a_device_set_color_control(m_device, as.command, K4A_COLOR_CONTROL_MODE_AUTO, 0));
ASSERT_EQ(K4A_RESULT_SUCCEEDED,
k4a_device_set_color_control(m_device, command, K4A_COLOR_CONTROL_MODE_AUTO, 0));
}
else
{
EXPECT_EQ(K4A_RESULT_FAILED,
k4a_device_set_color_control(m_device, as.command, K4A_COLOR_CONTROL_MODE_AUTO, 0));
ASSERT_EQ(K4A_RESULT_FAILED, k4a_device_set_color_control(m_device, command, K4A_COLOR_CONTROL_MODE_AUTO, 0));
}
if (as.command == K4A_COLOR_CONTROL_EXPOSURE_TIME_ABSOLUTE)
if (command == K4A_COLOR_CONTROL_EXPOSURE_TIME_ABSOLUTE)
{
#ifdef _WIN32
// Windows only support exposure time value as log base 2 seconds.
// Convert micro sec unit of min, max and step to Windows based values and test
min_value = (int32_t)log2f((float)min_value * 0.000001f);
max_value = (int32_t)log2f((float)max_value * 0.000001f);
step_value = 1;
bool b_sixty_hertz = (default_value == EXPOSURE_TIME_ABSOLUTE_CONTROL_DEFAULT_60_HZ_VALUE) ? true : false;
k4a_color_control_mode_t manual = K4A_COLOR_CONTROL_MODE_MANUAL;
// Test valid range
for (int32_t testValue = min_value; testValue <= max_value; testValue += step_value)
for (uint32_t x = 0; x < COUNTOF(device_exposure_mapping); x++)
{
// Set test value
EXPECT_EQ(K4A_RESULT_SUCCEEDED,
k4a_device_set_color_control(m_device,
as.command,
K4A_COLOR_CONTROL_MODE_MANUAL,
(int32_t)(exp2f((float)testValue) * 1000000.0f))); // Convert Windows
// based parameter
// to micro sec.
int32_t threshold = b_sixty_hertz ? device_exposure_mapping[x].exposure_mapped_60Hz_usec :
device_exposure_mapping[x].exposure_mapped_50Hz_usec;
// Get current value
EXPECT_EQ(K4A_RESULT_SUCCEEDED, k4a_device_get_color_control(m_device, as.command, &control_mode, &value));
// For this test we test the mapping value transitions; 1 below, 1 above, and the exact value.
int32_t testValue = threshold - 1;
ASSERT_EQ(K4A_RESULT_SUCCEEDED, k4a_device_set_color_control(m_device, command, manual, testValue));
ASSERT_EQ(K4A_RESULT_SUCCEEDED, k4a_device_get_color_control(m_device, command, &current_mode, &value));
ASSERT_EQ(current_mode, manual);
ASSERT_EQ(value, map_manual_exposure(testValue, b_sixty_hertz)) << testValue << " was the value tested\n";
EXPECT_EQ(control_mode, K4A_COLOR_CONTROL_MODE_MANUAL);
// Compare applied value in micro sec unit.
EXPECT_EQ(value, (int32_t)(exp2f((float)testValue) * 1000000.0f));
}
#else
// Test valid range
step_value *= 3; // skip test to do not too many test cases
for (int32_t testValue = min_value; testValue <= max_value; testValue += step_value)
{
// Set test value
EXPECT_EQ(K4A_RESULT_SUCCEEDED,
k4a_device_set_color_control(m_device, as.command, K4A_COLOR_CONTROL_MODE_MANUAL, testValue));
testValue = threshold;
ASSERT_EQ(K4A_RESULT_SUCCEEDED, k4a_device_set_color_control(m_device, command, manual, testValue));
ASSERT_EQ(K4A_RESULT_SUCCEEDED, k4a_device_get_color_control(m_device, command, &current_mode, &value));
ASSERT_EQ(current_mode, manual);
ASSERT_EQ(value, map_manual_exposure(testValue, b_sixty_hertz)) << testValue << " was the value tested\n";
// Get current value
EXPECT_EQ(K4A_RESULT_SUCCEEDED, k4a_device_get_color_control(m_device, as.command, &control_mode, &value));
testValue = threshold + 1;
ASSERT_EQ(K4A_RESULT_SUCCEEDED, k4a_device_set_color_control(m_device, command, manual, testValue));
ASSERT_EQ(K4A_RESULT_SUCCEEDED, k4a_device_get_color_control(m_device, command, &current_mode, &value));
ASSERT_EQ(current_mode, manual);
ASSERT_EQ(value, map_manual_exposure(testValue, b_sixty_hertz)) << testValue << " was the value tested\n";
EXPECT_EQ(control_mode, K4A_COLOR_CONTROL_MODE_MANUAL);
ASSERT_EQ(current_mode, manual);
ASSERT_EQ(current_mode, K4A_COLOR_CONTROL_MODE_MANUAL);
// LibUVC exposure time camera control has 0.0001 sec precision
EXPECT_EQ(value, testValue);
}
#endif
}
else
{
// Test invalid range
EXPECT_EQ(K4A_RESULT_FAILED,
ASSERT_EQ(K4A_RESULT_FAILED,
k4a_device_set_color_control(m_device,
as.command,
command,
K4A_COLOR_CONTROL_MODE_MANUAL,
min_value - step_value));
EXPECT_EQ(K4A_RESULT_FAILED,
ASSERT_EQ(K4A_RESULT_FAILED,
k4a_device_set_color_control(m_device,
as.command,
command,
K4A_COLOR_CONTROL_MODE_MANUAL,
max_value + step_value));
@ -785,34 +812,42 @@ TEST_P(color_control_test, control_test)
for (int32_t testValue = min_value; testValue <= max_value; testValue += step_value)
{
// Set test value
EXPECT_EQ(K4A_RESULT_SUCCEEDED,
k4a_device_set_color_control(m_device, as.command, K4A_COLOR_CONTROL_MODE_MANUAL, testValue));
// Get current value
EXPECT_EQ(K4A_RESULT_SUCCEEDED, k4a_device_get_color_control(m_device, as.command, &control_mode, &value));
EXPECT_EQ(control_mode, K4A_COLOR_CONTROL_MODE_MANUAL);
EXPECT_EQ(value, testValue);
ASSERT_EQ(K4A_RESULT_SUCCEEDED,
k4a_device_set_color_control(m_device, command, K4A_COLOR_CONTROL_MODE_MANUAL, testValue));
ASSERT_EQ(K4A_RESULT_SUCCEEDED, k4a_device_get_color_control(m_device, command, &current_mode, &value));
ASSERT_EQ(current_mode, K4A_COLOR_CONTROL_MODE_MANUAL);
ASSERT_EQ(value, testValue);
}
}
// Recover to initial value
EXPECT_EQ(K4A_RESULT_SUCCEEDED,
k4a_device_set_color_control(m_device, as.command, K4A_COLOR_CONTROL_MODE_MANUAL, default_value));
// If default mode is not manual, recover color control mode as well
if (default_mode != K4A_COLOR_CONTROL_MODE_MANUAL)
// Restore Defaults
{
EXPECT_EQ(K4A_RESULT_SUCCEEDED,
k4a_device_set_color_control(m_device, as.command, default_mode, default_value));
ASSERT_EQ(K4A_RESULT_SUCCEEDED, k4a_device_set_color_control(m_device, command, default_mode, default_value));
ASSERT_EQ(K4A_RESULT_SUCCEEDED, k4a_device_get_color_control(m_device, command, &current_mode, &current_value));
ASSERT_EQ(current_mode, default_mode);
if (default_mode == K4A_COLOR_CONTROL_MODE_MANUAL)
{
ASSERT_EQ(current_value, default_value);
}
}
}
#ifdef _WIN32
#define EXPOSURE_TIME_ABSOLUTE_CONTROL_DEFAULT_VALUE 15625
#else
#define EXPOSURE_TIME_ABSOLUTE_CONTROL_DEFAULT_VALUE 12700
#endif
TEST_P(color_control_test, control_test)
{
auto as = GetParam();
if (as.command != K4A_COLOR_CONTROL_EXPOSURE_TIME_ABSOLUTE)
{
control_test_worker(as.command, as.default_mode, as.default_value);
}
else
{
SET_POWER_LINE_FREQ(K4A_POWER_LINE_60HZ);
control_test_worker(as.command, as.default_mode, EXPOSURE_TIME_ABSOLUTE_CONTROL_DEFAULT_60_HZ_VALUE);
SET_POWER_LINE_FREQ(K4A_POWER_LINE_50HZ);
control_test_worker(as.command, as.default_mode, EXPOSURE_TIME_ABSOLUTE_CONTROL_DEFAULT_50_HZ_VALUE);
}
}
INSTANTIATE_TEST_CASE_P(
color_control,
@ -820,7 +855,7 @@ INSTANTIATE_TEST_CASE_P(
::testing::Values(
color_control_parameter{ K4A_COLOR_CONTROL_EXPOSURE_TIME_ABSOLUTE,
K4A_COLOR_CONTROL_MODE_AUTO,
EXPOSURE_TIME_ABSOLUTE_CONTROL_DEFAULT_VALUE },
0 } /* default is overwritten for this test case */,
color_control_parameter{ K4A_COLOR_CONTROL_BRIGHTNESS, K4A_COLOR_CONTROL_MODE_MANUAL, 128 },
color_control_parameter{ K4A_COLOR_CONTROL_CONTRAST, K4A_COLOR_CONTROL_MODE_MANUAL, 5 },
color_control_parameter{ K4A_COLOR_CONTROL_SATURATION, K4A_COLOR_CONTROL_MODE_MANUAL, 32 },

Просмотреть файл

@ -197,18 +197,18 @@ TEST_F(color_ut, exposure_control)
config.color_resolution = K4A_COLOR_RESOLUTION_720P;
config.depth_mode = K4A_DEPTH_MODE_OFF;
// set exposure to 488 uSec
// set exposure to 500 uSec
ASSERT_EQ(K4A_RESULT_SUCCEEDED,
color_set_control(color_handle,
K4A_COLOR_CONTROL_EXPOSURE_TIME_ABSOLUTE,
K4A_COLOR_CONTROL_MODE_MANUAL,
62500));
500));
// get exposure settings
ASSERT_EQ(K4A_RESULT_SUCCEEDED,
color_get_control(color_handle, K4A_COLOR_CONTROL_EXPOSURE_TIME_ABSOLUTE, &control_mode, &value));
ASSERT_EQ(control_mode, K4A_COLOR_CONTROL_MODE_MANUAL);
ASSERT_EQ(value, 62500);
ASSERT_EQ(value, 500);
// test color_start()
ASSERT_EQ(K4A_RESULT_SUCCEEDED, color_start(color_handle, &config));

Просмотреть файл

@ -15,7 +15,7 @@
#include <azure_c_shared_utility/threadapi.h>
#include <azure_c_shared_utility/envvariable.h>
#define TS_TO_MS(ts) ((long long)((ts) / 1000)) // TS convertion to milliseconds
#define TS_TO_MS(ts) ((long long)((ts) / 1)) // TS convertion to milliseconds
#define K4A_IMU_SAMPLE_RATE 1666 // +/- 2%
@ -30,6 +30,7 @@ static bool g_no_startup_flush = false;
static uint32_t g_subordinate_delay_off_master_usec = 0;
static bool g_manual_exposure = false;
static uint32_t g_exposure_setting = 0;
static bool g_power_line_50_hz = false;
using ::testing::ValuesIn;
@ -241,14 +242,35 @@ TEST_P(throughput_perf, testTest)
printf("Capturing %d frames for test: %s\n", g_capture_count, as.test_name);
{
int32_t power_line_setting = g_power_line_50_hz ? 1 : 2;
ASSERT_EQ(K4A_RESULT_SUCCEEDED,
k4a_device_set_color_control(m_device,
K4A_COLOR_CONTROL_POWERLINE_FREQUENCY,
K4A_COLOR_CONTROL_MODE_MANUAL,
power_line_setting));
printf("Power line mode set to manual and %s.\n", power_line_setting == 1 ? "50Hz" : "60Hz");
}
if (g_manual_exposure)
{
k4a_color_control_mode_t read_mode;
int32_t read_exposure;
ASSERT_EQ(K4A_RESULT_SUCCEEDED,
k4a_device_set_color_control(m_device,
K4A_COLOR_CONTROL_EXPOSURE_TIME_ABSOLUTE,
K4A_COLOR_CONTROL_MODE_MANUAL,
(int32_t)g_exposure_setting));
printf("Manual Exposure: %d\n", g_exposure_setting);
ASSERT_EQ(K4A_RESULT_SUCCEEDED,
k4a_device_get_color_control(m_device,
K4A_COLOR_CONTROL_EXPOSURE_TIME_ABSOLUTE,
&read_mode,
&read_exposure));
printf(
"Setting exposure to manual mode, exposure target is: %d. Actual mode is: %s. Actual value is: %d.\n",
g_exposure_setting,
read_mode == K4A_COLOR_CONTROL_MODE_AUTO ? "auto" : "manual",
read_exposure);
}
else
{
@ -332,9 +354,11 @@ TEST_P(throughput_perf, testTest)
k4a_capture_release(capture);
}
printf("\n");
printf(" | TS [Delta TS] | TS [Delta TS] | TS [Delta TS] | TS Delta (C&D)\n");
printf("===================================================================================================\n");
printf("All times in us\n");
printf("+---------------------------+-------------------+-------------------+--------+\n");
printf("| Color Info | IR 16 Info | Depth16 Info | TS Del |\n");
printf("| TS [Delta TS][Exposure] | TS [Delta TS] | TS [Delta TS] | (C-D) |\n");
printf("+---------------------------+-------------------+-------------------+--------+\n");
thread.enable_counting = true; // start counting IMU samples
while (capture_count-- > 0)
@ -351,7 +375,7 @@ TEST_P(throughput_perf, testTest)
{
k4a_image_t image;
printf("Capture:");
printf("|");
// Probe for a color image
image = k4a_capture_get_color_image(capture);
@ -361,7 +385,10 @@ TEST_P(throughput_perf, testTest)
ts = k4a_image_get_device_timestamp_usec(image);
adjusted_max_ts = std::max(ts, adjusted_max_ts);
static_assert(sizeof(ts) == 8, "this should not be wrong");
printf(" Color TS:%6lld[%4lld] ", TS_TO_MS(ts), TS_TO_MS(ts - last_color_ts));
printf(" %9lld[%6lld][%6lld]",
TS_TO_MS(ts),
TS_TO_MS(ts - last_color_ts),
(long long int)k4a_image_get_exposure_usec(image));
// TS should increase
EXPECT_GT(ts, last_color_ts);
@ -381,7 +408,7 @@ TEST_P(throughput_perf, testTest)
depth = true;
ts = k4a_image_get_device_timestamp_usec(image);
adjusted_max_ts = std::max(ts - (uint64_t)config.depth_delay_off_color_usec, adjusted_max_ts);
printf(" | Ir16 TS:%6lld[%4lld] ", TS_TO_MS(ts), TS_TO_MS(ts - last_ir16_ts));
printf(" | %9lld[%6lld]", TS_TO_MS(ts), TS_TO_MS(ts - last_ir16_ts));
// TS should increase
EXPECT_GT(ts, last_ir16_ts);
@ -391,7 +418,7 @@ TEST_P(throughput_perf, testTest)
}
else
{
printf(" | Ir16 None ");
printf(" | ");
}
// Probe for a depth16 image
@ -400,7 +427,7 @@ TEST_P(throughput_perf, testTest)
{
ts = k4a_image_get_device_timestamp_usec(image);
adjusted_max_ts = std::max(ts - (uint64_t)config.depth_delay_off_color_usec, adjusted_max_ts);
printf(" | Depth16 TS:%6lld[%4lld]", TS_TO_MS(ts), TS_TO_MS(ts - last_depth16_ts));
printf(" | %9lld[%6lld]", TS_TO_MS(ts), TS_TO_MS(ts - last_depth16_ts));
// TS should increase
EXPECT_GT(ts, last_depth16_ts);
@ -410,7 +437,7 @@ TEST_P(throughput_perf, testTest)
}
else
{
printf(" | Depth16 None ");
printf(" | ");
}
}
else if (wresult == K4A_WAIT_RESULT_TIMEOUT)
@ -428,7 +455,7 @@ TEST_P(throughput_perf, testTest)
both_count++;
int64_t delta = (int64_t)(last_ir16_ts - last_color_ts);
printf(" | %" PRId64 "us\n", delta);
printf(" | %6" PRId64, delta);
delta -= config.depth_delay_off_color_usec;
if (delta < 0)
@ -442,15 +469,17 @@ TEST_P(throughput_perf, testTest)
}
else if (depth)
{
printf(" | ---us\n");
printf(" | ------");
depth_count++;
}
else if (color)
{
printf(" | ---us\n");
printf(" | ------");
color_count++;
}
printf(" |\n");
EXPECT_NE(adjusted_max_ts, 0);
if (last_ts == UINT64_MAX)
{
@ -822,6 +851,16 @@ int main(int argc, char **argv)
g_no_startup_flush = true;
printf("g_no_startup_flush = true\n");
}
else if (strcmp(argument, "--60hz") == 0)
{
g_power_line_50_hz = false;
printf("g_power_line_50_hz = false\n");
}
else if (strcmp(argument, "--50hz") == 0)
{
g_power_line_50_hz = true;
printf("g_power_line_50_hz = true\n");
}
else if (strcmp(argument, "--index") == 0)
{
if (i + 1 <= argc)
@ -922,6 +961,10 @@ int main(int argc, char **argv)
printf(" --exposure <exposure in usec>\n");
printf(" By default the test uses auto exposure. This will test with the manual exposure setting\n");
printf(" that is passed in.\n");
printf(" --60hz\n");
printf(" <default> Sets the power line compensation frequency to 60Hz\n");
printf(" --50hz\n");
printf(" Sets the power line compensation frequency to 50Hz\n");
return 1; // Indicates an error or warning
}