--- /dev/null
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
LOCAL_EXPORT_C_INCLUDE_DIRS := system/media/alsa_utils/include
LOCAL_SHARED_LIBRARIES := liblog libcutils libtinyalsa libaudioutils
LOCAL_MODULE_TAGS := optional
-LOCAL_CFLAGS := -Wno-unused-parameter
+LOCAL_CFLAGS := -Werror -Wall
+LOCAL_CFLAGS += -Wno-unused-parameter
include $(BUILD_SHARED_LIBRARY)
#include <inttypes.h>
#include <stdint.h>
#include <stdlib.h>
+#include <cutils/properties.h>
#include <log/log.h>
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-/*TODO - Evaluate if this value should/can be retrieved from a device-specific property */
-#define BUFF_DURATION_MS 5
+#define PERIOD_DURATION_US (5 * 1000)
#define DEFAULT_PERIOD_SIZE 1024
if (profile == NULL) {
return DEFAULT_PERIOD_SIZE;
} else {
- unsigned num_sample_frames = (sample_rate * BUFF_DURATION_MS) / 1000;
+ unsigned period_us = property_get_int32("ro.audio.usb.period_us", PERIOD_DURATION_US);
+ unsigned num_sample_frames = ((uint64_t)sample_rate * period_us) / 1000000;
+
if (num_sample_frames < profile->min_period_size) {
num_sample_frames = profile->min_period_size;
}
- return round_to_16_mult(num_sample_frames) * 2;
+ return round_to_16_mult(num_sample_frames);
}
}
#endif
config->channels = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS);
+ // For output devices, let's make sure we choose at least stereo
+ // (assuming the device supports it).
+ if (profile->direction == PCM_OUT &&
+ config->channels < 2 && pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS) >= 2) {
+ config->channels = 2;
+ }
config->rate = pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE);
+ // Prefer 48K or 44.1K
+ if (config->rate < 48000 &&
+ pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE) >= 48000) {
+ config->rate = 48000;
+ } else if (config->rate < 441000 &&
+ pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE) >= 44100) {
+ config->rate = 44100;
+ }
config->period_size = profile_calc_min_period_size(profile, config->rate);
config->period_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIODS);
config->format = get_pcm_format_for_mask(pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT));
log_pcm_config(config, "proxy_setup()");
#endif
- proxy->alsa_config.format =
- config->format != PCM_FORMAT_INVALID && profile_is_format_valid(profile, config->format)
- ? config->format : profile->default_config.format;
- proxy->alsa_config.rate =
- config->rate != 0 && profile_is_sample_rate_valid(profile, config->rate)
- ? config->rate : profile->default_config.rate;
- proxy->alsa_config.channels =
- config->channels != 0 && profile_is_channel_count_valid(profile, config->channels)
- ? config->channels : profile->default_config.channels;
+ if (config->format != PCM_FORMAT_INVALID && profile_is_format_valid(profile, config->format)) {
+ proxy->alsa_config.format = config->format;
+ } else {
+ ALOGW("Invalid format %d - using default %d.",
+ config->format, profile->default_config.format);
+ proxy->alsa_config.format = profile->default_config.format;
+ }
+
+ if (config->rate != 0 && profile_is_sample_rate_valid(profile, config->rate)) {
+ proxy->alsa_config.rate = config->rate;
+ } else {
+ ALOGW("Invalid sample rate %u - using default %u.",
+ config->rate, profile->default_config.rate);
+ proxy->alsa_config.rate = profile->default_config.rate;
+ }
+
+ if (config->channels != 0 && profile_is_channel_count_valid(profile, config->channels)) {
+ proxy->alsa_config.channels = config->channels;
+ } else {
+ ALOGW("Invalid channel count %u - using default %u.",
+ config->channels, profile->default_config.channels);
+ proxy->alsa_config.channels = profile->default_config.channels;
+
+ }
proxy->alsa_config.period_count = profile->default_config.period_count;
proxy->alsa_config.period_size =
int slot_index, bit_index, table_index;
table_index = 0;
- int num_written = 0;
for (slot_index = 0; slot_index < num_slots && table_index < table_size; slot_index++) {
unsigned bit_mask = 1;
for (bit_index = 0; bit_index < bits_per_slot && table_index < table_size; bit_index++) {
__BEGIN_DECLS
+/* The macro FCC_2 highlights places where there are 2-channel assumptions.
+ * This is typically due to legacy implementation of stereo input or output.
+ * Search also for "2", "left", "right", "[0]", "[1]", ">> 16", "<< 16", etc.
+ * Do not change this value.
+ */
+#define FCC_2 2 // FCC_2 = Fixed Channel Count 2
+
+/* The macro FCC_8 highlights places where there are 8-channel assumptions.
+ * This is typically due to audio mixer and resampler limitations.
+ * Do not change this value without verifying all locations that use it.
+ */
+#define FCC_8 8 // FCC_8 = Fixed Channel Count 8
+
/* The enums were moved here mostly from
* frameworks/base/include/media/AudioSystem.h
*/
AUDIO_STREAM_REROUTING = 11, /* For dynamic policy output mixes */
AUDIO_STREAM_PATCH = 12, /* For internal audio flinger tracks. Fixed volume */
AUDIO_STREAM_PUBLIC_CNT = AUDIO_STREAM_TTS + 1,
+ AUDIO_STREAM_FOR_POLICY_CNT = AUDIO_STREAM_PATCH, /* number of streams considered by
+ audio policy for volume and routing */
AUDIO_STREAM_CNT = AUDIO_STREAM_PATCH + 1,
} audio_stream_type_t;
AUDIO_FLAG_HW_HOTWORD = 0x20,
AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY = 0x40,
AUDIO_FLAG_BYPASS_MUTE = 0x80,
+ AUDIO_FLAG_LOW_LATENCY = 0x100,
};
/* Do not change these values without updating their counterparts
/* An example of remote presentation is Wifi Display */
/* where a dongle attached to a TV can be used to */
/* play the mix captured by this audio source. */
+ AUDIO_SOURCE_UNPROCESSED = 9, /* Source for unprocessed sound.
+ Usage examples include level measurement and raw
+ signal analysis. */
AUDIO_SOURCE_CNT,
AUDIO_SOURCE_MAX = AUDIO_SOURCE_CNT - 1,
AUDIO_SOURCE_FM_TUNER = 1998,
} audio_attributes_t;
/* special audio session values
+ * do not need to have audio_unique_id_get_use(session) == AUDIO_UNIQUE_ID_USE_SESSION
* (XXX: should this be living in the audio effects land?)
*/
typedef enum {
* and requests a new session ID to be allocated
* TODO use unique values for AUDIO_SESSION_OUTPUT_MIX and AUDIO_SESSION_ALLOCATE,
* after all uses have been updated from 0 to the appropriate symbol, and have been tested.
+ * Corresponds to AudioManager.AUDIO_SESSION_ID_GENERATE and AudioSystem.AUDIO_SESSION_ALLOCATE.
*/
AUDIO_SESSION_ALLOCATE = 0,
+
+ /* For use with AudioRecord::start(), this indicates no trigger session.
+ * It is also used with output tracks and patch tracks, which never have a session.
+ */
+ AUDIO_SESSION_NONE = 0,
} audio_session_t;
-/* a unique ID allocated by AudioFlinger for use as a audio_io_handle_t or audio_session_t */
+/* a unique ID allocated by AudioFlinger for use as an audio_io_handle_t, audio_session_t,
+ * effect ID (int), audio_module_handle_t, and audio_patch_handle_t.
+ * Audio port IDs (audio_port_handle_t) are allocated by AudioPolicy
+ * in a different namespace than AudioFlinger unique IDs.
+ */
typedef int audio_unique_id_t;
+/* Possible uses for an audio_unique_id_t */
+typedef enum {
+ AUDIO_UNIQUE_ID_USE_UNSPECIFIED = 0,
+ AUDIO_UNIQUE_ID_USE_SESSION = 1, // for allocated sessions, not special AUDIO_SESSION_*
+ AUDIO_UNIQUE_ID_USE_MODULE = 2,
+ AUDIO_UNIQUE_ID_USE_EFFECT = 3,
+ AUDIO_UNIQUE_ID_USE_PATCH = 4,
+ AUDIO_UNIQUE_ID_USE_OUTPUT = 5,
+ AUDIO_UNIQUE_ID_USE_INPUT = 6,
+ // 7 is available
+ AUDIO_UNIQUE_ID_USE_MAX = 8, // must be a power-of-two
+ AUDIO_UNIQUE_ID_USE_MASK = AUDIO_UNIQUE_ID_USE_MAX - 1
+} audio_unique_id_use_t;
+
+/* Return the use of an audio_unique_id_t */
+static inline audio_unique_id_use_t audio_unique_id_get_use(audio_unique_id_t id)
+{
+ return (audio_unique_id_use_t) (id & AUDIO_UNIQUE_ID_USE_MASK);
+}
+
+/* Reserved audio_unique_id_t values. FIXME: not a complete list. */
#define AUDIO_UNIQUE_ID_ALLOCATE AUDIO_SESSION_ALLOCATE
/* Audio sub formats (see enum audio_format). */
} audio_format_vorbis_sub_fmt_t;
-/* Audio format consists of a main format field (upper 8 bits) and a sub format
- * field (lower 24 bits).
+/* Audio format is a 32-bit word that consists of:
+ * main format field (upper 8 bits)
+ * sub format field (lower 24 bits).
*
* The main format indicates the main codec type. The sub format field
* indicates options and parameters for each format. The sub format is mainly
AUDIO_FORMAT_E_AC3 = 0x0A000000UL,
AUDIO_FORMAT_DTS = 0x0B000000UL,
AUDIO_FORMAT_DTS_HD = 0x0C000000UL,
- AUDIO_FORMAT_MAIN_MASK = 0xFF000000UL,
+ // IEC61937 is encoded audio wrapped in 16-bit PCM.
+ AUDIO_FORMAT_IEC61937 = 0x0D000000UL,
+ AUDIO_FORMAT_MAIN_MASK = 0xFF000000UL, /* Deprecated. Use audio_get_main_format() */
AUDIO_FORMAT_SUB_MASK = 0x00FFFFFFUL,
/* Aliases */
*/
enum {
AUDIO_CHANNEL_INDEX_HDR = AUDIO_CHANNEL_REPRESENTATION_INDEX << AUDIO_CHANNEL_COUNT_MAX,
- AUDIO_CHANNEL_INDEX_MASK_1 = AUDIO_CHANNEL_INDEX_HDR | (1 << 1) - 1,
- AUDIO_CHANNEL_INDEX_MASK_2 = AUDIO_CHANNEL_INDEX_HDR | (1 << 2) - 1,
- AUDIO_CHANNEL_INDEX_MASK_3 = AUDIO_CHANNEL_INDEX_HDR | (1 << 3) - 1,
- AUDIO_CHANNEL_INDEX_MASK_4 = AUDIO_CHANNEL_INDEX_HDR | (1 << 4) - 1,
- AUDIO_CHANNEL_INDEX_MASK_5 = AUDIO_CHANNEL_INDEX_HDR | (1 << 5) - 1,
- AUDIO_CHANNEL_INDEX_MASK_6 = AUDIO_CHANNEL_INDEX_HDR | (1 << 6) - 1,
- AUDIO_CHANNEL_INDEX_MASK_7 = AUDIO_CHANNEL_INDEX_HDR | (1 << 7) - 1,
- AUDIO_CHANNEL_INDEX_MASK_8 = AUDIO_CHANNEL_INDEX_HDR | (1 << 8) - 1,
+ AUDIO_CHANNEL_INDEX_MASK_1 = AUDIO_CHANNEL_INDEX_HDR | ((1 << 1) - 1),
+ AUDIO_CHANNEL_INDEX_MASK_2 = AUDIO_CHANNEL_INDEX_HDR | ((1 << 2) - 1),
+ AUDIO_CHANNEL_INDEX_MASK_3 = AUDIO_CHANNEL_INDEX_HDR | ((1 << 3) - 1),
+ AUDIO_CHANNEL_INDEX_MASK_4 = AUDIO_CHANNEL_INDEX_HDR | ((1 << 4) - 1),
+ AUDIO_CHANNEL_INDEX_MASK_5 = AUDIO_CHANNEL_INDEX_HDR | ((1 << 5) - 1),
+ AUDIO_CHANNEL_INDEX_MASK_6 = AUDIO_CHANNEL_INDEX_HDR | ((1 << 6) - 1),
+ AUDIO_CHANNEL_INDEX_MASK_7 = AUDIO_CHANNEL_INDEX_HDR | ((1 << 7) - 1),
+ AUDIO_CHANNEL_INDEX_MASK_8 = AUDIO_CHANNEL_INDEX_HDR | ((1 << 8) - 1),
// FIXME FCC_8
};
/* limited-output speaker device for acoustic safety */
AUDIO_DEVICE_OUT_SPEAKER_SAFE = 0x400000,
AUDIO_DEVICE_OUT_IP = 0x800000,
+ /* audio bus implemented by the audio system (e.g an MOST stereo channel) */
+ AUDIO_DEVICE_OUT_BUS = 0x1000000,
AUDIO_DEVICE_OUT_DEFAULT = AUDIO_DEVICE_BIT_DEFAULT,
AUDIO_DEVICE_OUT_ALL = (AUDIO_DEVICE_OUT_EARPIECE |
AUDIO_DEVICE_OUT_SPEAKER |
AUDIO_DEVICE_OUT_AUX_LINE |
AUDIO_DEVICE_OUT_SPEAKER_SAFE |
AUDIO_DEVICE_OUT_IP |
+ AUDIO_DEVICE_OUT_BUS |
AUDIO_DEVICE_OUT_DEFAULT),
AUDIO_DEVICE_OUT_ALL_A2DP = (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
AUDIO_DEVICE_IN_BLUETOOTH_A2DP = AUDIO_DEVICE_BIT_IN | 0x20000,
AUDIO_DEVICE_IN_LOOPBACK = AUDIO_DEVICE_BIT_IN | 0x40000,
AUDIO_DEVICE_IN_IP = AUDIO_DEVICE_BIT_IN | 0x80000,
+ /* audio bus implemented by the audio system (e.g an MOST stereo channel) */
+ AUDIO_DEVICE_IN_BUS = AUDIO_DEVICE_BIT_IN | 0x100000,
AUDIO_DEVICE_IN_DEFAULT = AUDIO_DEVICE_BIT_IN | AUDIO_DEVICE_BIT_DEFAULT,
AUDIO_DEVICE_IN_ALL = (AUDIO_DEVICE_IN_COMMUNICATION |
AUDIO_DEVICE_IN_BLUETOOTH_A2DP |
AUDIO_DEVICE_IN_LOOPBACK |
AUDIO_DEVICE_IN_IP |
+ AUDIO_DEVICE_IN_BUS |
AUDIO_DEVICE_IN_DEFAULT),
AUDIO_DEVICE_IN_ALL_SCO = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
AUDIO_DEVICE_IN_ALL_USB = (AUDIO_DEVICE_IN_USB_ACCESSORY |
frame_count: 0,
};
+struct audio_config_base {
+ uint32_t sample_rate;
+ audio_channel_mask_t channel_mask;
+ audio_format_t format;
+};
+
+typedef struct audio_config_base audio_config_base_t;
+
+static const audio_config_base_t AUDIO_CONFIG_BASE_INITIALIZER = {
+ sample_rate: 0,
+ channel_mask: AUDIO_CHANNEL_NONE,
+ format: AUDIO_FORMAT_DEFAULT
+};
/* audio hw module handle functions or structures referencing a module */
-typedef int audio_module_handle_t;
+typedef enum {
+ AUDIO_MODULE_HANDLE_NONE = 0,
+} audio_module_handle_t;
/******************************
* Volume control
* But the same patch receives another system wide unique handle allocated by the framework.
* This unique handle is used for all transactions inside the framework.
*/
-typedef int audio_patch_handle_t;
-#define AUDIO_PATCH_HANDLE_NONE 0
+typedef enum {
+ AUDIO_PATCH_HANDLE_NONE = 0,
+} audio_patch_handle_t;
#define AUDIO_PATCH_PORTS_MAX 16
case AUDIO_FORMAT_E_AC3:
case AUDIO_FORMAT_DTS:
case AUDIO_FORMAT_DTS_HD:
+ case AUDIO_FORMAT_IEC61937:
return true;
default:
return false;
}
}
+/**
+ * Extract the primary format, eg. PCM, AC3, etc.
+ */
+static inline audio_format_t audio_get_main_format(audio_format_t format)
+{
+ return (audio_format_t)(format & AUDIO_FORMAT_MAIN_MASK);
+}
+
+/**
+ * Is the data plain PCM samples that can be scaled and mixed?
+ */
static inline bool audio_is_linear_pcm(audio_format_t format)
{
- return ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM);
+ return (audio_get_main_format(format) == AUDIO_FORMAT_PCM);
+}
+
+/**
+ * For this format, is the number of PCM audio frames directly proportional
+ * to the number of data bytes?
+ *
+ * In other words, is the format transported as PCM audio samples,
+ * but not necessarily scalable or mixable.
+ * This returns true for real PCM, but also for AUDIO_FORMAT_IEC61937,
+ * which is transported as 16 bit PCM audio, but where the encoded data
+ * cannot be mixed or scaled.
+ */
+static inline bool audio_has_proportional_frames(audio_format_t format)
+{
+ audio_format_t mainFormat = audio_get_main_format(format);
+ return (mainFormat == AUDIO_FORMAT_PCM
+ || mainFormat == AUDIO_FORMAT_IEC61937);
}
static inline size_t audio_bytes_per_sample(audio_format_t format)
size = sizeof(uint8_t) * 3;
break;
case AUDIO_FORMAT_PCM_16_BIT:
+ case AUDIO_FORMAT_IEC61937:
size = sizeof(int16_t);
break;
case AUDIO_FORMAT_PCM_8_BIT:
return (~AUDIO_DEVICE_BIT_IN & device & (AUDIO_DEVICE_IN_ALL_USB |
AUDIO_DEVICE_IN_HDMI |
AUDIO_DEVICE_IN_SPDIF |
- AUDIO_DEVICE_IN_IP)) != 0;
+ AUDIO_DEVICE_IN_IP |
+ AUDIO_DEVICE_IN_BUS)) != 0;
} else {
// output
return (device & (AUDIO_DEVICE_OUT_ALL_USB |
AUDIO_DEVICE_OUT_HDMI |
AUDIO_DEVICE_OUT_HDMI_ARC |
AUDIO_DEVICE_OUT_SPDIF |
- AUDIO_DEVICE_OUT_IP)) != 0;
+ AUDIO_DEVICE_OUT_IP |
+ AUDIO_DEVICE_OUT_BUS)) != 0;
}
}
* frameworks/base/include/media/AudioSystem.h
*/
-/* device categories used for audio_policy->set_force_use() */
+/* device categories used for audio_policy->set_force_use()
+ * These must match the values in AudioSystem.java
+ */
typedef enum {
AUDIO_POLICY_FORCE_NONE,
AUDIO_POLICY_FORCE_SPEAKER,
AUDIO_POLICY_FORCE_NO_BT_A2DP, /* A2DP sink is not preferred to speaker or wired HS */
AUDIO_POLICY_FORCE_SYSTEM_ENFORCED,
AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED,
+ AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER,
+ AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS,
AUDIO_POLICY_FORCE_CFG_CNT,
AUDIO_POLICY_FORCE_CFG_MAX = AUDIO_POLICY_FORCE_CFG_CNT - 1,
AUDIO_POLICY_FORCE_DEFAULT = AUDIO_POLICY_FORCE_NONE,
} audio_policy_forced_cfg_t;
-/* usages used for audio_policy->set_force_use() */
+/* usages used for audio_policy->set_force_use()
+ * These must match the values in AudioSystem.java
+ */
typedef enum {
AUDIO_POLICY_FORCE_FOR_COMMUNICATION,
AUDIO_POLICY_FORCE_FOR_MEDIA,
AUDIO_POLICY_FORCE_FOR_DOCK,
AUDIO_POLICY_FORCE_FOR_SYSTEM,
AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO,
+ AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND,
AUDIO_POLICY_FORCE_USE_CNT,
AUDIO_POLICY_FORCE_USE_MAX = AUDIO_POLICY_FORCE_USE_CNT - 1,
#define RECOGNITION_MODE_USER_IDENTIFICATION 0x2 /* trigger only if one user in model identified */
#define RECOGNITION_MODE_USER_AUTHENTICATION 0x4 /* trigger only if one user in mode
authenticated */
+#define RECOGNITION_MODE_GENERIC_TRIGGER 0x8 /* generic sound trigger */
+
#define RECOGNITION_STATUS_SUCCESS 0
#define RECOGNITION_STATUS_ABORT 1
#define RECOGNITION_STATUS_FAILURE 2
typedef enum {
SOUND_MODEL_TYPE_UNKNOWN = -1, /* use for unspecified sound model type */
- SOUND_MODEL_TYPE_KEYPHRASE = 0 /* use for key phrase sound models */
+ SOUND_MODEL_TYPE_KEYPHRASE = 0, /* use for key phrase sound models */
+ SOUND_MODEL_TYPE_GENERIC = 1 /* use for all models other than keyphrase */
} sound_trigger_sound_model_type_t;
typedef struct sound_trigger_uuid_s {
typedef int sound_model_handle_t;
/*
- * Generic sound model descriptor. This struct is the header of a larger block passed to
+ * Base sound model descriptor. This struct is the header of a larger block passed to
* load_sound_model() and containing the binary data of the sound model.
* Proprietary representation of users in binary data must match information indicated
* by users field
/*
+ * Generic sound model, used for all cases except key phrase detection.
+ */
+struct sound_trigger_generic_sound_model {
+ struct sound_trigger_sound_model common;
+};
+
+
+/*
* Generic recognition event sent via recognition callback
*/
struct sound_trigger_recognition_event {
struct sound_trigger_phrase_recognition_extra phrase_extras[SOUND_TRIGGER_MAX_PHRASES];
};
+struct sound_trigger_generic_recognition_event {
+ struct sound_trigger_recognition_event common;
+};
+
/*
* configuration for sound trigger capture session passed to start_recognition()
*/
#define CAMCORDER_SRC_TAG "camcorder" // AUDIO_SOURCE_CAMCORDER
#define VOICE_REC_SRC_TAG "voice_recognition" // AUDIO_SOURCE_VOICE_RECOGNITION
#define VOICE_COMM_SRC_TAG "voice_communication" // AUDIO_SOURCE_VOICE_COMMUNICATION
+#define UNPROCESSED_SRC_TAG "unprocessed" // AUDIO_SOURCE_UNPROCESSED
// audio_stream_type_t
#define AUDIO_STREAM_DEFAULT_TAG "default"
typedef enum
{
NS_PARAM_LEVEL, // noise suppression level (t_ns_level)
- NS_PARAM_PROPERTIES
+ NS_PARAM_PROPERTIES,
+ NS_PARAM_TYPE // noise suppression type (t_ns_type)
} t_ns_params;
// noise suppression level
NS_LEVEL_HIGH
} t_ns_level;
+// noise suppression type
+typedef enum {
+ NS_TYPE_SINGLE_CHANNEL,
+ NS_TYPE_MULTI_CHANNEL
+} t_ns_type;
+
// s_ns_settings groups all current ns settings for backup and restore.
typedef struct s_ns_settings {
uint32_t level;
+ uint32_t type;
} t_ns_settings;
#if __cplusplus
LOCAL_MODULE := libaudioroute
LOCAL_SHARED_LIBRARIES:= liblog libcutils libutils libexpat libtinyalsa
LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -Werror -Wall
include $(BUILD_SHARED_LIBRARY)
#define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
#define INITIAL_MIXER_PATH_SIZE 8
+union ctl_values {
+ int *enumerated;
+ long *integer;
+ void *ptr;
+ unsigned char *bytes;
+};
+
struct mixer_state {
struct mixer_ctl *ctl;
unsigned int num_values;
- int *old_value;
- int *new_value;
- int *reset_value;
+ union ctl_values old_value;
+ union ctl_values new_value;
+ union ctl_values reset_value;
};
struct mixer_setting {
unsigned int ctl_index;
unsigned int num_values;
- int *value;
+ unsigned int type;
+ union ctl_values value;
};
struct mixer_value {
unsigned int ctl_index;
int index;
- int value;
+ long value;
};
struct mixer_path {
case MIXER_CTL_TYPE_BOOL:
case MIXER_CTL_TYPE_INT:
case MIXER_CTL_TYPE_ENUM:
+ case MIXER_CTL_TYPE_BYTE:
return true;
default:
return false;
}
}
+/* as they match in alsa */
+static size_t sizeof_ctl_type(enum mixer_ctl_type type) {
+ switch (type) {
+ case MIXER_CTL_TYPE_BOOL:
+ case MIXER_CTL_TYPE_INT:
+ return sizeof(long);
+ case MIXER_CTL_TYPE_ENUM:
+ return sizeof(int);
+ case MIXER_CTL_TYPE_BYTE:
+ return sizeof(unsigned char);
+ case MIXER_CTL_TYPE_INT64:
+ case MIXER_CTL_TYPE_IEC958:
+ case MIXER_CTL_TYPE_UNKNOWN:
+ default:
+ LOG_ALWAYS_FATAL("Unsupported mixer ctl type: %d, check type before calling", (int)type);
+ return 0;
+ }
+}
+
static inline struct mixer_ctl *index_to_ctl(struct audio_route *ar,
unsigned int ctl_index)
{
return ar->mixer_state[ctl_index].ctl;
}
+#if 0
static void path_print(struct audio_route *ar, struct mixer_path *path)
{
unsigned int i;
struct mixer_ctl *ctl = index_to_ctl(ar, path->setting[i].ctl_index);
ALOGE(" id=%d: ctl=%s", i, mixer_ctl_get_name(ctl));
- for (j = 0; j < path->setting[i].num_values; j++)
- ALOGE(" id=%d value=%d", j, path->setting[i].value[j]);
+ if (mixer_ctl_get_type(ctl) == MIXER_CTL_TYPE_BYTE) {
+ for (j = 0; j < path->setting[i].num_values; j++)
+ ALOGE(" id=%d value=0x%02x", j, path->setting[i].value.bytes[j]);
+ } else if (mixer_ctl_get_type(ctl) == MIXER_CTL_TYPE_ENUM) {
+ for (j = 0; j < path->setting[i].num_values; j++)
+ ALOGE(" id=%d value=%d", j, path->setting[i].value.enumerated[j]);
+ } else {
+ for (j = 0; j < path->setting[i].num_values; j++)
+ ALOGE(" id=%d value=%ld", j, path->setting[i].value.integer[j]);
+ }
}
}
+#endif
static void path_free(struct audio_route *ar)
{
if (ar->mixer_path[i].name)
free(ar->mixer_path[i].name);
if (ar->mixer_path[i].setting) {
- if (ar->mixer_path[i].setting->value)
- free(ar->mixer_path[i].setting->value);
+ if (ar->mixer_path[i].setting->value.ptr)
+ free(ar->mixer_path[i].setting->value.ptr);
free(ar->mixer_path[i].setting);
}
}
free(ar->mixer_path);
+ ar->mixer_path = NULL;
+ ar->mixer_path_size = 0;
}
static struct mixer_path *path_get_by_name(struct audio_route *ar,
return -1;
}
+ if (!is_supported_ctl_type(setting->type)) {
+ ALOGE("unsupported type %d", (int)setting->type);
+ return -1;
+ }
+
path_index = alloc_path_setting(path);
if (path_index < 0)
return -1;
path->setting[path_index].ctl_index = setting->ctl_index;
+ path->setting[path_index].type = setting->type;
path->setting[path_index].num_values = setting->num_values;
- path->setting[path_index].value = malloc(setting->num_values * sizeof(int));
+
+ size_t value_sz = sizeof_ctl_type(setting->type);
+
+ path->setting[path_index].value.ptr = calloc(setting->num_values, value_sz);
/* copy all values */
- memcpy(path->setting[path_index].value, setting->value,
- setting->num_values * sizeof(int));
+ memcpy(path->setting[path_index].value.ptr, setting->value.ptr,
+ setting->num_values * value_sz);
return 0;
}
if (path_index < 0) {
/* New path */
+ enum mixer_ctl_type type = mixer_ctl_get_type(ctl);
+ if (!is_supported_ctl_type(type)) {
+ ALOGE("unsupported type %d", (int)type);
+ return -1;
+ }
path_index = alloc_path_setting(path);
if (path_index < 0)
return -1;
/* initialise the new path setting */
path->setting[path_index].ctl_index = mixer_value->ctl_index;
path->setting[path_index].num_values = num_values;
- path->setting[path_index].value = malloc(num_values * sizeof(int));
- path->setting[path_index].value[0] = mixer_value->value;
+ path->setting[path_index].type = type;
+
+ size_t value_sz = sizeof_ctl_type(type);
+ path->setting[path_index].value.ptr = calloc(num_values, value_sz);
+ if (path->setting[path_index].type == MIXER_CTL_TYPE_BYTE)
+ path->setting[path_index].value.bytes[0] = mixer_value->value;
+ else if (path->setting[path_index].type == MIXER_CTL_TYPE_ENUM)
+ path->setting[path_index].value.enumerated[0] = mixer_value->value;
+ else
+ path->setting[path_index].value.integer[0] = mixer_value->value;
}
if (mixer_value->index == -1) {
/* set all values the same */
- for (i = 0; i < num_values; i++)
- path->setting[path_index].value[i] = mixer_value->value;
+ if (path->setting[path_index].type == MIXER_CTL_TYPE_BYTE) {
+ for (i = 0; i < num_values; i++)
+ path->setting[path_index].value.bytes[i] = mixer_value->value;
+ } else if (path->setting[path_index].type == MIXER_CTL_TYPE_ENUM) {
+ for (i = 0; i < num_values; i++)
+ path->setting[path_index].value.enumerated[i] = mixer_value->value;
+ } else {
+ for (i = 0; i < num_values; i++)
+ path->setting[path_index].value.integer[i] = mixer_value->value;
+ }
} else {
/* set only one value */
- path->setting[path_index].value[mixer_value->index] = mixer_value->value;
+ if (path->setting[path_index].type == MIXER_CTL_TYPE_BYTE)
+ path->setting[path_index].value.bytes[mixer_value->index] = mixer_value->value;
+ else if (path->setting[path_index].type == MIXER_CTL_TYPE_ENUM)
+ path->setting[path_index].value.enumerated[mixer_value->index] = mixer_value->value;
+ else
+ path->setting[path_index].value.integer[mixer_value->index] = mixer_value->value;
}
return 0;
type = mixer_ctl_get_type(ctl);
if (!is_supported_ctl_type(type))
continue;
-
- /* apply the new value(s) */
- memcpy(ar->mixer_state[ctl_index].new_value, path->setting[i].value,
- path->setting[i].num_values * sizeof(int));
+ size_t value_sz = sizeof_ctl_type(type);
+ memcpy(ar->mixer_state[ctl_index].new_value.ptr, path->setting[i].value.ptr,
+ path->setting[i].num_values * value_sz);
}
return 0;
static int path_reset(struct audio_route *ar, struct mixer_path *path)
{
unsigned int i;
- unsigned int j;
unsigned int ctl_index;
struct mixer_ctl *ctl;
enum mixer_ctl_type type;
type = mixer_ctl_get_type(ctl);
if (!is_supported_ctl_type(type))
continue;
-
+ size_t value_sz = sizeof_ctl_type(type);
/* reset the value(s) */
- memcpy(ar->mixer_state[ctl_index].new_value,
- ar->mixer_state[ctl_index].reset_value,
- ar->mixer_state[ctl_index].num_values * sizeof(int));
+ memcpy(ar->mixer_state[ctl_index].new_value.ptr,
+ ar->mixer_state[ctl_index].reset_value.ptr,
+ ar->mixer_state[ctl_index].num_values * value_sz);
}
return 0;
unsigned int i;
unsigned int ctl_index;
struct mixer_ctl *ctl;
- int value;
+ long value;
unsigned int id;
struct mixer_value mixer_value;
enum mixer_ctl_type type;
switch (mixer_ctl_get_type(ctl)) {
case MIXER_CTL_TYPE_BOOL:
case MIXER_CTL_TYPE_INT:
- value = (int) strtol((char *)attr_value, NULL, 0);
+ value = strtol((char *)attr_value, NULL, 0);
+ break;
+ case MIXER_CTL_TYPE_BYTE:
+ value = (unsigned char) strtol((char *)attr_value, NULL, 16);
break;
case MIXER_CTL_TYPE_ENUM:
value = mixer_enum_string_to_value(ctl, (char *)attr_value);
/* set only one value */
id = atoi((char *)attr_id);
if (id < ar->mixer_state[ctl_index].num_values)
- ar->mixer_state[ctl_index].new_value[id] = value;
+ if (type == MIXER_CTL_TYPE_BYTE)
+ ar->mixer_state[ctl_index].new_value.bytes[id] = value;
+ else if (type == MIXER_CTL_TYPE_ENUM)
+ ar->mixer_state[ctl_index].new_value.enumerated[id] = value;
+ else
+ ar->mixer_state[ctl_index].new_value.integer[id] = value;
else
ALOGE("value id out of range for mixer ctl '%s'",
mixer_ctl_get_name(ctl));
} else {
/* set all values the same */
for (i = 0; i < ar->mixer_state[ctl_index].num_values; i++)
- ar->mixer_state[ctl_index].new_value[i] = value;
+ if (type == MIXER_CTL_TYPE_BYTE)
+ ar->mixer_state[ctl_index].new_value.bytes[i] = value;
+ else if (type == MIXER_CTL_TYPE_ENUM)
+ ar->mixer_state[ctl_index].new_value.enumerated[i] = value;
+ else
+ ar->mixer_state[ctl_index].new_value.integer[i] = value;
}
}
} else {
static int alloc_mixer_state(struct audio_route *ar)
{
unsigned int i;
- unsigned int j;
unsigned int num_values;
struct mixer_ctl *ctl;
enum mixer_ctl_type type;
ar->num_mixer_ctls = mixer_get_num_ctls(ar->mixer);
- ar->mixer_state = malloc(ar->num_mixer_ctls * sizeof(struct mixer_state));
+ ar->mixer_state = calloc(ar->num_mixer_ctls, sizeof(struct mixer_state));
if (!ar->mixer_state)
return -1;
if (!is_supported_ctl_type(type))
continue;
- ar->mixer_state[i].old_value = malloc(num_values * sizeof(int));
- ar->mixer_state[i].new_value = malloc(num_values * sizeof(int));
- ar->mixer_state[i].reset_value = malloc(num_values * sizeof(int));
+ size_t value_sz = sizeof_ctl_type(type);
+ ar->mixer_state[i].old_value.ptr = calloc(num_values, value_sz);
+ ar->mixer_state[i].new_value.ptr = calloc(num_values, value_sz);
+ ar->mixer_state[i].reset_value.ptr = calloc(num_values, value_sz);
if (type == MIXER_CTL_TYPE_ENUM)
- ar->mixer_state[i].old_value[0] = mixer_ctl_get_value(ctl, 0);
+ ar->mixer_state[i].old_value.enumerated[0] = mixer_ctl_get_value(ctl, 0);
else
- mixer_ctl_get_array(ctl, ar->mixer_state[i].old_value, num_values);
- memcpy(ar->mixer_state[i].new_value, ar->mixer_state[i].old_value,
- num_values * sizeof(int));
+ mixer_ctl_get_array(ctl, ar->mixer_state[i].old_value.ptr, num_values);
+
+ memcpy(ar->mixer_state[i].new_value.ptr, ar->mixer_state[i].old_value.ptr,
+ num_values * value_sz);
}
return 0;
if (!is_supported_ctl_type(type))
continue;
- free(ar->mixer_state[i].old_value);
- free(ar->mixer_state[i].new_value);
- free(ar->mixer_state[i].reset_value);
+ free(ar->mixer_state[i].old_value.ptr);
+ free(ar->mixer_state[i].new_value.ptr);
+ free(ar->mixer_state[i].reset_value.ptr);
}
free(ar->mixer_state);
/* if the value has changed, update the mixer */
bool changed = false;
- for (j = 0; j < num_values; j++) {
- if (ar->mixer_state[i].old_value[j] != ar->mixer_state[i].new_value[j]) {
- changed = true;
- break;
+ if (type == MIXER_CTL_TYPE_BYTE) {
+ for (j = 0; j < num_values; j++) {
+ if (ar->mixer_state[i].old_value.bytes[j] != ar->mixer_state[i].new_value.bytes[j]) {
+ changed = true;
+ break;
+ }
+ }
+ } else if (type == MIXER_CTL_TYPE_ENUM) {
+ for (j = 0; j < num_values; j++) {
+ if (ar->mixer_state[i].old_value.enumerated[j]
+ != ar->mixer_state[i].new_value.enumerated[j]) {
+ changed = true;
+ break;
+ }
+ }
+ } else {
+ for (j = 0; j < num_values; j++) {
+ if (ar->mixer_state[i].old_value.integer[j] != ar->mixer_state[i].new_value.integer[j]) {
+ changed = true;
+ break;
+ }
}
}
if (changed) {
if (type == MIXER_CTL_TYPE_ENUM)
- mixer_ctl_set_value(ctl, 0, ar->mixer_state[i].new_value[0]);
+ mixer_ctl_set_value(ctl, 0, ar->mixer_state[i].new_value.enumerated[0]);
else
- mixer_ctl_set_array(ctl, ar->mixer_state[i].new_value, num_values);
- memcpy(ar->mixer_state[i].old_value, ar->mixer_state[i].new_value,
- num_values * sizeof(int));
+ mixer_ctl_set_array(ctl, ar->mixer_state[i].new_value.ptr, num_values);
+
+ size_t value_sz = sizeof_ctl_type(type);
+ memcpy(ar->mixer_state[i].old_value.ptr, ar->mixer_state[i].new_value.ptr,
+ num_values * value_sz);
}
}
if (!is_supported_ctl_type(type))
continue;
- memcpy(ar->mixer_state[i].reset_value, ar->mixer_state[i].new_value,
- ar->mixer_state[i].num_values * sizeof(int));
+ size_t value_sz = sizeof_ctl_type(type);
+ memcpy(ar->mixer_state[i].reset_value.ptr, ar->mixer_state[i].new_value.ptr,
+ ar->mixer_state[i].num_values * value_sz);
}
}
if (!is_supported_ctl_type(type))
continue;
- memcpy(ar->mixer_state[i].new_value, ar->mixer_state[i].reset_value,
- ar->mixer_state[i].num_values * sizeof(int));
+ size_t value_sz = sizeof_ctl_type(type);
+ memcpy(ar->mixer_state[i].new_value.ptr, ar->mixer_state[i].reset_value.ptr,
+ ar->mixer_state[i].num_values * value_sz);
}
}
continue;
}
+ size_t value_sz = sizeof_ctl_type(type);
/* if any value has changed, update the mixer */
for (j = 0; j < ms->num_values; j++) {
- if (ms->old_value[j] != ms->new_value[j]) {
- if (type == MIXER_CTL_TYPE_ENUM)
- mixer_ctl_set_value(ms->ctl, 0, ms->new_value[0]);
- else
- mixer_ctl_set_array(ms->ctl, ms->new_value, ms->num_values);
- memcpy(ms->old_value, ms->new_value, ms->num_values * sizeof(int));
+ if (type == MIXER_CTL_TYPE_BYTE) {
+ if (ms->old_value.bytes[j] != ms->new_value.bytes[j]) {
+ mixer_ctl_set_array(ms->ctl, ms->new_value.bytes, ms->num_values);
+ memcpy(ms->old_value.bytes, ms->new_value.bytes, ms->num_values * value_sz);
+ break;
+ }
+ } else if (type == MIXER_CTL_TYPE_ENUM) {
+ if (ms->old_value.enumerated[j] != ms->new_value.enumerated[j]) {
+ mixer_ctl_set_value(ms->ctl, 0, ms->new_value.enumerated[0]);
+ memcpy(ms->old_value.enumerated, ms->new_value.enumerated,
+ ms->num_values * value_sz);
+ break;
+ }
+ } else if (ms->old_value.integer[j] != ms->new_value.integer[j]) {
+ mixer_ctl_set_array(ms->ctl, ms->new_value.integer, ms->num_values);
+ memcpy(ms->old_value.integer, ms->new_value.integer, ms->num_values * value_sz);
break;
}
}
FILE *file;
int bytes_read;
void *buf;
- int i;
struct audio_route *ar;
ar = calloc(1, sizeof(struct audio_route));
return ar;
err_parse:
+ path_free(ar);
XML_ParserFree(parser);
err_parser_create:
fclose(file);
{
free_mixer_state(ar);
mixer_close(ar->mixer);
+ path_free(ar);
free(ar);
}
LOCAL_SRC_FILES:= \
channels.c \
+ conversion.cpp \
fifo.c \
fixedfft.cpp.arm \
format.c \
+ limiter.c \
minifloat.c \
primitives.c \
resampler.c \
liblog \
libspeexresampler
+LOCAL_CFLAGS := -Werror -Wall
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
channels.c \
fifo.c \
format.c \
+ limiter.c \
minifloat.c \
primitives.c \
roundup.c
LOCAL_C_INCLUDES += \
$(call include-path-for, audio-utils)
-LOCAL_CFLAGS := -D__unused=
+LOCAL_CFLAGS := -Werror -Wall
+LOCAL_CFLAGS += -D__unused='__attribute__((unused))'
include $(BUILD_HOST_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES += \
$(call include-path-for, audio-utils)
-LOCAL_CFLAGS := -UHAVE_STDERR
+LOCAL_CFLAGS := -Werror -Wall
+LOCAL_CFLAGS += -UHAVE_STDERR
include $(BUILD_STATIC_LIBRARY)
#LOCAL_SHARED_LIBRARIES := libaudioutils
+LOCAL_CFLAGS := -Werror -Wall
+
include $(BUILD_HOST_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES += \
$(call include-path-for, audio-utils)
+LOCAL_CFLAGS := -Werror -Wall
+
include $(BUILD_STATIC_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))
--- /dev/null
+# Doxyfile 1.8.6
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = "My Project"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. Do not use file names with spaces, bibtex cannot handle them. See
+# also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = include/audio_utils/ include/audio_utils/spdif/
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
+# defined cascading style sheet that is included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet file to the output directory. For an example
+# see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavours of web server based searching depending on the
+# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
+# searching and an index file used by the script. When EXTERNAL_SEARCH is
+# enabled the indexing and searching needs to be provided by external tools. See
+# the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
+# replace them by respectively the title of the page, the current date and time,
+# only the current date, the version number of doxygen, the project name (see
+# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all refrences to function-like macros that are alone on a line, have an
+# all uppercase name, and do not end with a semicolon. Such function macros are
+# typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have an unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font n the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = YES
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
--- /dev/null
+# Doxyfile 1.8.6
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = "My Project"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. Do not use file names with spaces, bibtex cannot handle them. See
+# also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT =
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
+# defined cascading style sheet that is included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet file to the output directory. For an example
+# see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavours of web server based searching depending on the
+# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
+# searching and an index file used by the script. When EXTERNAL_SEARCH is
+# enabled the indexing and searching needs to be provided by external tools. See
+# the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
+# replace them by respectively the title of the page, the current date and time,
+# only the current date, the version number of doxygen, the project name (see
+# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all refrences to function-like macros that are alone on a line, have an
+# all uppercase name, and do not end with a semicolon. Such function macros are
+# typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have an unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font n the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = YES
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
--- /dev/null
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "audio_utils_conversion"
+
+#include <math.h>
+#include <audio_utils/conversion.h>
+#include <utils/Log.h>
+#include <audio_utils/limiter.h>
+
+// TODO: Speed up for special case of 2 channels?
+void mono_blend(void *buf, audio_format_t format, size_t channelCount, size_t frames, bool limit) {
+ if (channelCount < 2) {
+ return;
+ }
+ switch (format) {
+ case AUDIO_FORMAT_PCM_16_BIT: {
+ int16_t *out = (int16_t *)buf;
+ for (size_t i = 0; i < frames; ++i) {
+ const int16_t *in = out;
+ int accum = 0;
+ for (size_t j = 0; j < channelCount; ++j) {
+ accum += *in++;
+ }
+ accum /= channelCount; // round to 0
+ for (size_t j = 0; j < channelCount; ++j) {
+ *out++ = accum;
+ }
+ }
+ } break;
+ case AUDIO_FORMAT_PCM_FLOAT: {
+ float *out = (float *)buf;
+ const float recipdiv = 1. / channelCount;
+ for (size_t i = 0; i < frames; ++i) {
+ const float *in = out;
+ float accum = 0;
+ for (size_t j = 0; j < channelCount; ++j) {
+ accum += *in++;
+ }
+ if (limit && channelCount == 2) {
+ accum = limiter(accum * M_SQRT1_2);
+ } else {
+ accum *= recipdiv;
+ }
+ for (size_t j = 0; j < channelCount; ++j) {
+ *out++ = accum;
+ }
+ }
+ } break;
+ default:
+ ALOGE("mono_blend: invalid format %d", format);
+ break;
+ }
+}
ALOGV("echo_reference_read(): EchoPathDelayDeviation between reference and DMA [%"
PRId64 "]", deltaNs);
- if (abs(deltaNs) >= MIN_DELAY_DELTA_NS) {
+ if (llabs(deltaNs) >= MIN_DELAY_DELTA_NS) {
// smooth the variation and update the reference buffer only
// if a deviation in the same direction is observed for more than MIN_DELTA_NUM
// consecutive reads.
#ifndef ANDROID_AUDIO_CHANNELS_H
#define ANDROID_AUDIO_CHANNELS_H
+/** \cond */
__BEGIN_DECLS
+/** \endcond */
-/*
+/**
* Expands or contracts sample data from one interleaved channel format to another.
* Expanded channels are filled with zeros and put at the end of each audio frame.
* Contracted channels are omitted from the end of each audio frame.
- * in_buff points to the buffer of samples
- * in_buff_channels Specifies the number of channels in the input buffer.
- * out_buff points to the buffer to receive converted samples.
- * out_buff_channels Specifies the number of channels in the output buffer.
- * sample_size_in_bytes Specifies the number of bytes per sample. 1, 2, 3, 4 are
+ *
+ * \param in_buff points to the buffer of samples
+ * \param in_buff_chans Specifies the number of channels in the input buffer.
+ * \param out_buff points to the buffer to receive converted samples.
+ * \param out_buff_chans Specifies the number of channels in the output buffer.
+ * \param sample_size_in_bytes Specifies the number of bytes per sample. 1, 2, 3, 4 are
* currently valid.
- * num_in_bytes size of input buffer in BYTES
- * returns
+ * \param num_in_bytes size of input buffer in BYTES
+ *
+ * \return
* the number of BYTES of output data or 0 if an error occurs.
- * NOTE
+ *
+ * \note
* The out and sums buffers must either be completely separate (non-overlapping), or
* they must both start at the same address. Partially overlapping buffers are not supported.
*/
size_t adjust_channels(const void* in_buff, size_t in_buff_chans,
void* out_buff, size_t out_buff_chans,
unsigned sample_size_in_bytes, size_t num_in_bytes);
+
+/** \cond */
__END_DECLS
+/** \endcond */
#endif
--- /dev/null
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIO_CONVERSION_H
+#define ANDROID_AUDIO_CONVERSION_H
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <system/audio.h>
+
+/** \cond */
+__BEGIN_DECLS
+/** \endcond */
+
+// for in-place conversion routines
+
+/**
+ * In-place mono blend using the arithmetic average of the channels in each audio frame.
+ *
+ * \param buf buffer of frames
+ * \param format one of AUDIO_FORMAT_PCM_16_BIT or AUDIO_FORMAT_PCM_FLOAT
+ * \param channelCount number of channels per frame
+ * \param frames number of frames in buffer
+ * \param limit whether to use a limiter (experimental, currently only for stereo float)
+ *
+ * \return
+ * none
+ *
+ */
+
+void mono_blend(void *buf, audio_format_t format, size_t channelCount, size_t frames,
+ bool limit = false);
+
+/** \cond */
+__END_DECLS
+/** \endcond */
+
+#endif
__BEGIN_DECLS
-/* Buffer descriptor used by read() and write() methods, including the time stamp and delay. */
+/** Buffer descriptor used by read() and write() methods, including the time stamp and delay. */
struct echo_reference_buffer {
void *raw; // pointer to audio frame
size_t frame_count; // number of frames in buffer
struct timespec time_stamp; // time stamp for this buffer (see comment below)
// default ALSA gettimeofday() format
};
+
/**
* + as input:
* - delay_ns is the delay introduced by playback buffers
volatile int32_t mRear; // frame index of next frame slot available to write, or write index
};
-// Initialize a FIFO object.
-// Input parameters:
-// fifo Pointer to the FIFO object.
-// frameCount Max number of significant frames to be stored in the FIFO > 0.
-// If writes and reads always use the same count, and that count is a divisor of
-// frameCount, then the writes and reads will never do a partial transfer.
-// frameSize Size of each frame in bytes.
-// buffer Pointer to a caller-allocated buffer of frameCount frames.
+/**
+ * Initialize a FIFO object.
+ *
+ * \param fifo Pointer to the FIFO object.
+ * \param frameCount Max number of significant frames to be stored in the FIFO > 0.
+ * If writes and reads always use the same count, and that count is a divisor of
+ * frameCount, then the writes and reads will never do a partial transfer.
+ * \param frameSize Size of each frame in bytes.
+ * \param buffer Pointer to a caller-allocated buffer of frameCount frames.
+ */
void audio_utils_fifo_init(struct audio_utils_fifo *fifo, size_t frameCount, size_t frameSize,
void *buffer);
-// De-initialize a FIFO object.
-// Input parameters:
-// fifo Pointer to the FIFO object.
+/**
+ * De-initialize a FIFO object.
+ *
+ * \param fifo Pointer to the FIFO object.
+ */
void audio_utils_fifo_deinit(struct audio_utils_fifo *fifo);
-// Write to FIFO.
-// Input parameters:
-// fifo Pointer to the FIFO object.
-// buffer Pointer to source buffer containing 'count' frames of data.
-// Returns actual number of frames written <= count.
-// The actual transfer count may be zero if the FIFO is full,
-// or partial if the FIFO was almost full.
-// A negative return value indicates an error. Currently there are no errors defined.
+/**
+ * Write to FIFO.
+ *
+ * \param fifo Pointer to the FIFO object.
+ * \param buffer Pointer to source buffer containing 'count' frames of data.
+ * \param count Desired number of frames to write.
+ *
+ * \return actual number of frames written <= count.
+ *
+ * The actual transfer count may be zero if the FIFO is full,
+ * or partial if the FIFO was almost full.
+ * A negative return value indicates an error. Currently there are no errors defined.
+ */
ssize_t audio_utils_fifo_write(struct audio_utils_fifo *fifo, const void *buffer, size_t count);
-// Read from FIFO.
-// Input parameters:
-// fifo Pointer to the FIFO object.
-// buffer Pointer to destination buffer to be filled with up to 'count' frames of data.
-// Returns actual number of frames read <= count.
-// The actual transfer count may be zero if the FIFO is empty,
-// or partial if the FIFO was almost empty.
-// A negative return value indicates an error. Currently there are no errors defined.
+/** Read from FIFO.
+ *
+ * \param fifo Pointer to the FIFO object.
+ * \param buffer Pointer to destination buffer to be filled with up to 'count' frames of data.
+ * \param count Desired number of frames to read.
+ *
+ * \return actual number of frames read <= count.
+ *
+ * The actual transfer count may be zero if the FIFO is empty,
+ * or partial if the FIFO was almost empty.
+ * A negative return value indicates an error. Currently there are no errors defined.
+ */
ssize_t audio_utils_fifo_read(struct audio_utils_fifo *fifo, void *buffer, size_t count);
#ifdef __cplusplus
#include <stdint.h>
#include <sys/cdefs.h>
+/** \cond */
__BEGIN_DECLS
+/** \endcond */
-/* See description in fixedfft.cpp */
+/** See description in fixedfft.cpp */
extern void fixed_fft_real(int n, int32_t *v);
+/** \cond */
__END_DECLS
+/** \endcond */
#endif // ANDROID_AUDIO_FIXEDFFT_H
#include <sys/cdefs.h>
#include <system/audio.h>
+/** \cond */
__BEGIN_DECLS
+/** \endcond */
-/* Copy buffers with conversion between buffer sample formats.
+/**
+ * Copy buffers with conversion between buffer sample formats.
*
- * dst Destination buffer
- * dst_format Destination buffer format
- * src Source buffer
- * src_format Source buffer format
- * count Number of samples to copy
+ * \param dst Destination buffer
+ * \param dst_format Destination buffer format
+ * \param src Source buffer
+ * \param src_format Source buffer format
+ * \param count Number of samples to copy
*
* Allowed format conversions are given by either case 1 or 2 below:
*
* AUDIO_FORMAT_PCM_FLOAT, and the other format type is one of:
*
* AUDIO_FORMAT_PCM_16_BIT
+ * <BR>
* AUDIO_FORMAT_PCM_FLOAT
+ * <BR>
* AUDIO_FORMAT_PCM_8_BIT
+ * <BR>
* AUDIO_FORMAT_PCM_24_BIT_PACKED
+ * <BR>
* AUDIO_FORMAT_PCM_32_BIT
+ * <BR>
* AUDIO_FORMAT_PCM_8_24_BIT
*
* 2) Both dst_format and src_format are identical and of the list given
const void *src, audio_format_t src_format, size_t count);
-/* This function creates an index array for converting audio data with different
+/**
+ * This function creates an index array for converting audio data with different
* channel position and index masks, used by memcpy_by_index_array().
- * Returns the number of array elements required.
- * This may be greater than idxcount, so the return value should be checked
- * if idxary size is less than 32. Returns zero if the input masks are unrecognized.
*
* Note that idxary is a caller allocated array
* of at least as many channels as present in the dst_mask.
*
* Parameters:
- * idxary Updated array of indices of channels in the src frame for the dst frame
- * idxcount Number of caller allocated elements in idxary
- * dst_mask Bit mask corresponding to destination channels present
- * src_mask Bit mask corresponding to source channels present
+ * \param idxary Updated array of indices of channels in the src frame for the dst frame
+ * \param arysize Number of caller allocated elements in idxary
+ * \param dst_channel_mask Bit mask corresponding to destination channels present
+ * \param src_channel_mask Bit mask corresponding to source channels present
+ *
+ * \return the number of array elements required.
+ * This may be greater than idxcount, so the return value should be checked
+ * if idxary size is less than 32. Returns zero if the input masks are unrecognized.
*/
size_t memcpy_by_index_array_initialization_from_channel_mask(int8_t *idxary, size_t arysize,
audio_channel_mask_t dst_channel_mask, audio_channel_mask_t src_channel_mask);
+/** \cond */
__END_DECLS
+/** \endcond */
#endif // ANDROID_AUDIO_FORMAT_H
--- /dev/null
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIO_LIMITER_H
+#define ANDROID_AUDIO_LIMITER_H
+
+#include <sys/cdefs.h>
+
+/** \cond */
+__BEGIN_DECLS
+/** \endcond */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ /**
+ * This limiter function is the identity for [-sqrt(0.5), sqrt(0.5)]
+ * and then approximates atan or spline.
+ * \param in input in range [-sqrt(2), sqrt(2)]; out of range, inf, and NaN are not permitted
+ * \return the limited output in range no larger than [-1.0, 1.0].
+ * The implementation is permitted to limit the output to a slightly smaller range,
+ * so the minimum and maximum outputs may not be achievable.
+ */
+ extern float limiter(float in);
+#ifdef __cplusplus
+}
+#endif
+
+/** \cond */
+__END_DECLS
+/** \endcond */
+
+#endif /* !ANDROID_AUDIO_LIMITER_H */
#include <stdint.h>
#include <sys/cdefs.h>
+/** \cond */
__BEGIN_DECLS
+/** \endcond */
-/* A single gain expressed as minifloat */
+/** A single gain expressed as minifloat */
typedef uint16_t gain_minifloat_t;
-/* A pair of gain_minifloat_t packed into a single word */
+/** A pair of gain_minifloat_t packed into a single word */
typedef uint32_t gain_minifloat_packed_t;
-/* The nominal range of a gain, expressed as a float */
+/** The nominal range of a gain, expressed as a float */
#define GAIN_FLOAT_ZERO 0.0f
#define GAIN_FLOAT_UNITY 1.0f
-/* Unity gain expressed as a minifloat */
+/** Unity gain expressed as a minifloat */
#define GAIN_MINIFLOAT_UNITY 0xE000
-/* Pack a pair of gain_mini_float_t into a combined gain_minifloat_packed_t */
+/** Pack a pair of gain_mini_float_t into a combined gain_minifloat_packed_t */
static inline gain_minifloat_packed_t gain_minifloat_pack(gain_minifloat_t left,
gain_minifloat_t right)
{
return (right << 16) | left;
}
-/* Unpack a gain_minifloat_packed_t into the two gain_minifloat_t components */
+/** Unpack a gain_minifloat_packed_t into the two gain_minifloat_t components */
static inline gain_minifloat_t gain_minifloat_unpack_left(gain_minifloat_packed_t packed)
{
return packed & 0xFFFF;
return packed >> 16;
}
-/* A pair of unity gains expressed as a gain_minifloat_packed_t */
+/** A pair of unity gains expressed as a gain_minifloat_packed_t */
#define GAIN_MINIFLOAT_PACKED_UNITY gain_minifloat_pack(GAIN_MINIFLOAT_UNITY, GAIN_MINIFLOAT_UNITY)
-/* Convert a float to the internal representation used for gains.
+/**
+ * Convert a float to the internal representation used for gains.
* The nominal range [0.0, 1.0], but the hard range is [0.0, 2.0).
* Negative and underflow values are converted to 0.0,
* and values larger than the hard maximum are truncated to the hard maximum.
*/
gain_minifloat_t gain_from_float(float f);
-/* Convert the internal representation used for gains to float */
+/** Convert the internal representation used for gains to float */
float float_from_gain(gain_minifloat_t gain);
+/** \cond */
__END_DECLS
+/** \endcond */
#endif // ANDROID_AUDIO_MINIFLOAT_H
#include <stdlib.h>
#include <sys/cdefs.h>
+/** \cond */
__BEGIN_DECLS
+/** \endcond */
-/* The memcpy_* conversion routines are designed to work in-place on same dst as src
+/**
+ * \file primitives.h
+ * The memcpy_* conversion routines are designed to work in-place on same dst as src
* buffers only if the types shrink on copy, with the exception of memcpy_to_i16_from_u8().
* This allows the loops to go upwards for faster cache access (and may be more flexible
* for future optimization later).
*/
void ditherAndClamp(int32_t* out, const int32_t *sums, size_t c);
-/* Expand and copy samples from unsigned 8-bit offset by 0x80 to signed 16-bit.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+/**
+ * Expand and copy samples from unsigned 8-bit offset by 0x80 to signed 16-bit.
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must either be completely separate (non-overlapping), or
* they must both start at the same address. Partially overlapping buffers are not supported.
*/
void memcpy_to_i16_from_u8(int16_t *dst, const uint8_t *src, size_t count);
-/* Shrink and copy samples from signed 16-bit to unsigned 8-bit offset by 0x80.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+/**
+ * Shrink and copy samples from signed 16-bit to unsigned 8-bit offset by 0x80.
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must either be completely separate (non-overlapping), or
* they must both start at the same address. Partially overlapping buffers are not supported.
* The conversion is done by truncation, without dithering, so it loses resolution.
*/
void memcpy_to_u8_from_i16(uint8_t *dst, const int16_t *src, size_t count);
-/* Copy samples from float to unsigned 8-bit offset by 0x80.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+/**
+ * Copy samples from float to unsigned 8-bit offset by 0x80.
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must either be completely separate (non-overlapping), or
* they must both start at the same address. Partially overlapping buffers are not supported.
* The conversion is done by truncation, without dithering, so it loses resolution.
*/
void memcpy_to_u8_from_float(uint8_t *dst, const float *src, size_t count);
-/* Shrink and copy samples from signed 32-bit fixed-point Q0.31 to signed 16-bit Q0.15.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+/**
+ * Shrink and copy samples from signed 32-bit fixed-point Q0.31 to signed 16-bit Q0.15.
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must either be completely separate (non-overlapping), or
* they must both start at the same address. Partially overlapping buffers are not supported.
* The conversion is done by truncation, without dithering, so it loses resolution.
*/
void memcpy_to_i16_from_i32(int16_t *dst, const int32_t *src, size_t count);
-/* Shrink and copy samples from single-precision floating-point to signed 16-bit.
+/**
+ * Shrink and copy samples from single-precision floating-point to signed 16-bit.
* Each float should be in the range -1.0 to 1.0. Values outside that range are clamped,
* refer to clamp16_from_float().
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must either be completely separate (non-overlapping), or
* they must both start at the same address. Partially overlapping buffers are not supported.
* The conversion is done by truncation, without dithering, so it loses resolution.
*/
void memcpy_to_i16_from_float(int16_t *dst, const float *src, size_t count);
-/* Copy samples from signed fixed-point 32-bit Q4.27 to single-precision floating-point.
+/**
+ * Copy samples from signed fixed-point 32-bit Q4.27 to single-precision floating-point.
* The nominal output float range is [-1.0, 1.0] if the fixed-point range is
* [0xf8000000, 0x07ffffff]. The full float range is [-16.0, 16.0]. Note the closed range
* at 1.0 and 16.0 is due to rounding on conversion to float. See float_from_q4_27() for details.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must either be completely separate (non-overlapping), or
* they must both start at the same address. Partially overlapping buffers are not supported.
*/
void memcpy_to_float_from_q4_27(float *dst, const int32_t *src, size_t count);
-/* Copy samples from signed fixed-point 16 bit Q0.15 to single-precision floating-point.
+/**
+ * Copy samples from signed fixed-point 16 bit Q0.15 to single-precision floating-point.
* The output float range is [-1.0, 1.0) for the fixed-point range [0x8000, 0x7fff].
* No rounding is needed as the representation is exact.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must be completely separate.
*/
void memcpy_to_float_from_i16(float *dst, const int16_t *src, size_t count);
-/* Copy samples from unsigned fixed-point 8 bit to single-precision floating-point.
+/**
+ * Copy samples from unsigned fixed-point 8 bit to single-precision floating-point.
* The output float range is [-1.0, 1.0) for the fixed-point range [0x00, 0xFF].
* No rounding is needed as the representation is exact.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must be completely separate.
*/
void memcpy_to_float_from_u8(float *dst, const uint8_t *src, size_t count);
-/* Copy samples from signed fixed-point packed 24 bit Q0.23 to single-precision floating-point.
+/**
+ * Copy samples from signed fixed-point packed 24 bit Q0.23 to single-precision floating-point.
* The packed 24 bit input is stored in native endian format in a uint8_t byte array.
* The output float range is [-1.0, 1.0) for the fixed-point range [0x800000, 0x7fffff].
* No rounding is needed as the representation is exact.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must be completely separate.
*/
void memcpy_to_float_from_p24(float *dst, const uint8_t *src, size_t count);
-/* Copy samples from signed fixed-point packed 24 bit Q0.23 to signed fixed point 16 bit Q0.15.
+/**
+ * Copy samples from signed fixed-point packed 24 bit Q0.23 to signed fixed point 16 bit Q0.15.
* The packed 24 bit output is stored in native endian format in a uint8_t byte array.
* The data is truncated without rounding.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must either be completely separate (non-overlapping), or
* they must both start at the same address. Partially overlapping buffers are not supported.
*/
void memcpy_to_i16_from_p24(int16_t *dst, const uint8_t *src, size_t count);
-/* Copy samples from signed fixed-point packed 24 bit Q0.23 to signed fixed-point 32-bit Q0.31.
+/**
+ * Copy samples from signed fixed-point packed 24 bit Q0.23 to signed fixed-point 32-bit Q0.31.
* The packed 24 bit input is stored in native endian format in a uint8_t byte array.
* The output data range is [0x80000000, 0x7fffff00] at intervals of 0x100.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must be completely separate.
*/
void memcpy_to_i32_from_p24(int32_t *dst, const uint8_t *src, size_t count);
-/* Copy samples from signed fixed point 16 bit Q0.15 to signed fixed-point packed 24 bit Q0.23.
+/**
+ * Copy samples from signed fixed point 16 bit Q0.15 to signed fixed-point packed 24 bit Q0.23.
* The packed 24 bit output is assumed to be a native-endian uint8_t byte array.
* The output data range is [0x800000, 0x7fff00] (not full).
* Nevertheless there is no DC offset on the output, if the input has no DC offset.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must be completely separate.
*/
void memcpy_to_p24_from_i16(uint8_t *dst, const int16_t *src, size_t count);
-/* Copy samples from single-precision floating-point to signed fixed-point packed 24 bit Q0.23.
+/**
+ * Copy samples from single-precision floating-point to signed fixed-point packed 24 bit Q0.23.
* The packed 24 bit output is assumed to be a native-endian uint8_t byte array.
* The data is clamped and rounded to nearest, ties away from zero. See clamp24_from_float()
* for details.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must either be completely separate (non-overlapping), or
* they must both start at the same address. Partially overlapping buffers are not supported.
*/
void memcpy_to_p24_from_float(uint8_t *dst, const float *src, size_t count);
-/* Copy samples from signed fixed-point 32-bit Q8.23 to signed fixed-point packed 24 bit Q0.23.
+/**
+ * Copy samples from signed fixed-point 32-bit Q8.23 to signed fixed-point packed 24 bit Q0.23.
* The packed 24 bit output is assumed to be a native-endian uint8_t byte array.
* The data is clamped to the range is [0x800000, 0x7fffff].
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must be completely separate.
*/
void memcpy_to_p24_from_q8_23(uint8_t *dst, const int32_t *src, size_t count);
-/* Shrink and copy samples from signed 32-bit fixed-point Q0.31
+/**
+ * Shrink and copy samples from signed 32-bit fixed-point Q0.31
* to signed fixed-point packed 24 bit Q0.23.
* The packed 24 bit output is assumed to be a native-endian uint8_t byte array.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must either be completely separate (non-overlapping), or
* they must both start at the same address. Partially overlapping buffers are not supported.
* The conversion is done by truncation, without dithering, so it loses resolution.
*/
void memcpy_to_p24_from_i32(uint8_t *dst, const int32_t *src, size_t count);
-/* Copy samples from signed fixed point 16-bit Q0.15 to signed fixed-point 32-bit Q8.23.
+/**
+ * Copy samples from signed fixed point 16-bit Q0.15 to signed fixed-point 32-bit Q8.23.
* The output data range is [0xff800000, 0x007fff00] at intervals of 0x100.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must be completely separate.
*/
void memcpy_to_q8_23_from_i16(int32_t *dst, const int16_t *src, size_t count);
-/* Copy samples from single-precision floating-point to signed fixed-point 32-bit Q8.23.
+/**
+ * Copy samples from single-precision floating-point to signed fixed-point 32-bit Q8.23.
* This copy will clamp the Q8.23 representation to [0xff800000, 0x007fffff] even though there
* are guard bits available. Fractional lsb is rounded to nearest, ties away from zero.
* See clamp24_from_float() for details.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must either be completely separate (non-overlapping), or
* they must both start at the same address. Partially overlapping buffers are not supported.
*/
void memcpy_to_q8_23_from_float_with_clamp(int32_t *dst, const float *src, size_t count);
-/* Copy samples from signed fixed point packed 24-bit Q0.23 to signed fixed-point 32-bit Q8.23.
+/**
+ * Copy samples from signed fixed point packed 24-bit Q0.23 to signed fixed-point 32-bit Q8.23.
* The output data range is [0xff800000, 0x007fffff].
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must be completely separate.
*/
void memcpy_to_q8_23_from_p24(int32_t *dst, const uint8_t *src, size_t count);
-/* Copy samples from single-precision floating-point to signed fixed-point 32-bit Q4.27.
+/**
+ * Copy samples from single-precision floating-point to signed fixed-point 32-bit Q4.27.
* The conversion will use the full available Q4.27 range, including guard bits.
* Fractional lsb is rounded to nearest, ties away from zero.
* See clampq4_27_from_float() for details.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must either be completely separate (non-overlapping), or
* they must both start at the same address. Partially overlapping buffers are not supported.
*/
void memcpy_to_q4_27_from_float(int32_t *dst, const float *src, size_t count);
-/* Copy samples from signed fixed-point 32-bit Q8.23 to signed fixed point 16-bit Q0.15.
+/**
+ * Copy samples from signed fixed-point 32-bit Q8.23 to signed fixed point 16-bit Q0.15.
* The data is clamped, and truncated without rounding.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must either be completely separate (non-overlapping), or
* they must both start at the same address. Partially overlapping buffers are not supported.
*/
void memcpy_to_i16_from_q8_23(int16_t *dst, const int32_t *src, size_t count);
-/* Copy samples from signed fixed-point 32-bit Q8.23 to single-precision floating-point.
+/**
+ * Copy samples from signed fixed-point 32-bit Q8.23 to single-precision floating-point.
* The nominal output float range is [-1.0, 1.0) for the fixed-point
* range [0xff800000, 0x007fffff]. The maximum output float range is [-256.0, 256.0).
* No rounding is needed as the representation is exact for nominal values.
* Rounding for overflow values is to nearest, ties to even.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must either be completely separate (non-overlapping), or
* they must both start at the same address. Partially overlapping buffers are not supported.
*/
void memcpy_to_float_from_q8_23(float *dst, const int32_t *src, size_t count);
-/* Copy samples from signed fixed point 16-bit Q0.15 to signed fixed-point 32-bit Q0.31.
+/**
+ * Copy samples from signed fixed point 16-bit Q0.15 to signed fixed-point 32-bit Q0.31.
* The output data range is [0x80000000, 0x7fff0000] at intervals of 0x10000.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must be completely separate.
*/
void memcpy_to_i32_from_i16(int32_t *dst, const int16_t *src, size_t count);
-/* Copy samples from single-precision floating-point to signed fixed-point 32-bit Q0.31.
+/**
+ * Copy samples from single-precision floating-point to signed fixed-point 32-bit Q0.31.
* If rounding is needed on truncation, the fractional lsb is rounded to nearest,
* ties away from zero. See clamp32_from_float() for details.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must either be completely separate (non-overlapping), or
* they must both start at the same address. Partially overlapping buffers are not supported.
*/
void memcpy_to_i32_from_float(int32_t *dst, const float *src, size_t count);
-/* Copy samples from signed fixed-point 32-bit Q0.31 to single-precision floating-point.
+/**
+ * Copy samples from signed fixed-point 32-bit Q0.31 to single-precision floating-point.
* The float range is [-1.0, 1.0] for the fixed-point range [0x80000000, 0x7fffffff].
* Rounding is done according to float_from_i32().
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of samples to copy
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to copy
+ *
* The destination and source buffers must either be completely separate (non-overlapping), or
* they must both start at the same address. Partially overlapping buffers are not supported.
*/
void memcpy_to_float_from_i32(float *dst, const int32_t *src, size_t count);
-/* Downmix pairs of interleaved stereo input 16-bit samples to mono output 16-bit samples.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of stereo frames to downmix
+/**
+ * Downmix pairs of interleaved stereo input 16-bit samples to mono output 16-bit samples.
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of stereo frames to downmix
+ *
* The destination and source buffers must be completely separate (non-overlapping).
* The current implementation truncates the mean rather than dither, but this may change.
*/
void downmix_to_mono_i16_from_stereo_i16(int16_t *dst, const int16_t *src, size_t count);
-/* Upmix mono input 16-bit samples to pairs of interleaved stereo output 16-bit samples by
+/**
+ * Upmix mono input 16-bit samples to pairs of interleaved stereo output 16-bit samples by
* duplicating.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of mono samples to upmix
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of mono samples to upmix
+ *
* The destination and source buffers must be completely separate (non-overlapping).
*/
void upmix_to_stereo_i16_from_mono_i16(int16_t *dst, const int16_t *src, size_t count);
-/* Downmix pairs of interleaved stereo input float samples to mono output float samples
+/**
+ * Downmix pairs of interleaved stereo input float samples to mono output float samples
* by averaging the stereo pair together.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of stereo frames to downmix
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of stereo frames to downmix
+ *
* The destination and source buffers must be completely separate (non-overlapping),
* or they must both start at the same address.
*/
void downmix_to_mono_float_from_stereo_float(float *dst, const float *src, size_t count);
-/* Upmix mono input float samples to pairs of interleaved stereo output float samples by
+/**
+ * Upmix mono input float samples to pairs of interleaved stereo output float samples by
* duplicating.
- * Parameters:
- * dst Destination buffer
- * src Source buffer
- * count Number of mono samples to upmix
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of mono samples to upmix
+ *
* The destination and source buffers must be completely separate (non-overlapping).
*/
void upmix_to_stereo_float_from_mono_float(float *dst, const float *src, size_t count);
-/* Return the total number of non-zero 32-bit samples */
+/**
+ * \return the total number of non-zero 32-bit samples.
+ */
size_t nonZeroMono32(const int32_t *samples, size_t count);
-/* Return the total number of non-zero 16-bit samples */
+/**
+ * \return the total number of non-zero 16-bit samples.
+ */
size_t nonZeroMono16(const int16_t *samples, size_t count);
-/* Return the total number of non-zero stereo frames, where a frame is considered non-zero
- * if either of its constituent 32-bit samples is non-zero
+/**
+ * \return the total number of non-zero stereo frames, where a frame is considered non-zero
+ * if either of its constituent 32-bit samples is non-zero.
*/
size_t nonZeroStereo32(const int32_t *frames, size_t count);
-/* Return the total number of non-zero stereo frames, where a frame is considered non-zero
- * if either of its constituent 16-bit samples is non-zero
+/**
+ * \return the total number of non-zero stereo frames, where a frame is considered non-zero
+ * if either of its constituent 16-bit samples is non-zero.
*/
size_t nonZeroStereo16(const int16_t *frames, size_t count);
-/* Copy frames, selecting source samples based on a source channel mask to fit
+/**
+ * Copy frames, selecting source samples based on a source channel mask to fit
* the destination channel mask. Unmatched channels in the destination channel mask
* are zero filled. Unmatched channels in the source channel mask are dropped.
* Channels present in the channel mask are represented by set bits in the
* uint32_t value and are matched without further interpretation.
- * Parameters:
- * dst Destination buffer
- * dst_mask Bit mask corresponding to destination channels present
- * src Source buffer
- * src_mask Bit mask corresponding to source channels present
- * sample_size Size of each sample in bytes. Must be 1, 2, 3, or 4.
- * count Number of frames to copy
+ *
+ * \param dst Destination buffer
+ * \param dst_mask Bit mask corresponding to destination channels present
+ * \param src Source buffer
+ * \param src_mask Bit mask corresponding to source channels present
+ * \param sample_size Size of each sample in bytes. Must be 1, 2, 3, or 4.
+ * \param count Number of frames to copy
+ *
* The destination and source buffers must be completely separate (non-overlapping).
* If the sample size is not in range, the function will abort.
*/
void memcpy_by_channel_mask(void *dst, uint32_t dst_mask,
const void *src, uint32_t src_mask, size_t sample_size, size_t count);
-/* Copy frames, selecting source samples based on an index array (idxary).
+/**
+ * Copy frames, selecting source samples based on an index array (idxary).
* The idxary[] consists of dst_channels number of elements.
* The ith element if idxary[] corresponds the ith destination channel.
* A non-negative value is the channel index in the source frame.
* A negative index (-1) represents filling with 0.
*
* Example: Swapping L and R channels for stereo streams
+ * <PRE>
* idxary[0] = 1;
* idxary[1] = 0;
+ * </PRE>
*
* Example: Copying a mono source to the front center 5.1 channel
+ * <PRE>
* idxary[0] = -1;
* idxary[1] = -1;
* idxary[2] = 0;
* idxary[3] = -1;
* idxary[4] = -1;
* idxary[5] = -1;
+ * </PRE>
*
* This copy allows swizzling of channels or replication of channels.
*
- * Parameters:
- * dst Destination buffer
- * dst_channels Number of destination channels per frame
- * src Source buffer
- * src_channels Number of source channels per frame
- * idxary Array of indices representing channels in the source frame
- * sample_size Size of each sample in bytes. Must be 1, 2, 3, or 4.
- * count Number of frames to copy
+ * \param dst Destination buffer
+ * \param dst_channels Number of destination channels per frame
+ * \param src Source buffer
+ * \param src_channels Number of source channels per frame
+ * \param idxary Array of indices representing channels in the source frame
+ * \param sample_size Size of each sample in bytes. Must be 1, 2, 3, or 4.
+ * \param count Number of frames to copy
+ *
* The destination and source buffers must be completely separate (non-overlapping).
* If the sample size is not in range, the function will abort.
*/
const void *src, uint32_t src_channels,
const int8_t *idxary, size_t sample_size, size_t count);
-/* Prepares an index array (idxary) from channel masks, which can be later
- * used by memcpy_by_index_array(). Returns the number of array elements required.
+/**
+ * Prepares an index array (idxary) from channel masks, which can be later
+ * used by memcpy_by_index_array().
+ *
+ * \return the number of array elements required.
* This may be greater than idxcount, so the return value should be checked
- * if idxary size is less than 32. Note that idxary is a caller allocated array
+ * if idxary size is less than 32.
+ *
+ * Note that idxary is a caller allocated array
* of at least as many channels as present in the dst_mask.
* Channels present in the channel mask are represented by set bits in the
* uint32_t value and are matched without further interpretation.
* This function is typically used for converting audio data with different
* channel position masks.
*
- * Parameters:
- * idxary Updated array of indices of channels in the src frame for the dst frame
- * idxcount Number of caller allocated elements in idxary
- * dst_mask Bit mask corresponding to destination channels present
- * src_mask Bit mask corresponding to source channels present
+ * \param idxary Updated array of indices of channels in the src frame for the dst frame
+ * \param idxcount Number of caller allocated elements in idxary
+ * \param dst_mask Bit mask corresponding to destination channels present
+ * \param src_mask Bit mask corresponding to source channels present
*/
size_t memcpy_by_index_array_initialization(int8_t *idxary, size_t idxcount,
uint32_t dst_mask, uint32_t src_mask);
-/* Prepares an index array (idxary) from channel masks, which can be later
- * used by memcpy_by_index_array(). Returns the number of array elements required.
+/**
+ * Prepares an index array (idxary) from channel masks, which can be later
+ * used by memcpy_by_index_array().
+ *
+ * \return the number of array elements required.
*
* For a source channel index mask, the source channels will map to the destination
* channels as if counting the set bits in dst_mask in order from lsb to msb
* ith SET bit of dst_mask and the ith destination channel. Hence, a zero ith
* bit of the src_mask indicates that the ith destination channel plays silence.
*
- * Parameters:
- * idxary Updated array of indices of channels in the src frame for the dst frame
- * idxcount Number of caller allocated elements in idxary
- * dst_mask Bit mask corresponding to destination channels present
- * src_mask Bit mask corresponding to source channels present
+ * \param idxary Updated array of indices of channels in the src frame for the dst frame
+ * \param idxcount Number of caller allocated elements in idxary
+ * \param dst_mask Bit mask corresponding to destination channels present
+ * \param src_mask Bit mask corresponding to source channels present
*/
size_t memcpy_by_index_array_initialization_src_index(int8_t *idxary, size_t idxcount,
uint32_t dst_mask, uint32_t src_mask);
-/* Prepares an index array (idxary) from channel mask bits, which can be later
- * used by memcpy_by_index_array(). Returns the number of array elements required.
+/**
+ * Prepares an index array (idxary) from channel mask bits, which can be later
+ * used by memcpy_by_index_array().
+ *
+ * \return the number of array elements required.
*
* This initialization is for a destination channel index mask from a positional
* source mask.
* of set destination bits (unlikely), the corresponding source channel will
* be dropped.
*
- * Parameters:
- * idxary Updated array of indices of channels in the src frame for the dst frame
- * idxcount Number of caller allocated elements in idxary
- * dst_mask Bit mask corresponding to destination channels present
- * src_mask Bit mask corresponding to source channels present
+ * \param idxary Updated array of indices of channels in the src frame for the dst frame
+ * \param idxcount Number of caller allocated elements in idxary
+ * \param dst_mask Bit mask corresponding to destination channels present
+ * \param src_mask Bit mask corresponding to source channels present
*/
size_t memcpy_by_index_array_initialization_dst_index(int8_t *idxary, size_t idxcount,
uint32_t dst_mask, uint32_t src_mask);
return sample;
}
-/*
+/**
* Convert a IEEE 754 single precision float [-1.0, 1.0) to int16_t [-32768, 32767]
* with clamping. Note the open bound at 1.0, values within 1/65536 of 1.0 map
* to 32767 instead of 32768 (early clamping due to the smaller positive integer subrange).
return u.i; /* Return lower 16 bits, the part of interest in the significand. */
}
-/*
+/**
* Convert a IEEE 754 single precision float [-1.0, 1.0) to uint8_t [0, 0xff]
* with clamping. Note the open bound at 1.0, values within 1/128 of 1.0 map
* to 255 instead of 256 (early clamping due to the smaller positive integer subrange).
return u.i; /* Return lower 8 bits, the part of interest in the significand. */
}
-/* Convert a single-precision floating point value to a Q0.23 integer value, stored in a
+/**
+ * Convert a single-precision floating point value to a Q0.23 integer value, stored in a
* 32 bit signed integer (technically stored as Q8.23, but clamped to Q0.23).
*
* Rounds to nearest, ties away from 0.
return f > 0 ? f + 0.5 : f - 0.5;
}
-/* Convert a signed fixed-point 32-bit Q8.23 value to a Q0.23 integer value,
+/**
+ * Convert a signed fixed-point 32-bit Q8.23 value to a Q0.23 integer value,
* stored in a 32-bit signed integer (technically stored as Q8.23, but clamped to Q0.23).
*
* Values outside the range [-0x800000, 0x7fffff] are clamped to that range.
}
}
-/* Convert a single-precision floating point value to a Q4.27 integer value.
+/**
+ * Convert a single-precision floating point value to a Q4.27 integer value.
* Rounds to nearest, ties away from 0.
*
* Values outside the range [-16.0, 16.0) are properly clamped to -2147483648 and 2147483647,
return f > 0 ? f + 0.5 : f - 0.5;
}
-/* Convert a single-precision floating point value to a Q0.31 integer value.
+/**
+ * Convert a single-precision floating point value to a Q0.31 integer value.
* Rounds to nearest, ties away from 0.
*
* Values outside the range [-1.0, 1.0) are properly clamped to -2147483648 and 2147483647,
return f > 0 ? f + 0.5 : f - 0.5;
}
-/* Convert a signed fixed-point 32-bit Q4.27 value to single-precision floating-point.
+/**
+ * Convert a signed fixed-point 32-bit Q4.27 value to single-precision floating-point.
* The nominal output float range is [-1.0, 1.0] if the fixed-point range is
* [0xf8000000, 0x07ffffff]. The full float range is [-16.0, 16.0].
*
return ival * scale;
}
-/* Convert an unsigned fixed-point 32-bit U4.28 value to single-precision floating-point.
+/**
+ * Convert an unsigned fixed-point 32-bit U4.28 value to single-precision floating-point.
* The nominal output float range is [0.0, 1.0] if the fixed-point range is
* [0x00000000, 0x10000000]. The full float range is [0.0, 16.0].
*
return uval * scale;
}
-/* Convert an unsigned fixed-point 16-bit U4.12 value to single-precision floating-point.
+/**
+ * Convert an unsigned fixed-point 16-bit U4.12 value to single-precision floating-point.
* The nominal output float range is [0.0, 1.0] if the fixed-point range is
* [0x0000, 0x1000]. The full float range is [0.0, 16.0).
*/
return uval * scale;
}
-/* Convert a single-precision floating point value to a U4.28 integer value.
+/**
+ * Convert a single-precision floating point value to a U4.28 integer value.
* Rounds to nearest, ties away from 0.
*
* Values outside the range [0, 16.0] are properly clamped to [0, 4294967295]
return f * scale + 0.5;
}
-/* Convert a single-precision floating point value to a U4.12 integer value.
+/**
+ * Convert a single-precision floating point value to a U4.12 integer value.
* Rounds to nearest, ties away from 0.
*
* Values outside the range [0, 16.0) are properly clamped to [0, 65535]
return f * scale + 0.5;
}
-/* Convert a signed fixed-point 16-bit Q0.15 value to single-precision floating-point.
+/**
+ * Convert a signed fixed-point 16-bit Q0.15 value to single-precision floating-point.
* The output float range is [-1.0, 1.0) for the fixed-point range
* [0x8000, 0x7fff].
*
return ival * scale;
}
-/* Convert an unsigned fixed-point 8-bit U0.8 value to single-precision floating-point.
+/**
+ * Convert an unsigned fixed-point 8-bit U0.8 value to single-precision floating-point.
* The nominal output float range is [-1.0, 1.0) if the fixed-point range is
* [0x00, 0xff].
*/
return ((int)uval - 128) * scale;
}
-/* Convert a packed 24bit Q0.23 value stored native-endian in a uint8_t ptr
+/**
+ * Convert a packed 24bit Q0.23 value stored native-endian in a uint8_t ptr
* to a signed fixed-point 32 bit integer Q0.31 value. The output Q0.31 range
* is [0x80000000, 0x7fffff00] for the fixed-point range [0x800000, 0x7fffff].
* Even though the output range is limited on the positive side, there is no
return (packed24[0] << 8) | (packed24[1] << 16) | (packed24[2] << 24);
}
-/* Convert a 32-bit Q0.31 value to single-precision floating-point.
+/**
+ * Convert a 32-bit Q0.31 value to single-precision floating-point.
* The output float range is [-1.0, 1.0] for the fixed-point range
* [0x80000000, 0x7fffffff].
*
return ival * scale;
}
-/* Convert a packed 24bit Q0.23 value stored native endian in a uint8_t ptr
+/**
+ * Convert a packed 24bit Q0.23 value stored native endian in a uint8_t ptr
* to single-precision floating-point. The output float range is [-1.0, 1.0)
* for the fixed-point range [0x800000, 0x7fffff].
*
return float_from_i32(i32_from_p24(packed24));
}
-/* Convert a 24-bit Q8.23 value to single-precision floating-point.
+/**
+ * Convert a 24-bit Q8.23 value to single-precision floating-point.
* The nominal output float range is [-1.0, 1.0) for the fixed-point
* range [0xff800000, 0x007fffff]. The maximum float range is [-256.0, 256.0).
*
#endif
}
+/** \cond */
__END_DECLS
+/** \endcond */
#endif // ANDROID_AUDIO_PRIMITIVES_H
size_t frame_count;
};
-/* call back interface used by the resampler to get new data */
+/** call back interface used by the resampler to get new data */
struct resampler_buffer_provider
{
/**
struct resampler_buffer *buffer);
};
-/* resampler interface */
+/** resampler interface */
struct resampler_itfe {
/**
* reset resampler state
int16_t *out,
size_t *outFrameCount);
/**
- * return the latency introduced by the resampler in ns.
+ * \return the latency introduced by the resampler in ns.
*/
int32_t (*delay_ns)(struct resampler_itfe *resampler);
};
extern "C" {
#endif
-// Round up to the next highest power of 2
+/** Round up to the next highest power of 2 */
unsigned roundup(unsigned v);
#ifdef __cplusplus
#include <stdio.h>
#include <sys/cdefs.h>
+/** \cond */
__BEGIN_DECLS
+/** \endcond */
// visible to clients
typedef int sf_count_t;
#define SF_FORMAT_PCM_32 8
#define SF_FORMAT_PCM_24 10
-// Open stream
+/** Open stream */
SNDFILE *sf_open(const char *path, int mode, SF_INFO *info);
-// Close stream
+/** Close stream */
void sf_close(SNDFILE *handle);
-// Read interleaved frames and return actual number of frames read
+/**
+ * Read interleaved frames
+ * \return actual number of frames read
+ */
sf_count_t sf_readf_short(SNDFILE *handle, short *ptr, sf_count_t desired);
sf_count_t sf_readf_float(SNDFILE *handle, float *ptr, sf_count_t desired);
sf_count_t sf_readf_int(SNDFILE *handle, int *ptr, sf_count_t desired);
-// Write interleaved frames and return actual number of frames written
+/**
+ * Write interleaved frames
+ * \return actual number of frames written
+ */
sf_count_t sf_writef_short(SNDFILE *handle, const short *ptr, sf_count_t desired);
sf_count_t sf_writef_float(SNDFILE *handle, const float *ptr, sf_count_t desired);
sf_count_t sf_writef_int(SNDFILE *handle, const int *ptr, sf_count_t desired);
+/** \cond */
__END_DECLS
+/** \endcond */
#endif /* __AUDIO_UTIL_SNDFILE_H */
--- /dev/null
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <math.h>
+#include <audio_utils/limiter.h>
+
+#undef USE_ATAN_APPROXIMATION
+
+#ifdef USE_ATAN_APPROXIMATION
+static inline float atan_approximation(float in)
+{
+ static const float kPi_2 = 1.5625; // pi/2 ~= 2.0 * atan_approximation(1.0)
+ if (in <= 1.0) {
+ return in / (1.0 + 0.28 * in * in);
+ } else {
+ const float in_inverse = 1.0 / in;
+ return kPi_2 - in_inverse / (1.0 + 0.28 * in_inverse * in_inverse);
+ }
+}
+#endif
+
+float limiter(float in)
+{
+ static const float crossover = M_SQRT1_2;
+ float in_abs = fabsf(in);
+ if (in_abs <= crossover) {
+ return in;
+ }
+ float out;
+#ifdef USE_ATAN_APPROXIMATION
+ // atan approximation
+ static const float factor = 4.3125;
+ static const float ratio = 1.0 / factor;
+ out = crossover + atan_approximation((in_abs - crossover)*factor)*ratio;
+ if (out > 1.0) {
+ out = 1.0;
+ }
+#else
+ // polynomial spline
+ static const float A = 0.3431457505;
+ static const float B = -1.798989873;
+ static const float C = 3.029437252;
+ static const float D = -0.6568542495;
+ // Cubic solution Ax^3 + Bx^2 + Cx + D
+ if (in_abs < M_SQRT2) {
+ // TODO Use Estrin's method P3
+ out = ((A*in_abs + B)*in_abs + C)*in_abs + D;
+ } else {
+ out = 1.0;
+ }
+#endif
+ if (in < 0) {
+ out = -out;
+ }
+ return out;
+}
return false;
}
+ // bitstream mode, main, commentary, etc.
+ uint32_t bsmod = mHeaderBuffer[5] & 7;
+ mDataTypeInfo = bsmod; // as per IEC61937-3, table 3.
+
// The names fscod, frmsiz are from the AC3 spec.
uint32_t fscod = mHeaderBuffer[4] >> 6;
if (mDataType == SPDIF_DATA_TYPE_E_AC3) {
if (fscod == 3) {
uint32_t fscod2 = (mHeaderBuffer[4] >> 4) & 0x03;
if (fscod2 >= AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES) {
- ALOGW("Invalid EAC3 fscod2 = %d\n", fscod2);
+ ALOGW("Invalid EAC3 fscod2 = %d", fscod2);
return false;
} else {
mSampleRate = kEAC3ReducedSampleRateTable[fscod2];
uint32_t frmsizcod = mHeaderBuffer[4] & 0x3F; // frame size code
if (fscod >= AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES) {
- ALOGW("Invalid AC3 sampleRateCode = %d\n", fscod);
+ ALOGW("Invalid AC3 sampleRateCode = %d", fscod);
return false;
} else if (frmsizcod >= AC3_NUM_FRAME_SIZE_TABLE_ENTRIES) {
- ALOGW("Invalid AC3 frameSizeCode = %d\n", frmsizcod);
+ ALOGW("Invalid AC3 frameSizeCode = %d", frmsizcod);
return false;
} else {
mSampleRate = kAC3SampleRateTable[fscod];
mAudioBlocksPerSyncFrame = 6;
}
ALOGI_IF((mFormatDumpCount == 0),
- "AC3 frame rate = %d * %d, size = %d, audioBlocksPerSyncFrame = %d\n",
+ "AC3 frame rate = %d * %d, size = %zu, audioBlocksPerSyncFrame = %d",
mSampleRate, mRateMultiplier, mFrameSizeBytes, mAudioBlocksPerSyncFrame);
mFormatDumpCount++;
return true;
libcutils \
liblog
+LOCAL_CFLAGS := -Werror -Wall
include $(BUILD_SHARED_LIBRARY)
// These variables are named after the fields in the DTS spec 5.3.1
// Extract field in order.
- uint32_t ftype = parser.readBits(1);
- uint32_t deficit = parser.readBits(5); // "short"
+ (void) /* uint32_t ftype = */ parser.readBits(1);
+ (void) /* uint32_t deficit = */ parser.readBits(5); // "short"
uint32_t cpf = parser.readBits(1);
uint32_t nblks = parser.readBits(7);
uint32_t fsize = parser.readBits(14);
- uint32_t amode = parser.readBits(6);
+ (void) /* uint32_t amode = */ parser.readBits(6);
uint32_t sfreq = parser.readBits(4);
// make sure we did not read past collected data
ALOG_ASSERT((mSyncLength + ((parser.getBitCursor() + 7) >> 3))
mRateMultiplier = 1; // TODO what about "frequency extension"?
ALOGI_IF((mFormatDumpCount == 0),
- "DTS frame rate = %d * %d, size = %d\n",
+ "DTS frame rate = %d * %d, size = %zu",
mSampleRate, mRateMultiplier, mFrameSizeBytes);
mFormatDumpCount++;
return true;
bool FrameScanner::scan(uint8_t byte)
{
bool result = false;
- ALOGV("FrameScanner: byte = 0x%02X, mCursor = %d\n", byte, mCursor);
+ ALOGV("FrameScanner: byte = 0x%02X, mCursor = %d", byte, mCursor);
assert(mCursor < sizeof(mHeaderBuffer));
if (mCursor < mSyncLength) {
// match sync word
#define isLittleEndian() (*((uint8_t *)&sEndianDetector))
SPDIFEncoder::SPDIFEncoder(audio_format_t format)
- : mSampleRate(48000)
+ : mFramer(NULL)
+ , mSampleRate(48000)
, mBurstBuffer(NULL)
, mBurstBufferSizeBytes(0)
, mRateMultiplier(1)
mFramer = new DTSFrameScanner();
break;
default:
- ALOGE("SPDIFEncoder: ERROR invalid audio format = 0x%08X", format);
- mFramer = NULL;
break;
}
+ // This a programmer error. Call isFormatSupported() first.
+ LOG_ALWAYS_FATAL_IF((mFramer == NULL),
+ "SPDIFEncoder: invalid audio format = 0x%08X", format);
+
mBurstBufferSizeBytes = sizeof(uint16_t)
* SPDIF_ENCODED_CHANNEL_COUNT
* mFramer->getMaxSampleFramesPerSyncFrame();
- ALOGI("SPDIFEncoder: mBurstBufferSizeBytes = %d, littleEndian = %d",
+ ALOGI("SPDIFEncoder: mBurstBufferSizeBytes = %zu, littleEndian = %d",
mBurstBufferSizeBytes, isLittleEndian());
mBurstBuffer = new uint16_t[mBurstBufferSizeBytes >> 1];
clearBurstBuffer();
void SPDIFEncoder::writeBurstBufferShorts(const uint16_t *buffer, size_t numShorts)
{
+ // avoid static analyser warning
+ LOG_ALWAYS_FATAL_IF((mBurstBuffer == NULL), "mBurstBuffer never allocated");
mByteCursor = (mByteCursor + 1) & ~1; // round up to even byte
size_t bytesToWrite = numShorts * sizeof(uint16_t);
if ((mByteCursor + bytesToWrite) > mBurstBufferSizeBytes) {
- ALOGE("SPDIFEncoder: Burst buffer overflow!\n");
+ ALOGE("SPDIFEncoder: Burst buffer overflow!");
reset();
return;
}
{
size_t bytesToWrite = numBytes;
if ((mByteCursor + bytesToWrite) > mBurstBufferSizeBytes) {
- ALOGE("SPDIFEncoder: Burst buffer overflow!\n");
+ ALOGE("SPDIFEncoder: Burst buffer overflow!");
clearBurstBuffer();
return;
}
{
size_t bytesLeft = numBytes;
const uint8_t *data = (const uint8_t *)buffer;
- ALOGV("SPDIFEncoder: mScanning = %d, write(buffer[0] = 0x%02X, numBytes = %u)",
+ ALOGV("SPDIFEncoder: mScanning = %d, write(buffer[0] = 0x%02X, numBytes = %zu)",
mScanning, (uint) *data, numBytes);
while (bytesLeft > 0) {
if (mScanning) {
LOCAL_MODULE := primitives_tests
LOCAL_MODULE_TAGS := tests
+LOCAL_CFLAGS := -Werror -Wall
include $(BUILD_NATIVE_TEST)
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := libaudioutils
# libmedia libbinder libcutils libutils
LOCAL_STATIC_LIBRARIES := libsndfile
+LOCAL_CFLAGS := -Werror -Wall
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(call include-path-for, audio-utils)
# libmedia libbinder libcutils libutils
LOCAL_STATIC_LIBRARIES := libsndfile libaudioutils liblog
+LOCAL_CFLAGS := -Werror -Wall
+include $(BUILD_HOST_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := limiter_tests.c
+LOCAL_MODULE := limiter_tests
+LOCAL_C_INCLUDES := $(call include-path-for, audio-utils)
+LOCAL_STATIC_LIBRARIES := libaudioutils
+LOCAL_CFLAGS := -Werror -Wall
include $(BUILD_HOST_EXECUTABLE)
--- /dev/null
+primitive\_tests uses gtest framework
+
+fifo\_tests does not run under gtest
sf_count_t actualWritten = sf_writef_short(sfout, outputBuffer, framesRead);
delete[] inputBuffer;
delete[] outputBuffer;
+ delete[] fifoBuffer;
if (actualWritten != (sf_count_t) framesRead) {
fprintf(stderr, "%s: unexpected error\n", outputFile);
sf_close(sfout);
--- /dev/null
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <audio_utils/limiter.h>
+
+int main(int argc, char **argv)
+{
+ int i;
+ if (argc > 1) {
+ for (i = 1; i < argc; i++) {
+ float x = atof(argv[i]);
+ printf("limit(%g)=%g\n", x, limiter(x));
+ }
+ } else {
+ for (i = 0; i <= 150; i++) {
+ float in = (float) ((double) i * 0.01);
+ float out = limiter(in);
+ printf("%g,%g\n", in, out);
+ if (i != 0) {
+ out = limiter(-in);
+ printf("%g,%g\n", -in, out);
+ }
+ }
+ }
+ return EXIT_SUCCESS;
+}
* limitations under the License.
*/
+#include <system/audio.h>
#include <audio_utils/sndfile.h>
#include <audio_utils/primitives.h>
#ifdef HAVE_STDERR
fseek(stream, (long) (chunkSize - minSize), SEEK_CUR);
}
unsigned channels = little2u(&fmt[2]);
- // FIXME FCC_8
- if (channels != 1 && channels != 2 && channels != 4 && channels != 6 && channels != 8) {
+ if ((channels < 1) || (channels > FCC_8)) {
#ifdef HAVE_STDERR
fprintf(stderr, "unsupported channels %u\n", channels);
#endif
int sub = info->format & SF_FORMAT_SUBMASK;
if (!(
(info->samplerate > 0) &&
- // FIXME FCC_8
- (info->channels > 0 && info->channels <= 8) &&
+ (info->channels > 0 && info->channels <= FCC_8) &&
((info->format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV) &&
(sub == SF_FORMAT_PCM_16 || sub == SF_FORMAT_PCM_U8 || sub == SF_FORMAT_FLOAT ||
sub == SF_FORMAT_PCM_24 || sub == SF_FORMAT_PCM_32)
--- /dev/null
+# Copyright 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+audio_service_shared_libraries := \
+ libbinderwrapper \
+ libbrillo \
+ libbrillo-binder \
+ libc \
+ libchrome \
+ libmedia \
+ libutils
+
+# Audio service.
+# =============================================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := brilloaudioservice
+LOCAL_SRC_FILES := \
+ audio_daemon.cpp \
+ audio_device_handler.cpp \
+ main_audio_service.cpp
+LOCAL_SHARED_LIBRARIES := $(audio_service_shared_libraries)
+LOCAL_CFLAGS := -Werror -Wall
+LOCAL_INIT_RC := brilloaudioserv.rc
+include $(BUILD_EXECUTABLE)
+
+# Unit tests for audio device handler.
+# =============================================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := brilloaudioservice_test
+LOCAL_SRC_FILES := \
+ audio_device_handler.cpp \
+ test/audio_device_handler_test.cpp
+LOCAL_C_INCLUDES := external/gtest/include
+LOCAL_SHARED_LIBRARIES := $(audio_service_shared_libraries)
+LOCAL_STATIC_LIBRARIES := \
+ libBionicGtestMain \
+ libchrome_test_helpers \
+ libgmock
+LOCAL_CFLAGS := -Werror -Wall
+LOCAL_CFLAGS += -Wno-sign-compare
+include $(BUILD_NATIVE_TEST)
--- /dev/null
+// Copyright 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Implementation of audio_daemon.h.
+
+#include "audio_daemon.h"
+
+#include <sysexits.h>
+
+#include <base/bind.h>
+#include <base/files/file_enumerator.h>
+#include <base/files/file_path.h>
+#include <base/time/time.h>
+#include <binderwrapper/binder_wrapper.h>
+#include <linux/input.h>
+
+namespace brillo {
+
+static const char kAPSServiceName[] = "media.audio_policy";
+static const char kInputDeviceDir[] = "/dev/input";
+
+void AudioDaemon::InitializeHandler() {
+ // Start and initialize the audio device handler.
+ audio_device_handler_ =
+ std::unique_ptr<AudioDeviceHandler>(new AudioDeviceHandler());
+ audio_device_handler_->Init(aps_);
+
+ // Poll on all files in kInputDeviceDir.
+ base::FileEnumerator fenum(base::FilePath(kInputDeviceDir),
+ false /*recursive*/, base::FileEnumerator::FILES);
+ for (base::FilePath name = fenum.Next(); !name.empty(); name = fenum.Next()) {
+ base::File file(name, base::File::FLAG_OPEN | base::File::FLAG_READ);
+ if (file.IsValid()) {
+ MessageLoop* message_loop = MessageLoop::current();
+ int fd = file.GetPlatformFile();
+ // Move file to files_ and ensure that when binding we get a pointer from
+ // the object in files_.
+ files_.emplace(std::move(file));
+ base::Closure callback =
+ base::Bind(&AudioDaemon::Callback, weak_ptr_factory_.GetWeakPtr(),
+ &files_.top());
+ message_loop->WatchFileDescriptor(fd, MessageLoop::kWatchRead,
+ true /*persistent*/, callback);
+ } else {
+ LOG(WARNING) << "Could not open " << name.value() << " for reading. ("
+ << base::File::ErrorToString(file.error_details()) << ")";
+ }
+ }
+ handler_initialized_ = true;
+}
+
+void AudioDaemon::ConnectToAPS() {
+ android::BinderWrapper* binder_wrapper = android::BinderWrapper::Get();
+ auto binder = binder_wrapper->GetService(kAPSServiceName);
+ // If we didn't get the audio policy service, try again in 500 ms.
+ if (!binder.get()) {
+ LOG(INFO) << "Could not connect to audio policy service. Trying again...";
+ brillo::MessageLoop::current()->PostDelayedTask(
+ base::Bind(&AudioDaemon::ConnectToAPS, weak_ptr_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(500));
+ return;
+ }
+ LOG(INFO) << "Connected to audio policy service.";
+ binder_wrapper->RegisterForDeathNotifications(
+ binder,
+ base::Bind(&AudioDaemon::OnAPSDisconnected,
+ weak_ptr_factory_.GetWeakPtr()));
+ VLOG(1) << "Registered death notification.";
+ aps_ = android::interface_cast<android::IAudioPolicyService>(binder);
+ if (!handler_initialized_)
+ InitializeHandler();
+ else
+ audio_device_handler_->APSConnect(aps_);
+}
+
+void AudioDaemon::OnAPSDisconnected() {
+ LOG(INFO) << "Audio policy service died. Will try to reconnect.";
+ audio_device_handler_->APSDisconnect();
+ aps_ = nullptr;
+ ConnectToAPS();
+}
+
+// OnInit, we want to do the following:
+// - Get a binder to the audio policy service.
+// - Initialize the audio device handler.
+// - Set up polling on files in /dev/input.
+int AudioDaemon::OnInit() {
+ int exit_code = Daemon::OnInit();
+ if (exit_code != EX_OK) return exit_code;
+ // Initialize a binder wrapper.
+ android::BinderWrapper::Create();
+ // Initialize a binder watcher.
+ binder_watcher_.Init();
+ ConnectToAPS();
+ return EX_OK;
+}
+
+void AudioDaemon::Callback(base::File* file) {
+ input_event event;
+ int bytes_read =
+ file->ReadAtCurrentPos(reinterpret_cast<char*>(&event), sizeof(event));
+ if (bytes_read != sizeof(event)) {
+ LOG(WARNING) << "Couldn't read an input event.";
+ return;
+ }
+ audio_device_handler_->ProcessEvent(event);
+}
+
+} // namespace brillo
--- /dev/null
+// Copyright 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Main loop of the brillo audio service.
+
+#ifndef BRILLO_AUDIO_AUDIOSERVICE_AUDIO_DAEMON_H_
+#define BRILLO_AUDIO_AUDIOSERVICE_AUDIO_DAEMON_H_
+
+#include <memory>
+#include <stack>
+
+#include <base/files/file.h>
+#include <base/memory/weak_ptr.h>
+#include <brillo/binder_watcher.h>
+#include <brillo/daemons/daemon.h>
+#include <media/IAudioPolicyService.h>
+
+#include "audio_device_handler.h"
+
+namespace brillo {
+
+class AudioDaemon : public Daemon {
+ public:
+ AudioDaemon() {}
+
+ protected:
+ // Initialize the audio device handler and start pollig the files in
+ // /dev/input.
+ int OnInit() override;
+
+ private:
+ // Callback function for input events. Events are handled by the audio device
+ // handler.
+ void Callback(base::File* file);
+
+ // Callback function for audio policy service death notification.
+ void OnAPSDisconnected();
+
+ // Connect to the audio policy service and register a callback to be invoked
+ // if the audio policy service dies.
+ void ConnectToAPS();
+
+ // Initialize the audio_device_handler_.
+ //
+ // Note: This can only occur after we have connected to the audio policy
+ // service.
+ void InitializeHandler();
+
+ // Store the file objects that are created during initialization for the files
+ // being polled. This is done so these objects can be freed when the
+ // AudioDaemon object is destroyed.
+ std::stack<base::File> files_;
+ // Handler for audio device input events.
+ std::unique_ptr<AudioDeviceHandler> audio_device_handler_;
+ // Used to generate weak_ptr to AudioDaemon for use in base::Bind.
+ base::WeakPtrFactory<AudioDaemon> weak_ptr_factory_{this};
+ // Pointer to the audio policy service.
+ android::sp<android::IAudioPolicyService> aps_;
+ // Flag to indicate whether the handler has been initialized.
+ bool handler_initialized_ = false;
+ // Binder watcher to watch for binder messages.
+ brillo::BinderWatcher binder_watcher_;
+};
+
+} // namespace brillo
+
+#endif // BRILLO_AUDIO_AUDIOSERVICE_AUDIO_DAEMON_H_
--- /dev/null
+// Copyright 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Implementation of audio_device_handler.h
+
+#include "audio_device_handler.h"
+
+#include <base/files/file.h>
+#include <base/logging.h>
+#include <media/AudioSystem.h>
+
+namespace brillo {
+
+static const char kH2WStateFile[] = "/sys/class/switch/h2w/state";
+
+AudioDeviceHandler::AudioDeviceHandler() {
+ headphone_ = false;
+ microphone_ = false;
+}
+
+AudioDeviceHandler::~AudioDeviceHandler() {}
+
+void AudioDeviceHandler::APSDisconnect() {
+ aps_.clear();
+}
+
+void AudioDeviceHandler::APSConnect(
+ android::sp<android::IAudioPolicyService> aps) {
+ aps_ = aps;
+ // Reset the state
+ connected_input_devices_.clear();
+ connected_output_devices_.clear();
+ // Inform audio policy service about the currently connected devices.
+ VLOG(1) << "Calling GetInitialAudioDeviceState on APSConnect.";
+ GetInitialAudioDeviceState(base::FilePath(kH2WStateFile));
+}
+
+void AudioDeviceHandler::Init(android::sp<android::IAudioPolicyService> aps) {
+ aps_ = aps;
+ // Reset audio policy service state in case this service crashed and there is
+ // a mismatch between the current system state and what audio policy service
+ // was previously told.
+ VLOG(1) << "Calling DisconnectAllSupportedDevices.";
+ DisconnectAllSupportedDevices();
+
+ // Get headphone jack state and update audio policy service with new state.
+ VLOG(1) << "Calling ReadInitialAudioDeviceState.";
+ GetInitialAudioDeviceState(base::FilePath(kH2WStateFile));
+}
+
+void AudioDeviceHandler::GetInitialAudioDeviceState(
+ const base::FilePath& path) {
+ base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
+ if (!file.IsValid()) {
+ LOG(WARNING) << "Kernel does not have wired headset support. Could not "
+ << "open " << path.value() << "( "
+ << base::File::ErrorToString(file.error_details()) << " ).";
+ return;
+ }
+ int state = 0;
+ int bytes_read = file.ReadAtCurrentPos(reinterpret_cast<char*>(&state), 1);
+ state -= '0';
+ if (bytes_read == 0) {
+ LOG(WARNING) << "Could not read from " << path.value();
+ return;
+ }
+ VLOG(1) << "Initial audio jack state is " << state;
+ static const int kHeadPhoneMask = 0x1;
+ bool headphone = state & kHeadPhoneMask;
+ static const int kMicrophoneMask = 0x2;
+ bool microphone = (state & kMicrophoneMask) >> 1;
+
+ UpdateAudioSystem(headphone, microphone);
+}
+
+void AudioDeviceHandler::NotifyAudioPolicyService(
+ audio_devices_t device, audio_policy_dev_state_t state) {
+ if (aps_ == nullptr) {
+ LOG(INFO) << "Audio device handler cannot call audio policy service. Will "
+ << "try again later.";
+ return;
+ }
+ VLOG(1) << "Calling Audio Policy Service to change " << device << " to state "
+ << state;
+ aps_->setDeviceConnectionState(device, state, "", "");
+}
+
+void AudioDeviceHandler::ConnectAudioDevice(audio_devices_t device) {
+ audio_policy_dev_state_t state = AUDIO_POLICY_DEVICE_STATE_AVAILABLE;
+ NotifyAudioPolicyService(device, state);
+ if (audio_is_input_device(device))
+ connected_input_devices_.insert(device);
+ else
+ connected_output_devices_.insert(device);
+}
+
+void AudioDeviceHandler::DisconnectAudioDevice(audio_devices_t device) {
+ audio_policy_dev_state_t state = AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
+ NotifyAudioPolicyService(device, state);
+ if (audio_is_input_device(device))
+ connected_input_devices_.erase(device);
+ else
+ connected_output_devices_.erase(device);
+}
+
+void AudioDeviceHandler::DisconnectAllSupportedDevices() {
+ for (auto device : kSupportedInputDevices_) {
+ DisconnectAudioDevice(device);
+ }
+ for (auto device : kSupportedOutputDevices_) {
+ DisconnectAudioDevice(device);
+ }
+}
+
+void AudioDeviceHandler::DisconnectAllConnectedDevices() {
+ while (!connected_input_devices_.empty()) {
+ audio_devices_t device = *(connected_input_devices_.begin());
+ DisconnectAudioDevice(device);
+ }
+ while (!connected_output_devices_.empty()) {
+ audio_devices_t device = *(connected_output_devices_.begin());
+ DisconnectAudioDevice(device);
+ }
+}
+
+void AudioDeviceHandler::UpdateAudioSystem(bool headphone, bool microphone) {
+ if (microphone) {
+ ConnectAudioDevice(AUDIO_DEVICE_IN_WIRED_HEADSET);
+ }
+ if (headphone && microphone) {
+ ConnectAudioDevice(AUDIO_DEVICE_OUT_WIRED_HEADSET);
+ } else if (headphone) {
+ ConnectAudioDevice(AUDIO_DEVICE_OUT_WIRED_HEADPHONE);
+ } else if (!microphone) {
+ // No devices are connected. Inform the audio policy service that all
+ // connected devices have been disconnected.
+ DisconnectAllConnectedDevices();
+ }
+}
+
+void AudioDeviceHandler::ProcessEvent(const struct input_event& event) {
+ VLOG(1) << event.type << " " << event.code << " " << event.value;
+ if (event.type == EV_SW) {
+ switch (event.code) {
+ case SW_HEADPHONE_INSERT:
+ headphone_ = event.value;
+ break;
+ case SW_MICROPHONE_INSERT:
+ microphone_ = event.value;
+ break;
+ default:
+ // This event code is not supported by this handler.
+ break;
+ }
+ } else if (event.type == EV_SYN) {
+ // We have received all input events. Update the audio system.
+ UpdateAudioSystem(headphone_, microphone_);
+ // Reset the headphone and microphone flags that are used to track
+ // information across multiple calls to ProcessEvent.
+ headphone_ = false;
+ microphone_ = false;
+ }
+}
+
+} // namespace brillo
--- /dev/null
+// Copyright 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Handler for input events in /dev/input. AudioDeviceHandler handles events
+// only for audio devices being plugged in/removed from the system. Implements
+// some of the functionality present in WiredAccessoryManager.java.
+
+#ifndef BRILLO_AUDIO_AUDIOSERVICE_AUDIO_DEVICE_HANDLER_H_
+#define BRILLO_AUDIO_AUDIOSERVICE_AUDIO_DEVICE_HANDLER_H_
+
+#include <set>
+#include <vector>
+
+#include <base/files/file_path.h>
+#include <gtest/gtest_prod.h>
+#include <linux/input.h>
+#include <media/IAudioPolicyService.h>
+#include <system/audio.h>
+#include <system/audio_policy.h>
+
+namespace brillo {
+
+class AudioDeviceHandler {
+ public:
+ AudioDeviceHandler();
+ virtual ~AudioDeviceHandler();
+
+ // Get the current state of the headset jack and update AudioSystem based on
+ // the initial state.
+ //
+ // |aps| is a pointer to the binder object.
+ void Init(android::sp<android::IAudioPolicyService> aps);
+
+ // Process input events from the kernel. Connecting/disconnecting an audio
+ // device will result in multiple calls to this method.
+ //
+ // |event| is a pointer to an input_event. This function should be able to
+ // gracefully handle input events that are not relevant to the functionality
+ // provided by this class.
+ void ProcessEvent(const struct input_event& event);
+
+ // Inform the handler that the audio policy service has been disconnected.
+ void APSDisconnect();
+
+ // Inform the handler that the audio policy service is reconnected.
+ //
+ // |aps| is a pointer to the binder object.
+ void APSConnect(android::sp<android::IAudioPolicyService> aps);
+
+ private:
+ friend class AudioDeviceHandlerTest;
+ FRIEND_TEST(AudioDeviceHandlerTest,
+ DisconnectAllSupportedDevicesCallsDisconnect);
+ FRIEND_TEST(AudioDeviceHandlerTest, InitCallsDisconnectAllSupportedDevices);
+ FRIEND_TEST(AudioDeviceHandlerTest, InitialAudioStateMic);
+ FRIEND_TEST(AudioDeviceHandlerTest, InitialAudioStateHeadphone);
+ FRIEND_TEST(AudioDeviceHandlerTest, InitialAudioStateHeadset);
+ FRIEND_TEST(AudioDeviceHandlerTest, InitialAudioStateNone);
+ FRIEND_TEST(AudioDeviceHandlerTest, InitialAudioStateInvalid);
+ FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventEmpty);
+ FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventMicrophonePresent);
+ FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventHeadphonePresent);
+ FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventMicrophoneNotPresent);
+ FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventHeadphoneNotPresent);
+ FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventInvalid);
+ FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemNone);
+ FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemConnectMic);
+ FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemConnectHeadphone);
+ FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemConnectHeadset);
+ FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemDisconnectMic);
+ FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemDisconnectHeadphone);
+ FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemDisconnectHeadset);
+ FRIEND_TEST(AudioDeviceHandlerTest, ConnectAudioDeviceInput);
+ FRIEND_TEST(AudioDeviceHandlerTest, ConnectAudioDeviceOutput);
+ FRIEND_TEST(AudioDeviceHandlerTest, DisconnectAudioDeviceInput);
+ FRIEND_TEST(AudioDeviceHandlerTest, DisconnectAudioDeviceOutput);
+
+ // Read the initial state of audio devices in /sys/class/* and update
+ // the audio policy service.
+ //
+ // |path| is the file that contains the initial audio jack state.
+ void GetInitialAudioDeviceState(const base::FilePath& path);
+
+ // Update the audio policy service once an input_event has completed.
+ //
+ // |headphone| is true is headphones are connected.
+ // |microphone| is true is microphones are connected.
+ void UpdateAudioSystem(bool headphone, bool microphone);
+
+ // Notify the audio policy service that this device has been removed.
+ //
+ // |device| is the audio device whose state is to be changed.
+ // |state| is the current state of |device|.
+ virtual void NotifyAudioPolicyService(audio_devices_t device,
+ audio_policy_dev_state_t state);
+
+ // Connect an audio device by calling aps and add it to the appropriate set
+ // (either connected_input_devices_ or connected_output_devices_).
+ //
+ // |device| is the audio device that has been added.
+ void ConnectAudioDevice(audio_devices_t device);
+
+ // Disconnect an audio device by calling aps and remove it from the
+ // appropriate set (either connected_input_devices_ or
+ // connected_output_devices_).
+ //
+ // |device| is the audio device that has been disconnected.
+ void DisconnectAudioDevice(audio_devices_t device);
+
+ // Disconnected all connected audio devices.
+ void DisconnectAllConnectedDevices();
+
+ // Disconnect all supported audio devices.
+ void DisconnectAllSupportedDevices();
+
+ // All input devices currently supported by AudioDeviceHandler.
+ std::vector<audio_devices_t> kSupportedInputDevices_{
+ AUDIO_DEVICE_IN_WIRED_HEADSET};
+ // All output devices currently supported by AudioDeviceHandler.
+ std::vector<audio_devices_t> kSupportedOutputDevices_{
+ AUDIO_DEVICE_OUT_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADPHONE};
+ // Pointer to the audio policy service.
+ android::sp<android::IAudioPolicyService> aps_;
+
+ protected:
+ // Set of connected input devices.
+ std::set<audio_devices_t> connected_input_devices_;
+ // Set of connected output devices.
+ std::set<audio_devices_t> connected_output_devices_;
+ // Keeps track of whether a headphone has been connected. Used by ProcessEvent
+ // and UpdateAudioSystem.
+ bool headphone_;
+ // Keeps track of whether a microphone has been connected. Used by
+ // ProcessEvent and UpdateAudioSystem.
+ bool microphone_;
+};
+
+} // namespace brillo
+
+#endif // BRILLO_AUDIO_AUDIOSERVICE_AUDIO_DEVICE_HANDLER_H_
--- /dev/null
+service brilloaudioserv /system/bin/brilloaudioservice
+ class late_start
+ user system
+ group input
--- /dev/null
+// Copyright 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <brillo/flag_helper.h>
+#include <brillo/syslog_logging.h>
+
+#include "audio_daemon.h"
+
+int main(int argc, char** argv) {
+ brillo::FlagHelper::Init(argc, argv, "Brillo audio service,");
+ brillo::InitLog(brillo::kLogToSyslog | brillo::kLogHeader);
+ LOG(INFO) << "Starting brilloaudioservice.";
+ brillo::AudioDaemon audio_daemon;
+ return audio_daemon.Run();
+}
--- /dev/null
+// Copyright 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Mock of AudioDeviceHandler.
+
+#ifndef BRILLO_AUDIO_AUDIOSERVICE_TEST_AUDIO_DEVICE_HANDLER_MOCK_H_
+#define BRILLO_AUDIO_AUDIOSERVICE_TEST_AUDIO_DEVICE_HANDLER_MOCK_H_
+
+#include <base/files/file_path.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest_prod.h>
+#include <system/audio.h>
+#include <system/audio_policy.h>
+
+#include "audio_device_handler.h"
+
+namespace brillo {
+
+class AudioDeviceHandlerMock : public AudioDeviceHandler {
+ public:
+ AudioDeviceHandlerMock() = default;
+ ~AudioDeviceHandlerMock() {}
+
+ // Reset all local data.
+ void Reset() {
+ connected_input_devices_.clear();
+ connected_output_devices_.clear();
+ headphone_ = false;
+ microphone_ = false;
+ }
+
+ private:
+ friend class AudioDeviceHandlerTest;
+ FRIEND_TEST(AudioDeviceHandlerTest,
+ DisconnectAllSupportedDevicesCallsDisconnect);
+ FRIEND_TEST(AudioDeviceHandlerTest, InitCallsDisconnectAllSupportedDevices);
+ FRIEND_TEST(AudioDeviceHandlerTest, InitialAudioStateMic);
+ FRIEND_TEST(AudioDeviceHandlerTest, InitialAudioStateHeadphone);
+ FRIEND_TEST(AudioDeviceHandlerTest, InitialAudioStateHeadset);
+ FRIEND_TEST(AudioDeviceHandlerTest, InitialAudioStateNone);
+ FRIEND_TEST(AudioDeviceHandlerTest, InitialAudioStateInvalid);
+ FRIEND_TEST(AudioDeviceHandlerTest, InitCallsDisconnect);
+ FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventEmpty);
+ FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventMicrophonePresent);
+ FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventHeadphonePresent);
+ FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventMicrophoneNotPresent);
+ FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventHeadphoneNotPresent);
+ FRIEND_TEST(AudioDeviceHandlerTest, ProcessEventInvalid);
+ FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemNone);
+ FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemConnectMic);
+ FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemConnectHeadphone);
+ FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemConnectHeadset);
+ FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemDisconnectMic);
+ FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemDisconnectHeadphone);
+ FRIEND_TEST(AudioDeviceHandlerTest, UpdateAudioSystemDisconnectHeadset);
+ FRIEND_TEST(AudioDeviceHandlerTest, ConnectAudioDeviceInput);
+ FRIEND_TEST(AudioDeviceHandlerTest, ConnectAudioDeviceOutput);
+ FRIEND_TEST(AudioDeviceHandlerTest, DisconnectAudioDeviceInput);
+ FRIEND_TEST(AudioDeviceHandlerTest, DisconnectAudioDeviceOutput);
+
+ MOCK_METHOD2(NotifyAudioPolicyService,
+ void(audio_devices_t device, audio_policy_dev_state_t state));
+};
+
+} // namespace brillo
+
+#endif // BRILLO_AUDIO_AUDIOSERVICE_TEST_AUDIO_DEVICE_HANDLER_MOCK_H_
--- /dev/null
+// Copyright 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Tests for audio device handler.
+
+#include "audio_device_handler_mock.h"
+
+#include <string>
+
+#include <base/files/file_path.h>
+#include <base/files/file_util.h>
+#include <base/files/scoped_temp_dir.h>
+#include <base/strings/string_number_conversions.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using base::FilePath;
+using base::IntToString;
+using base::ScopedTempDir;
+using base::WriteFile;
+using brillo::AudioDeviceHandlerMock;
+using testing::_;
+using testing::AnyNumber;
+
+namespace brillo {
+
+class AudioDeviceHandlerTest : public testing::Test {
+ public:
+ void SetUp() override {
+ EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
+ h2w_file_path_ = temp_dir_.path().Append("h2wstate");
+ }
+
+ void TearDown() override { handler_.Reset(); }
+
+ // Method to store the current state of the audio jack to a file.
+ //
+ // |value| - Value in the h2w file.
+ void WriteToH2WFile(int value) {
+ std::string value_string = IntToString(value);
+ WriteFile(h2w_file_path_, value_string.c_str(), value_string.length());
+ }
+
+ AudioDeviceHandlerMock handler_;
+ FilePath h2w_file_path_;
+
+ private:
+ ScopedTempDir temp_dir_;
+};
+
+// Test that DisconnectAllSupportedDevices() calls NotifyAudioPolicyService()
+// the right number of times.
+TEST_F(AudioDeviceHandlerTest, DisconnectAllSupportedDevicesCallsDisconnect) {
+ EXPECT_CALL(handler_,
+ NotifyAudioPolicyService(
+ _, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE)).Times(3);
+ handler_.DisconnectAllSupportedDevices();
+}
+
+// Test that Init() calls DisconnectAllSupportedDevices().
+TEST_F(AudioDeviceHandlerTest, InitCallsDisconnectAllSupportedDevices) {
+ EXPECT_CALL(handler_,
+ NotifyAudioPolicyService(
+ _, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE)).Times(3);
+ EXPECT_CALL(handler_,
+ NotifyAudioPolicyService(
+ _, AUDIO_POLICY_DEVICE_STATE_AVAILABLE)).Times(AnyNumber());
+ handler_.Init(nullptr);
+}
+
+// Test GetInitialAudioDeviceState() with just a microphone.
+TEST_F(AudioDeviceHandlerTest, InitialAudioStateMic) {
+ WriteToH2WFile(2);
+ EXPECT_CALL(handler_,
+ NotifyAudioPolicyService(AUDIO_DEVICE_IN_WIRED_HEADSET,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+ handler_.GetInitialAudioDeviceState(h2w_file_path_);
+ EXPECT_NE(
+ handler_.connected_input_devices_.find(AUDIO_DEVICE_IN_WIRED_HEADSET),
+ handler_.connected_input_devices_.end());
+ EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+}
+
+// Test GetInitialAudioDeviceState() with a headphone.
+TEST_F(AudioDeviceHandlerTest, InitialAudioStateHeadphone) {
+ WriteToH2WFile(1);
+ EXPECT_CALL(handler_,
+ NotifyAudioPolicyService(AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+ handler_.GetInitialAudioDeviceState(h2w_file_path_);
+ EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
+ EXPECT_NE(
+ handler_.connected_output_devices_.find(AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
+ handler_.connected_output_devices_.end());
+}
+
+// Test GetInitialAudioDeviceState() with a headset.
+TEST_F(AudioDeviceHandlerTest, InitialAudioStateHeadset) {
+ WriteToH2WFile(3);
+ EXPECT_CALL(handler_,
+ NotifyAudioPolicyService(AUDIO_DEVICE_IN_WIRED_HEADSET,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+ EXPECT_CALL(handler_,
+ NotifyAudioPolicyService(AUDIO_DEVICE_OUT_WIRED_HEADSET,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+ handler_.GetInitialAudioDeviceState(h2w_file_path_);
+ EXPECT_NE(
+ handler_.connected_input_devices_.find(AUDIO_DEVICE_IN_WIRED_HEADSET),
+ handler_.connected_input_devices_.end());
+ EXPECT_NE(
+ handler_.connected_output_devices_.find(AUDIO_DEVICE_OUT_WIRED_HEADSET),
+ handler_.connected_output_devices_.end());
+}
+
+// Test GetInitialAudioDeviceState() without any devices connected to the audio
+// jack. No need to call NotifyAudioPolicyService() since that's already handled
+// by Init().
+TEST_F(AudioDeviceHandlerTest, InitialAudioStateNone) {
+ WriteToH2WFile(0);
+ handler_.GetInitialAudioDeviceState(h2w_file_path_);
+ EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
+ EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+}
+
+// Test GetInitialAudioDeviceState() with an invalid file. The audio handler
+// should not fail in this case because it should work on boards that don't
+// support audio jacks.
+TEST_F(AudioDeviceHandlerTest, InitialAudioStateInvalid) {
+ FilePath path = h2w_file_path_;
+ handler_.GetInitialAudioDeviceState(h2w_file_path_);
+ EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
+ EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+}
+
+// Test ProcessEvent() with an empty input_event arg.
+TEST_F(AudioDeviceHandlerTest, ProcessEventEmpty) {
+ struct input_event event;
+ event.type = 0;
+ event.code = 0;
+ event.value = 0;
+ handler_.ProcessEvent(event);
+ EXPECT_FALSE(handler_.headphone_);
+ EXPECT_FALSE(handler_.microphone_);
+}
+
+// Test ProcessEvent() with a microphone present input_event arg.
+TEST_F(AudioDeviceHandlerTest, ProcessEventMicrophonePresent) {
+ struct input_event event;
+ event.type = EV_SW;
+ event.code = SW_MICROPHONE_INSERT;
+ event.value = 1;
+ handler_.ProcessEvent(event);
+ EXPECT_FALSE(handler_.headphone_);
+ EXPECT_TRUE(handler_.microphone_);
+}
+
+// Test ProcessEvent() with a headphone present input_event arg.
+TEST_F(AudioDeviceHandlerTest, ProcessEventHeadphonePresent) {
+ struct input_event event;
+ event.type = EV_SW;
+ event.code = SW_HEADPHONE_INSERT;
+ event.value = 1;
+ handler_.ProcessEvent(event);
+ EXPECT_TRUE(handler_.headphone_);
+ EXPECT_FALSE(handler_.microphone_);
+}
+
+// Test ProcessEvent() with a microphone not present input_event arg.
+TEST_F(AudioDeviceHandlerTest, ProcessEventMicrophoneNotPresent) {
+ struct input_event event;
+ event.type = EV_SW;
+ event.code = SW_MICROPHONE_INSERT;
+ event.value = 0;
+ handler_.ProcessEvent(event);
+ EXPECT_FALSE(handler_.headphone_);
+ EXPECT_FALSE(handler_.microphone_);
+}
+
+// Test ProcessEvent() with a headphone not preset input_event arg.
+TEST_F(AudioDeviceHandlerTest, ProcessEventHeadphoneNotPresent) {
+ struct input_event event;
+ event.type = EV_SW;
+ event.code = SW_HEADPHONE_INSERT;
+ event.value = 0;
+ handler_.ProcessEvent(event);
+ EXPECT_FALSE(handler_.headphone_);
+ EXPECT_FALSE(handler_.microphone_);
+}
+
+// Test ProcessEvent() with an unsupported input_event arg.
+TEST_F(AudioDeviceHandlerTest, ProcessEventInvalid) {
+ struct input_event event;
+ event.type = EV_SW;
+ event.code = SW_MAX;
+ event.value = 0;
+ handler_.ProcessEvent(event);
+ EXPECT_FALSE(handler_.headphone_);
+ EXPECT_FALSE(handler_.microphone_);
+}
+
+// Test UpdateAudioSystem() without any devices connected.
+TEST_F(AudioDeviceHandlerTest, UpdateAudioSystemNone) {
+ EXPECT_CALL(handler_,
+ NotifyAudioPolicyService(
+ _, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE)).Times(0);
+ handler_.UpdateAudioSystem(handler_.headphone_, handler_.microphone_);
+}
+
+// Test UpdateAudioSystem() when disconnecting a microphone.
+TEST_F(AudioDeviceHandlerTest, UpdateAudioSystemDisconnectMic) {
+ audio_devices_t device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+ handler_.connected_input_devices_.insert(device);
+ EXPECT_CALL(handler_,
+ NotifyAudioPolicyService(device,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
+ handler_.UpdateAudioSystem(handler_.headphone_, handler_.microphone_);
+ EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
+ EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+}
+
+// Test UpdateAudioSystem() when disconnecting a headphone.
+TEST_F(AudioDeviceHandlerTest, UpdateAudioSystemDisconnectHeadphone) {
+ audio_devices_t device = AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
+ handler_.connected_output_devices_.insert(device);
+ EXPECT_CALL(handler_,
+ NotifyAudioPolicyService(device,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
+ handler_.UpdateAudioSystem(handler_.headphone_, handler_.microphone_);
+ EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
+ EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+}
+
+// Test UpdateAudioSystem() when disconnecting a headset & headphones.
+TEST_F(AudioDeviceHandlerTest, UpdateAudioSystemDisconnectHeadset) {
+ handler_.connected_input_devices_.insert(AUDIO_DEVICE_IN_WIRED_HEADSET);
+ handler_.connected_output_devices_.insert(AUDIO_DEVICE_OUT_WIRED_HEADSET);
+ handler_.connected_output_devices_.insert(AUDIO_DEVICE_OUT_WIRED_HEADPHONE);
+ EXPECT_CALL(handler_,
+ NotifyAudioPolicyService(AUDIO_DEVICE_IN_WIRED_HEADSET,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
+ EXPECT_CALL(handler_,
+ NotifyAudioPolicyService(AUDIO_DEVICE_OUT_WIRED_HEADSET,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
+ EXPECT_CALL(handler_,
+ NotifyAudioPolicyService(AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
+ handler_.UpdateAudioSystem(handler_.headphone_, handler_.microphone_);
+ EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
+ EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+}
+
+// Test UpdateAudioSystem() when connecting a microphone.
+TEST_F(AudioDeviceHandlerTest, UpdateAudioSystemConnectMic) {
+ handler_.microphone_ = true;
+ EXPECT_CALL(handler_,
+ NotifyAudioPolicyService(AUDIO_DEVICE_IN_WIRED_HEADSET,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+ handler_.UpdateAudioSystem(handler_.headphone_, handler_.microphone_);
+ EXPECT_EQ(handler_.connected_input_devices_.size(), 1);
+ EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+}
+
+// Test UpdateAudioSystem() when connecting a headphone.
+TEST_F(AudioDeviceHandlerTest, UpdateAudioSystemConnectHeadphone) {
+ handler_.headphone_ = true;
+ EXPECT_CALL(handler_,
+ NotifyAudioPolicyService(AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+ handler_.UpdateAudioSystem(handler_.headphone_, handler_.microphone_);
+ EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
+ EXPECT_EQ(handler_.connected_output_devices_.size(), 1);
+}
+
+// Test UpdateAudioSystem() when connecting a headset.
+TEST_F(AudioDeviceHandlerTest, UpdateAudioSystemConnectHeadset) {
+ handler_.headphone_ = true;
+ handler_.microphone_ = true;
+ EXPECT_CALL(handler_,
+ NotifyAudioPolicyService(AUDIO_DEVICE_IN_WIRED_HEADSET,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+ EXPECT_CALL(handler_,
+ NotifyAudioPolicyService(AUDIO_DEVICE_OUT_WIRED_HEADSET,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+ handler_.UpdateAudioSystem(handler_.headphone_, handler_.microphone_);
+ EXPECT_EQ(handler_.connected_input_devices_.size(), 1);
+ EXPECT_EQ(handler_.connected_output_devices_.size(), 1);
+}
+
+// Test ConnectAudioDevice() with an input device.
+TEST_F(AudioDeviceHandlerTest, ConnectAudioDeviceInput) {
+ audio_devices_t device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+ EXPECT_CALL(handler_,
+ NotifyAudioPolicyService(device,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+ handler_.ConnectAudioDevice(device);
+ EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+ EXPECT_NE(
+ handler_.connected_input_devices_.find(device),
+ handler_.connected_input_devices_.end());
+}
+
+// Test ConnectAudioDevice() with an output device.
+TEST_F(AudioDeviceHandlerTest, ConnectAudioDeviceOutput) {
+ audio_devices_t device = AUDIO_DEVICE_OUT_WIRED_HEADSET;
+ EXPECT_CALL(handler_,
+ NotifyAudioPolicyService(device,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE));
+ handler_.ConnectAudioDevice(device);
+ EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
+ EXPECT_NE(
+ handler_.connected_output_devices_.find(device),
+ handler_.connected_output_devices_.end());
+}
+
+// Test DisconnectAudioDevice() with an input device.
+TEST_F(AudioDeviceHandlerTest, DisconnectAudioDeviceInput) {
+ audio_devices_t device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+ handler_.connected_input_devices_.insert(device);
+ handler_.connected_output_devices_.insert(device);
+ EXPECT_CALL(handler_,
+ NotifyAudioPolicyService(device,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
+ handler_.DisconnectAudioDevice(device);
+ EXPECT_EQ(handler_.connected_input_devices_.size(), 0);
+ EXPECT_EQ(handler_.connected_output_devices_.size(), 1);
+}
+
+// Test DisconnectAudioDevice() with an output device.
+TEST_F(AudioDeviceHandlerTest, DisconnectAudioDeviceOutput) {
+ audio_devices_t device = AUDIO_DEVICE_OUT_WIRED_HEADSET;
+ handler_.connected_input_devices_.insert(device);
+ handler_.connected_output_devices_.insert(device);
+ EXPECT_CALL(handler_,
+ NotifyAudioPolicyService(device,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
+ handler_.DisconnectAudioDevice(device);
+ EXPECT_EQ(handler_.connected_input_devices_.size(), 1);
+ EXPECT_EQ(handler_.connected_output_devices_.size(), 0);
+}
+
+} // namespace brillo
--- /dev/null
+## -*- coding: utf-8 -*-
+##
+## Copyright (C) 2015 The Android Open Source Project
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+##
+\
+## Generate a list of only Static, Controls, or Dynamic properties.
+<%def name="single_kind_keys(kind_name)">\
+% for outer_namespace in metadata.outer_namespaces: ## assumes single 'android' namespace
+ % for section in outer_namespace.sections:
+ % if section.find_first(lambda x: isinstance(x, metadata_model.Entry) and x.kind == kind_name) and \
+ any_visible(section, kind_name, ('public','ndk_public') ):
+ % for inner_namespace in get_children_by_filtering_kind(section, kind_name, 'namespaces'):
+## We only support 1 level of inner namespace, i.e. android.a.b and android.a.b.c works, but not android.a.b.c.d
+## If we need to support more, we should use a recursive function here instead.. but the indentation gets trickier.
+ % for entry in filter_visibility(inner_namespace.merged_entries, ('public','ndk_public')):
+ % if not entry.synthetic:
+ case ${ndk(entry.name) | csym}:
+ % else:
+ assert(False),"A synthetic key should not present in NDK!"
+ % endif
+ % endfor
+ % endfor
+ % for entry in filter_visibility( \
+ get_children_by_filtering_kind(section, kind_name, 'merged_entries'), \
+ ('public','ndk_public')):
+ % if not entry.synthetic:
+ case ${ndk(entry.name) | csym}:
+ % endif
+ % endfor
+ % endif
+ % endfor
+% endfor
+</%def>\
+/*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
+ * The key entries below this point are generated from metadata
+ * definitions in /system/media/camera/docs. Do not modify by hand or
+ * modify the comment blocks at the start or end.
+ *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~*/
+
+bool
+ACameraMetadata::isCaptureRequestTag(const uint32_t tag) {
+ // Skip check for vendor keys
+ if (isVendorTag(tag)) {
+ return true;
+ }
+
+ switch (tag) {
+${single_kind_keys("controls")}\
+ return true;
+ default:
+ return false;
+ }
+}
+
+// System tags that should be hidden from users
+std::unordered_set<uint32_t> ACameraMetadata::sSystemTags ({
+ % for sec in find_all_sections(metadata):
+ % for entry in remove_synthetic(find_unique_entries(sec)):
+ % if entry.applied_visibility == "system":
+ ${entry.name | csym},
+ % endif
+ % endfor
+ %endfor
+});
+
+/*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
+ * End generated code
+ *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
--- /dev/null
+## -*- coding: utf-8 -*-
+##
+## Copyright (C) 2016 The Android Open Source Project
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+##
+ /*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
+ * The key entries below this point are generated from metadata
+ * definitions in /system/media/camera/docs. Do not modify by hand or
+ * modify the comment blocks at the start or end.
+ *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~*/
+
+ private static HashSet<String> getAllCharacteristicsKeyNames() {
+ HashSet<String> charsKeyNames = new HashSet<String>();
+% for sec in find_all_sections(metadata):
+ % for entry in find_unique_entries(sec):
+ % if entry.kind == 'static' and entry.visibility in ("public", "java_public"):
+ charsKeyNames.add(CameraCharacteristics.${jkey_identifier(entry.name)}.getName());
+ % endif
+ % endfor
+% endfor
+
+ return charsKeyNames;
+ }
+
+ /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
+ * End generated code
+ *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
${value.notes | javadoc(metadata)}\
% endif
* @see ${target_class}#${entry.name | jkey_identifier}
- % if entry.applied_visibility == 'hidden' or value.hidden:
+ % if entry.applied_visibility in ('hidden', 'ndk_public') or value.hidden:
* @hide
%endif
% if value.deprecated:
% for outer_namespace in metadata.outer_namespaces: ## assumes single 'android' namespace
% for section in outer_namespace.sections:
% if section.find_first(lambda x: isinstance(x, metadata_model.Entry) and x.kind == xml_name) and \
- any_visible(section, xml_name, ('public','hidden') ):
+ any_visible(section, xml_name, ('public','hidden', 'ndk_public', 'java_public') ):
% for inner_namespace in get_children_by_filtering_kind(section, xml_name, 'namespaces'):
## We only support 1 level of inner namespace, i.e. android.a.b and android.a.b.c works, but not android.a.b.c.d
## If we need to support more, we should use a recursive function here instead.. but the indentation gets trickier.
- % for entry in filter_visibility(inner_namespace.entries, ('hidden','public')):
+ % for entry in filter_visibility(inner_namespace.entries, ('hidden','public', 'ndk_public', 'java_public')):
% if entry.enum \
and not (entry.typedef and entry.typedef.languages.get('java')) \
and not entry.is_clone():
% endfor
% for entry in filter_visibility( \
get_children_by_filtering_kind(section, xml_name, 'entries'), \
- ('hidden', 'public')):
+ ('hidden', 'public', 'ndk_public', 'java_public')):
% if entry.enum \
and not (entry.typedef and entry.typedef.languages.get('java')) \
and not entry.is_clone():
% if entry.deprecated:
* @deprecated
% endif
- % if entry.applied_visibility == 'hidden':
+ % if entry.applied_visibility in ('hidden', 'ndk_public'):
* @hide
% endif
*/
% if entry.deprecated:
@Deprecated
% endif
- % if entry.applied_visibility == 'public':
+ % if entry.applied_visibility in ('public', 'java_public'):
@PublicKey
% endif
% if entry.synthetic:
% for outer_namespace in metadata.outer_namespaces: ## assumes single 'android' namespace
% for section in outer_namespace.sections:
% if section.find_first(lambda x: isinstance(x, metadata_model.Entry) and x.kind == xml_name) and \
- any_visible(section, xml_name, ('public','hidden') ):
+ any_visible(section, xml_name, ('public','hidden','ndk_public','java_public') ):
% for inner_namespace in get_children_by_filtering_kind(section, xml_name, 'namespaces'):
## We only support 1 level of inner namespace, i.e. android.a.b and android.a.b.c works, but not android.a.b.c.d
## If we need to support more, we should use a recursive function here instead.. but the indentation gets trickier.
- % for entry in filter_visibility(inner_namespace.merged_entries, ('hidden','public')):
+ % for entry in filter_visibility(inner_namespace.merged_entries, ('hidden','public', 'ndk_public', 'java_public')):
${generate_key(entry)}
% endfor
% endfor
% for entry in filter_visibility( \
get_children_by_filtering_kind(section, xml_name, 'merged_entries'), \
- ('hidden', 'public')):
+ ('hidden', 'public', 'ndk_public', 'java_public')):
${generate_key(entry)}
% endfor
% endif
ArrayList<CaptureResult.Key<?>> resultKeys = new ArrayList<CaptureResult.Key<?>>();
% for sec in find_all_sections(metadata):
% for entry in find_unique_entries(sec):
- % if entry.kind == 'dynamic' and entry.visibility == "public":
+ % if entry.kind == 'dynamic' and entry.visibility in ("public", "java_public"):
resultKeys.add(CaptureResult.${jkey_identifier(entry.name)});
% endif
% endfor
--- /dev/null
+// LINT: LEGACY_NAMES
+syntax = "proto2";
+
+package wireless.android.partner.adl.proto;
+
+option java_package = "com.google.wireless.android.partner.adl.proto";
+option java_outer_classname = "CameraDeviceInfoProto";
+
+// Content of this file is generated from $(ANDROID_ROOT)/system/media/camera/doc
+// Keep internal protocol buffer definition in sync with this one
+// Camera related device information
+// Next Id: 9
+message CameraDeviceInfo {
+ // Supported profiles from CamcorderProfile.hasProfile
+ optional bool profile_480p = 1;
+ optional bool profile_720p = 2;
+ optional bool profile_1080p = 3;
+ optional bool profile_cif = 4;
+ optional bool profile_qcif = 5;
+ optional bool profile_qvga = 6;
+ optional int32 num_of_camera = 7;
+
+ message PerCameraInfo {
+ message Rational {
+ optional int32 numerator = 1;
+ optional int32 denominator = 2;
+ }
+
+ message Size {
+ optional int32 width = 1;
+ optional int32 height = 2;
+ }
+
+ message SizeF {
+ optional float width = 1;
+ optional float height = 2;
+ }
+
+ message Rect {
+ optional int32 left = 1;
+ optional int32 right = 2;
+ optional int32 top = 3;
+ optional int32 bottom = 4;
+ }
+
+ message StreamConfigurations {
+ message StreamConfig {
+ optional int32 format = 1;
+ optional int32 width = 2;
+ optional int32 height = 3;
+ optional bool input = 4;
+ optional int64 minFrameDuration = 5;
+ }
+ repeated StreamConfig availableStreamConfigurations = 1;
+ }
+
+ message RangeInt {
+ optional int32 lower = 1;
+ optional int32 upper = 2;
+ }
+
+ message RangeLong {
+ optional int64 lower = 1;
+ optional int64 upper = 2;
+ }
+
+ message ColorSpaceTransform {
+ repeated Rational elements = 1;
+ }
+
+ message BlackLevelPattern {
+ repeated int32 black_level_pattern = 1;
+ }
+
+ optional string cameraId = 1;
+
+ // Start of codegen fields
+<%\
+ section_idx = 1
+%>\
+% for sec in find_all_sections(metadata):
+## Reserve 2^16 tag id space for each section
+<%\
+ idx = section_idx * pow(2,16)
+%>\
+% for entry in find_unique_entries(sec):
+% if entry.kind == 'static' and entry.visibility in ("public", "java_public"):
+ ${protobuf_type(entry)} ${protobuf_name(entry)} = ${idx};
+<%\
+ idx += 1
+%>\
+% endif
+% endfor
+<%\
+ section_idx += 1
+%>\
+% endfor
+ // End of codegen fields
+ }
+
+ // Per camera (front/back) informations
+ repeated PerCameraInfo per_camera_info = 8;
+} // CameraDeviceInfo
+
--- /dev/null
+// LINT: LEGACY_NAMES
+syntax = "proto2";
+
+package wireless.android.partner.adl.proto;
+
+option java_package = "com.google.wireless.android.partner.adl.proto";
+option java_outer_classname = "CameraDeviceInfoProto";
+
+// Content of this file is generated from $(ANDROID_ROOT)/system/media/camera/doc
+// Keep internal protocol buffer definition in sync with this one
+// Camera related device information
+// Next Id: 9
+message CameraDeviceInfo {
+ // Supported profiles from CamcorderProfile.hasProfile
+ optional bool profile_480p = 1;
+ optional bool profile_720p = 2;
+ optional bool profile_1080p = 3;
+ optional bool profile_cif = 4;
+ optional bool profile_qcif = 5;
+ optional bool profile_qvga = 6;
+ optional int32 num_of_camera = 7;
+
+ message PerCameraInfo {
+ message Rational {
+ optional int32 numerator = 1;
+ optional int32 denominator = 2;
+ }
+
+ message Size {
+ optional int32 width = 1;
+ optional int32 height = 2;
+ }
+
+ message SizeF {
+ optional float width = 1;
+ optional float height = 2;
+ }
+
+ message Rect {
+ optional int32 left = 1;
+ optional int32 right = 2;
+ optional int32 top = 3;
+ optional int32 bottom = 4;
+ }
+
+ message StreamConfigurations {
+ message StreamConfig {
+ optional int32 format = 1;
+ optional int32 width = 2;
+ optional int32 height = 3;
+ optional bool input = 4;
+ optional int64 minFrameDuration = 5;
+ }
+ repeated StreamConfig availableStreamConfigurations = 1;
+ }
+
+ message RangeInt {
+ optional int32 lower = 1;
+ optional int32 upper = 2;
+ }
+
+ message RangeLong {
+ optional int64 lower = 1;
+ optional int64 upper = 2;
+ }
+
+ message ColorSpaceTransform {
+ repeated Rational elements = 1;
+ }
+
+ message BlackLevelPattern {
+ repeated int32 black_level_pattern = 1;
+ }
+
+ optional string cameraId = 1;
+
+ // Start of codegen fields
+ repeated int32 android_colorCorrection_availableAberrationModes = 65536;
+ repeated int32 android_control_aeAvailableAntibandingModes = 131072;
+ repeated int32 android_control_aeAvailableModes = 131073;
+ repeated RangeInt android_control_aeAvailableTargetFpsRanges = 131074;
+ optional RangeInt android_control_aeCompensationRange = 131075;
+ optional Rational android_control_aeCompensationStep = 131076;
+ repeated int32 android_control_afAvailableModes = 131077;
+ repeated int32 android_control_availableEffects = 131078;
+ repeated int32 android_control_availableSceneModes = 131079;
+ repeated int32 android_control_availableVideoStabilizationModes = 131080;
+ repeated int32 android_control_awbAvailableModes = 131081;
+ optional int32 android_control_maxRegionsAe = 131082;
+ optional int32 android_control_maxRegionsAwb = 131083;
+ optional int32 android_control_maxRegionsAf = 131084;
+ optional bool android_control_aeLockAvailable = 131085;
+ optional bool android_control_awbLockAvailable = 131086;
+ repeated int32 android_control_availableModes = 131087;
+ optional RangeInt android_control_postRawSensitivityBoostRange = 131088;
+ repeated int32 android_edge_availableEdgeModes = 262144;
+ optional bool android_flash_info_available = 393216;
+ repeated int32 android_hotPixel_availableHotPixelModes = 458752;
+ repeated Size android_jpeg_availableThumbnailSizes = 524288;
+ optional int32 android_lens_facing = 589824;
+ repeated float android_lens_info_availableApertures = 655360;
+ repeated float android_lens_info_availableFilterDensities = 655361;
+ repeated float android_lens_info_availableFocalLengths = 655362;
+ repeated int32 android_lens_info_availableOpticalStabilization = 655363;
+ optional float android_lens_info_hyperfocalDistance = 655364;
+ optional float android_lens_info_minimumFocusDistance = 655365;
+ optional int32 android_lens_info_focusDistanceCalibration = 655366;
+ repeated int32 android_noiseReduction_availableNoiseReductionModes = 720896;
+ optional int32 android_request_maxNumOutputRaw = 851968;
+ optional int32 android_request_maxNumOutputProc = 851969;
+ optional int32 android_request_maxNumOutputProcStalling = 851970;
+ optional int32 android_request_maxNumInputStreams = 851971;
+ optional int32 android_request_pipelineMaxDepth = 851972;
+ optional int32 android_request_partialResultCount = 851973;
+ repeated int32 android_request_availableCapabilities = 851974;
+ optional float android_scaler_availableMaxDigitalZoom = 917504;
+ optional StreamConfigurations android_scaler_streamConfigurationMap = 917505;
+ optional int32 android_scaler_croppingType = 917506;
+ optional int32 android_sensor_referenceIlluminant1 = 983040;
+ optional int32 android_sensor_referenceIlluminant2 = 983041;
+ optional ColorSpaceTransform android_sensor_calibrationTransform1 = 983042;
+ optional ColorSpaceTransform android_sensor_calibrationTransform2 = 983043;
+ optional ColorSpaceTransform android_sensor_colorTransform1 = 983044;
+ optional ColorSpaceTransform android_sensor_colorTransform2 = 983045;
+ optional ColorSpaceTransform android_sensor_forwardMatrix1 = 983046;
+ optional ColorSpaceTransform android_sensor_forwardMatrix2 = 983047;
+ optional BlackLevelPattern android_sensor_blackLevelPattern = 983048;
+ optional int32 android_sensor_maxAnalogSensitivity = 983049;
+ optional int32 android_sensor_orientation = 983050;
+ repeated int32 android_sensor_availableTestPatternModes = 983051;
+ repeated Rect android_sensor_opticalBlackRegions = 983052;
+ optional Rect android_sensor_info_activeArraySize = 1048576;
+ optional RangeInt android_sensor_info_sensitivityRange = 1048577;
+ optional int32 android_sensor_info_colorFilterArrangement = 1048578;
+ optional RangeLong android_sensor_info_exposureTimeRange = 1048579;
+ optional int64 android_sensor_info_maxFrameDuration = 1048580;
+ optional SizeF android_sensor_info_physicalSize = 1048581;
+ optional Size android_sensor_info_pixelArraySize = 1048582;
+ optional int32 android_sensor_info_whiteLevel = 1048583;
+ optional int32 android_sensor_info_timestampSource = 1048584;
+ optional bool android_sensor_info_lensShadingApplied = 1048585;
+ optional Rect android_sensor_info_preCorrectionActiveArraySize = 1048586;
+ repeated int32 android_shading_availableModes = 1114112;
+ repeated int32 android_statistics_info_availableFaceDetectModes = 1245184;
+ optional int32 android_statistics_info_maxFaceCount = 1245185;
+ repeated bool android_statistics_info_availableHotPixelMapModes = 1245186;
+ repeated int32 android_statistics_info_availableLensShadingMapModes = 1245187;
+ optional int32 android_tonemap_maxCurvePoints = 1310720;
+ repeated int32 android_tonemap_availableToneMapModes = 1310721;
+ optional int32 android_info_supportedHardwareLevel = 1441792;
+ optional int32 android_sync_maxLatency = 1572864;
+ optional int32 android_reprocess_maxCaptureStall = 1638400;
+ optional bool android_depth_depthIsExclusive = 1703936;
+ // End of codegen fields
+ }
+
+ // Per camera (front/back) informations
+ repeated PerCameraInfo per_camera_info = 8;
+} // CameraDeviceInfo
+
<head>
<!-- automatically generated from html.mako. do NOT edit directly -->
<meta charset="utf-8" />
- <title>Android Camera HAL3.2 Properties</title>
+ <title>Android Camera HAL3.4 Properties</title>
<style type="text/css">
body { background-color: #f7f7f7; font-family: Roboto, sans-serif;}
h1 { color: #333333; }
><a href="#controls_android.control.sceneMode">android.control.sceneMode</a></li>
<li
><a href="#controls_android.control.videoStabilizationMode">android.control.videoStabilizationMode</a></li>
+ <li
+ ><a href="#controls_android.control.postRawSensitivityBoost">android.control.postRawSensitivityBoost</a></li>
</ul>
</li>
<li>
><a href="#static_android.control.awbLockAvailable">android.control.awbLockAvailable</a></li>
<li
><a href="#static_android.control.availableModes">android.control.availableModes</a></li>
+ <li
+ ><a href="#static_android.control.postRawSensitivityBoostRange">android.control.postRawSensitivityBoostRange</a></li>
</ul>
</li>
<li>
><a href="#dynamic_android.control.sceneMode">android.control.sceneMode</a></li>
<li
><a href="#dynamic_android.control.videoStabilizationMode">android.control.videoStabilizationMode</a></li>
+ <li
+ ><a href="#dynamic_android.control.postRawSensitivityBoost">android.control.postRawSensitivityBoost</a></li>
</ul>
</li>
</ul> <!-- toc_section -->
><a href="#static_android.sensor.profileHueSatMapDimensions">android.sensor.profileHueSatMapDimensions</a></li>
<li
><a href="#static_android.sensor.availableTestPatternModes">android.sensor.availableTestPatternModes</a></li>
+ <li
+ ><a href="#static_android.sensor.opticalBlackRegions">android.sensor.opticalBlackRegions</a></li>
+ <li
+ ><a href="#static_android.sensor.opaqueRawSize">android.sensor.opaqueRawSize</a></li>
</ul>
</li>
<li>
><a href="#dynamic_android.sensor.testPatternMode">android.sensor.testPatternMode</a></li>
<li
><a href="#dynamic_android.sensor.rollingShutterSkew">android.sensor.rollingShutterSkew</a></li>
+ <li
+ ><a href="#dynamic_android.sensor.dynamicBlackLevel">android.sensor.dynamicBlackLevel</a></li>
+ <li
+ ><a href="#dynamic_android.sensor.dynamicWhiteLevel">android.sensor.dynamicWhiteLevel</a></li>
</ul>
</li>
</ul> <!-- toc_section -->
produced in response to a capture request submitted
while in HDR mode.<wbr/></p>
<p>Since substantial post-processing is generally needed to
-produce an HDR image,<wbr/> only YUV and JPEG outputs are
-supported for LIMITED/<wbr/>FULL device HDR captures,<wbr/> and only
-JPEG outputs are supported for LEGACY HDR
-captures.<wbr/> Using a RAW output for HDR capture is not
-supported.<wbr/></p></span>
+produce an HDR image,<wbr/> only YUV,<wbr/> PRIVATE,<wbr/> and JPEG
+outputs are supported for LIMITED/<wbr/>FULL device HDR
+captures,<wbr/> and only JPEG outputs are supported for LEGACY
+HDR captures.<wbr/> Using a RAW output for HDR capture is not
+supported.<wbr/></p>
+<p>Some devices may also support always-on HDR,<wbr/> which
+applies HDR processing at full frame rate.<wbr/> For these
+devices,<wbr/> intents other than STILL_<wbr/>CAPTURE will also
+produce an HDR output with no frame rate impact compared
+to normal operation,<wbr/> though the quality may be lower
+than for STILL_<wbr/>CAPTURE intents.<wbr/></p>
+<p>If SCENE_<wbr/>MODE_<wbr/>HDR is used with unsupported output types
+or capture intents,<wbr/> the images captured will be as if
+the SCENE_<wbr/>MODE was not enabled at all.<wbr/></p></span>
</li>
<li>
<span class="entry_type_enum_name">FACE_PRIORITY_LOW_LIGHT</span>
<a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>,<wbr/> and <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a>
remain active when FACE_<wbr/>PRIORITY_<wbr/>LOW_<wbr/>LIGHT is set.<wbr/></p></span>
</li>
+ <li>
+ <span class="entry_type_enum_name">DEVICE_CUSTOM_START</span>
+ <span class="entry_type_enum_optional">[optional]</span>
+ <span class="entry_type_enum_hidden">[hidden]</span>
+ <span class="entry_type_enum_value">100</span>
+ <span class="entry_type_enum_notes"><p>Scene mode values within the range of
+<code>[DEVICE_<wbr/>CUSTOM_<wbr/>START,<wbr/> DEVICE_<wbr/>CUSTOM_<wbr/>END]</code> are reserved for device specific
+customized scene modes.<wbr/></p></span>
+ </li>
+ <li>
+ <span class="entry_type_enum_name">DEVICE_CUSTOM_END</span>
+ <span class="entry_type_enum_optional">[optional]</span>
+ <span class="entry_type_enum_hidden">[hidden]</span>
+ <span class="entry_type_enum_value">127</span>
+ <span class="entry_type_enum_notes"><p>Scene mode values within the range of
+<code>[DEVICE_<wbr/>CUSTOM_<wbr/>START,<wbr/> DEVICE_<wbr/>CUSTOM_<wbr/>END]</code> are reserved for device specific
+customized scene modes.<wbr/></p></span>
+ </li>
</ul>
</td> <!-- entry_type -->
<tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
<!-- end of entry -->
+
+ <tr class="entry" id="controls_android.control.postRawSensitivityBoost">
+ <td class="entry_name
+ " rowspan="3">
+ android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost
+ </td>
+ <td class="entry_type">
+ <span class="entry_type_name">int32</span>
+
+ <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+ </td> <!-- entry_type -->
+
+ <td class="entry_description">
+ <p>The amount of additional sensitivity boost applied to output images
+after RAW sensor data is captured.<wbr/></p>
+ </td>
+
+ <td class="entry_units">
+ ISO arithmetic units,<wbr/> the same as android.<wbr/>sensor.<wbr/>sensitivity
+ </td>
+
+ <td class="entry_range">
+ <p><a href="#static_android.control.postRawSensitivityBoostRange">android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost<wbr/>Range</a></p>
+ </td>
+
+ <td class="entry_tags">
+ </td>
+
+ </tr>
+ <tr class="entries_header">
+ <th class="th_details" colspan="5">Details</th>
+ </tr>
+ <tr class="entry_cont">
+ <td class="entry_details" colspan="5">
+ <p>Some camera devices support additional digital sensitivity boosting in the
+camera processing pipeline after sensor RAW image is captured.<wbr/>
+Such a boost will be applied to YUV/<wbr/>JPEG format output images but will not
+have effect on RAW output formats like RAW_<wbr/>SENSOR,<wbr/> RAW10,<wbr/> RAW12 or RAW_<wbr/>OPAQUE.<wbr/></p>
+<p>This key will be <code>null</code> for devices that do not support any RAW format
+outputs.<wbr/> For devices that do support RAW format outputs,<wbr/> this key will always
+present,<wbr/> and if a device does not support post RAW sensitivity boost,<wbr/> it will
+list <code>100</code> in this key.<wbr/></p>
+<p>If the camera device cannot apply the exact boost requested,<wbr/> it will reduce the
+boost to the nearest supported value.<wbr/>
+The final boost value used will be available in the output capture result.<wbr/></p>
+<p>For devices that support post RAW sensitivity boost,<wbr/> the YUV/<wbr/>JPEG output images
+of such device will have the total sensitivity of
+<code><a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a> * <a href="#controls_android.control.postRawSensitivityBoost">android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost</a> /<wbr/> 100</code>
+The sensitivity of RAW format images will always be <code><a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a></code></p>
+<p>This control is only effective if <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> or <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> is set to
+OFF; otherwise the auto-exposure algorithm will override this value.<wbr/></p>
+ </td>
+ </tr>
+
+
+ <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+ <!-- end of entry -->
+
<!-- end of kind -->
<td class="entry_details" colspan="5">
<p>For devices at the LEGACY level or above:</p>
<ul>
-<li>This list will always include (30,<wbr/> 30).<wbr/></li>
-<li>Also,<wbr/> for constant-framerate recording,<wbr/> for each normal
+<li>
+<p>For constant-framerate recording,<wbr/> for each normal
+<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a>,<wbr/> that is,<wbr/> a
<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a> that has
<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#quality">quality</a> in
the range [<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#QUALITY_LOW">QUALITY_<wbr/>LOW</a>,<wbr/>
<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#QUALITY_2160P">QUALITY_<wbr/>2160P</a>],<wbr/> if the profile is
supported by the device and has
<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#videoFrameRate">videoFrameRate</a> <code>x</code>,<wbr/> this list will
-always include (<code>x</code>,<wbr/><code>x</code>).<wbr/></li>
-<li>For preview streaming use case,<wbr/> this list will always include (<code>min</code>,<wbr/> <code>max</code>) where
-<code>min</code> <= 15 and <code>max</code> >= 30.<wbr/></li>
+always include (<code>x</code>,<wbr/><code>x</code>).<wbr/></p>
+</li>
+<li>
+<p>Also,<wbr/> a camera device must either not support any
+<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a>,<wbr/>
+or support at least one
+normal <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a> that has
+<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#videoFrameRate">videoFrameRate</a> <code>x</code> >= 24.<wbr/></p>
+</li>
</ul>
<p>For devices at the LIMITED level or above:</p>
<ul>
<span class="entry_type_array">
3
</span>
- <span class="entry_type_visibility"> [hidden]</span>
+ <span class="entry_type_visibility"> [ndk_public]</span>
<span class="entry_type_hwlevel">[legacy] </span>
<td class="entry_type">
<span class="entry_type_name">int32</span>
- <span class="entry_type_visibility"> [public]</span>
+ <span class="entry_type_visibility"> [java_public]</span>
<span class="entry_type_synthetic">[synthetic] </span>
<td class="entry_type">
<span class="entry_type_name">int32</span>
- <span class="entry_type_visibility"> [public]</span>
+ <span class="entry_type_visibility"> [java_public]</span>
<span class="entry_type_synthetic">[synthetic] </span>
<td class="entry_type">
<span class="entry_type_name">int32</span>
- <span class="entry_type_visibility"> [public]</span>
+ <span class="entry_type_visibility"> [java_public]</span>
<span class="entry_type_synthetic">[synthetic] </span>
<tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
<!-- end of entry -->
+
+ <tr class="entry" id="static_android.control.postRawSensitivityBoostRange">
+ <td class="entry_name
+ " rowspan="5">
+ android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost<wbr/>Range
+ </td>
+ <td class="entry_type">
+ <span class="entry_type_name">int32</span>
+ <span class="entry_type_container">x</span>
+
+ <span class="entry_type_array">
+ 2
+ </span>
+ <span class="entry_type_visibility"> [public as rangeInt]</span>
+
+
+
+
+ <div class="entry_type_notes">Range of supported post RAW sensitivitiy boosts</div>
+
+
+ </td> <!-- entry_type -->
+
+ <td class="entry_description">
+ <p>Range of boosts for <a href="#controls_android.control.postRawSensitivityBoost">android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost</a> supported
+by this camera device.<wbr/></p>
+ </td>
+
+ <td class="entry_units">
+ ISO arithmetic units,<wbr/> the same as android.<wbr/>sensor.<wbr/>sensitivity
+ </td>
+
+ <td class="entry_range">
+ </td>
+
+ <td class="entry_tags">
+ </td>
+
+ </tr>
+ <tr class="entries_header">
+ <th class="th_details" colspan="5">Details</th>
+ </tr>
+ <tr class="entry_cont">
+ <td class="entry_details" colspan="5">
+ <p>Devices support post RAW sensitivity boost will advertise
+<a href="#controls_android.control.postRawSensitivityBoost">android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost</a> key for controling
+post RAW sensitivity boost.<wbr/></p>
+<p>This key will be <code>null</code> for devices that do not support any RAW format
+outputs.<wbr/> For devices that do support RAW format outputs,<wbr/> this key will always
+present,<wbr/> and if a device does not support post RAW sensitivity boost,<wbr/> it will
+list <code>(100,<wbr/> 100)</code> in this key.<wbr/></p>
+ </td>
+ </tr>
+
+ <tr class="entries_header">
+ <th class="th_details" colspan="5">HAL Implementation Details</th>
+ </tr>
+ <tr class="entry_cont">
+ <td class="entry_details" colspan="5">
+ <p>This key is added in HAL3.<wbr/>4.<wbr/> For HAL3.<wbr/>3 or earlier devices,<wbr/> camera framework will
+generate this key as <code>(100,<wbr/> 100)</code> if device supports any of RAW output formats.<wbr/>
+All HAL3.<wbr/>4 and above devices should list this key if device supports any of RAW
+output formats.<wbr/></p>
+ </td>
+ </tr>
+
+ <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+ <!-- end of entry -->
+
<!-- end of kind -->
produced in response to a capture request submitted
while in HDR mode.<wbr/></p>
<p>Since substantial post-processing is generally needed to
-produce an HDR image,<wbr/> only YUV and JPEG outputs are
-supported for LIMITED/<wbr/>FULL device HDR captures,<wbr/> and only
-JPEG outputs are supported for LEGACY HDR
-captures.<wbr/> Using a RAW output for HDR capture is not
-supported.<wbr/></p></span>
+produce an HDR image,<wbr/> only YUV,<wbr/> PRIVATE,<wbr/> and JPEG
+outputs are supported for LIMITED/<wbr/>FULL device HDR
+captures,<wbr/> and only JPEG outputs are supported for LEGACY
+HDR captures.<wbr/> Using a RAW output for HDR capture is not
+supported.<wbr/></p>
+<p>Some devices may also support always-on HDR,<wbr/> which
+applies HDR processing at full frame rate.<wbr/> For these
+devices,<wbr/> intents other than STILL_<wbr/>CAPTURE will also
+produce an HDR output with no frame rate impact compared
+to normal operation,<wbr/> though the quality may be lower
+than for STILL_<wbr/>CAPTURE intents.<wbr/></p>
+<p>If SCENE_<wbr/>MODE_<wbr/>HDR is used with unsupported output types
+or capture intents,<wbr/> the images captured will be as if
+the SCENE_<wbr/>MODE was not enabled at all.<wbr/></p></span>
</li>
<li>
<span class="entry_type_enum_name">FACE_PRIORITY_LOW_LIGHT</span>
<a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>,<wbr/> and <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a>
remain active when FACE_<wbr/>PRIORITY_<wbr/>LOW_<wbr/>LIGHT is set.<wbr/></p></span>
</li>
+ <li>
+ <span class="entry_type_enum_name">DEVICE_CUSTOM_START</span>
+ <span class="entry_type_enum_optional">[optional]</span>
+ <span class="entry_type_enum_hidden">[hidden]</span>
+ <span class="entry_type_enum_value">100</span>
+ <span class="entry_type_enum_notes"><p>Scene mode values within the range of
+<code>[DEVICE_<wbr/>CUSTOM_<wbr/>START,<wbr/> DEVICE_<wbr/>CUSTOM_<wbr/>END]</code> are reserved for device specific
+customized scene modes.<wbr/></p></span>
+ </li>
+ <li>
+ <span class="entry_type_enum_name">DEVICE_CUSTOM_END</span>
+ <span class="entry_type_enum_optional">[optional]</span>
+ <span class="entry_type_enum_hidden">[hidden]</span>
+ <span class="entry_type_enum_value">127</span>
+ <span class="entry_type_enum_notes"><p>Scene mode values within the range of
+<code>[DEVICE_<wbr/>CUSTOM_<wbr/>START,<wbr/> DEVICE_<wbr/>CUSTOM_<wbr/>END]</code> are reserved for device specific
+customized scene modes.<wbr/></p></span>
+ </li>
</ul>
</td> <!-- entry_type -->
<tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
<!-- end of entry -->
+
+ <tr class="entry" id="dynamic_android.control.postRawSensitivityBoost">
+ <td class="entry_name
+ " rowspan="3">
+ android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost
+ </td>
+ <td class="entry_type">
+ <span class="entry_type_name">int32</span>
+
+ <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+ </td> <!-- entry_type -->
+
+ <td class="entry_description">
+ <p>The amount of additional sensitivity boost applied to output images
+after RAW sensor data is captured.<wbr/></p>
+ </td>
+
+ <td class="entry_units">
+ ISO arithmetic units,<wbr/> the same as android.<wbr/>sensor.<wbr/>sensitivity
+ </td>
+
+ <td class="entry_range">
+ <p><a href="#static_android.control.postRawSensitivityBoostRange">android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost<wbr/>Range</a></p>
+ </td>
+
+ <td class="entry_tags">
+ </td>
+
+ </tr>
+ <tr class="entries_header">
+ <th class="th_details" colspan="5">Details</th>
+ </tr>
+ <tr class="entry_cont">
+ <td class="entry_details" colspan="5">
+ <p>Some camera devices support additional digital sensitivity boosting in the
+camera processing pipeline after sensor RAW image is captured.<wbr/>
+Such a boost will be applied to YUV/<wbr/>JPEG format output images but will not
+have effect on RAW output formats like RAW_<wbr/>SENSOR,<wbr/> RAW10,<wbr/> RAW12 or RAW_<wbr/>OPAQUE.<wbr/></p>
+<p>This key will be <code>null</code> for devices that do not support any RAW format
+outputs.<wbr/> For devices that do support RAW format outputs,<wbr/> this key will always
+present,<wbr/> and if a device does not support post RAW sensitivity boost,<wbr/> it will
+list <code>100</code> in this key.<wbr/></p>
+<p>If the camera device cannot apply the exact boost requested,<wbr/> it will reduce the
+boost to the nearest supported value.<wbr/>
+The final boost value used will be available in the output capture result.<wbr/></p>
+<p>For devices that support post RAW sensitivity boost,<wbr/> the YUV/<wbr/>JPEG output images
+of such device will have the total sensitivity of
+<code><a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a> * <a href="#controls_android.control.postRawSensitivityBoost">android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost</a> /<wbr/> 100</code>
+The sensitivity of RAW format images will always be <code><a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a></code></p>
+<p>This control is only effective if <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> or <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> is set to
+OFF; otherwise the auto-exposure algorithm will override this value.<wbr/></p>
+ </td>
+ </tr>
+
+
+ <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+ <!-- end of entry -->
+
<!-- end of kind -->
<td class="entry_type">
<span class="entry_type_name">byte</span>
- <span class="entry_type_visibility"> [public as location]</span>
+ <span class="entry_type_visibility"> [java_public as location]</span>
<span class="entry_type_synthetic">[synthetic] </span>
<span class="entry_type_array">
3
</span>
- <span class="entry_type_visibility"> [hidden]</span>
+ <span class="entry_type_visibility"> [ndk_public]</span>
<span class="entry_type_hwlevel">[legacy] </span>
<td class="entry_type">
<span class="entry_type_name">byte</span>
- <span class="entry_type_visibility"> [hidden as string]</span>
+ <span class="entry_type_visibility"> [ndk_public as string]</span>
<span class="entry_type_hwlevel">[legacy] </span>
<td class="entry_type">
<span class="entry_type_name">int64</span>
- <span class="entry_type_visibility"> [hidden]</span>
+ <span class="entry_type_visibility"> [ndk_public]</span>
<span class="entry_type_hwlevel">[legacy] </span>
<td class="entry_type">
<span class="entry_type_name">byte</span>
- <span class="entry_type_visibility"> [public as location]</span>
+ <span class="entry_type_visibility"> [java_public as location]</span>
<span class="entry_type_synthetic">[synthetic] </span>
<span class="entry_type_array">
3
</span>
- <span class="entry_type_visibility"> [hidden]</span>
+ <span class="entry_type_visibility"> [ndk_public]</span>
<span class="entry_type_hwlevel">[legacy] </span>
<td class="entry_type">
<span class="entry_type_name">byte</span>
- <span class="entry_type_visibility"> [hidden as string]</span>
+ <span class="entry_type_visibility"> [ndk_public as string]</span>
<span class="entry_type_hwlevel">[legacy] </span>
<td class="entry_type">
<span class="entry_type_name">int64</span>
- <span class="entry_type_visibility"> [hidden]</span>
+ <span class="entry_type_visibility"> [ndk_public]</span>
<span class="entry_type_hwlevel">[legacy] </span>
<span class="entry_type_array">
2
</span>
- <span class="entry_type_visibility"> [hidden as size]</span>
+ <span class="entry_type_visibility"> [ndk_public as size]</span>
<span class="entry_type_hwlevel">[full] </span>
<span class="entry_type_array">
3
</span>
- <span class="entry_type_visibility"> [hidden]</span>
+ <span class="entry_type_visibility"> [ndk_public]</span>
<span class="entry_type_hwlevel">[legacy] </span>
<td class="entry_type">
<span class="entry_type_name">int32</span>
- <span class="entry_type_visibility"> [public]</span>
+ <span class="entry_type_visibility"> [java_public]</span>
<span class="entry_type_synthetic">[synthetic] </span>
<td class="entry_type">
<span class="entry_type_name">int32</span>
- <span class="entry_type_visibility"> [public]</span>
+ <span class="entry_type_visibility"> [java_public]</span>
<span class="entry_type_synthetic">[synthetic] </span>
<td class="entry_type">
<span class="entry_type_name">int32</span>
- <span class="entry_type_visibility"> [public]</span>
+ <span class="entry_type_visibility"> [java_public]</span>
<span class="entry_type_synthetic">[synthetic] </span>
<span class="entry_type_array">
n
</span>
- <span class="entry_type_visibility"> [hidden]</span>
+ <span class="entry_type_visibility"> [ndk_public]</span>
<span class="entry_type_hwlevel">[legacy] </span>
<span class="entry_type_array">
n
</span>
- <span class="entry_type_visibility"> [hidden]</span>
+ <span class="entry_type_visibility"> [ndk_public]</span>
<span class="entry_type_hwlevel">[legacy] </span>
<span class="entry_type_array">
n
</span>
- <span class="entry_type_visibility"> [hidden]</span>
+ <span class="entry_type_visibility"> [ndk_public]</span>
<span class="entry_type_hwlevel">[legacy] </span>
<span class="entry_type_enum_name">RAW_OPAQUE</span>
<span class="entry_type_enum_optional">[optional]</span>
<span class="entry_type_enum_value">0x24</span>
- <span class="entry_type_enum_notes"><p>RAW_<wbr/>OPAQUE is a format for raw image buffers coming from an
-image sensor.<wbr/></p>
+ <span class="entry_type_enum_notes"><p>RAW_<wbr/>OPAQUE (or
+<a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#RAW_PRIVATE">RAW_<wbr/>PRIVATE</a>
+as referred in public API) is a format for raw image buffers
+coming from an image sensor.<wbr/></p>
<p>The actual structure of buffers of this format is
platform-specific,<wbr/> but must follow several constraints:</p>
<ol>
<span class="entry_type_array">
n x 4
</span>
- <span class="entry_type_visibility"> [hidden as streamConfiguration]</span>
+ <span class="entry_type_visibility"> [ndk_public as streamConfiguration]</span>
<span class="entry_type_hwlevel">[legacy] </span>
<span class="entry_type_array">
4 x n
</span>
- <span class="entry_type_visibility"> [hidden as streamConfigurationDuration]</span>
+ <span class="entry_type_visibility"> [ndk_public as streamConfigurationDuration]</span>
<span class="entry_type_hwlevel">[legacy] </span>
<span class="entry_type_array">
4 x n
</span>
- <span class="entry_type_visibility"> [hidden as streamConfigurationDuration]</span>
+ <span class="entry_type_visibility"> [ndk_public as streamConfigurationDuration]</span>
<span class="entry_type_hwlevel">[legacy] </span>
<td class="entry_type">
<span class="entry_type_name">int32</span>
- <span class="entry_type_visibility"> [public as streamConfigurationMap]</span>
+ <span class="entry_type_visibility"> [java_public as streamConfigurationMap]</span>
<span class="entry_type_synthetic">[synthetic] </span>
requested,<wbr/> it will reduce the gain to the nearest supported
value.<wbr/> The final sensitivity used will be available in the
output capture result.<wbr/></p>
+<p>This control is only effective if <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> or <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> is set to
+OFF; otherwise the auto-exposure algorithm will override this value.<wbr/></p>
</td>
</tr>
(8-14 bits is expected),<wbr/> or by the point where the sensor response
becomes too non-linear to be useful.<wbr/> The default value for this is
maximum representable value for a 16-bit raw sample (2^16 - 1).<wbr/></p>
+<p>The white level values of captured images may vary for different
+capture settings (e.<wbr/>g.,<wbr/> <a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>).<wbr/> This key
+represents a coarse approximation for such case.<wbr/> It is recommended
+to use <a href="#dynamic_android.sensor.dynamicWhiteLevel">android.<wbr/>sensor.<wbr/>dynamic<wbr/>White<wbr/>Level</a> for captures when supported
+by the camera device,<wbr/> which provides more accurate white level values.<wbr/></p>
</td>
</tr>
layout key (see <a href="#static_android.sensor.info.colorFilterArrangement">android.<wbr/>sensor.<wbr/>info.<wbr/>color<wbr/>Filter<wbr/>Arrangement</a>),<wbr/> i.<wbr/>e.<wbr/> the
nth value given corresponds to the black level offset for the nth
color channel listed in the CFA.<wbr/></p>
+<p>The black level values of captured images may vary for different
+capture settings (e.<wbr/>g.,<wbr/> <a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>).<wbr/> This key
+represents a coarse approximation for such case.<wbr/> It is recommended to
+use <a href="#dynamic_android.sensor.dynamicBlackLevel">android.<wbr/>sensor.<wbr/>dynamic<wbr/>Black<wbr/>Level</a> or use pixels from
+<a href="#static_android.sensor.opticalBlackRegions">android.<wbr/>sensor.<wbr/>optical<wbr/>Black<wbr/>Regions</a> directly for captures when
+supported by the camera device,<wbr/> which provides more accurate black
+level values.<wbr/> For raw capture in particular,<wbr/> it is recommended to use
+pixels from <a href="#static_android.sensor.opticalBlackRegions">android.<wbr/>sensor.<wbr/>optical<wbr/>Black<wbr/>Regions</a> to calculate black
+level values for each frame.<wbr/></p>
</td>
</tr>
<tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
<!-- end of entry -->
+
+ <tr class="entry" id="static_android.sensor.opticalBlackRegions">
+ <td class="entry_name
+ " rowspan="5">
+ android.<wbr/>sensor.<wbr/>optical<wbr/>Black<wbr/>Regions
+ </td>
+ <td class="entry_type">
+ <span class="entry_type_name">int32</span>
+ <span class="entry_type_container">x</span>
+
+ <span class="entry_type_array">
+ 4 x num_regions
+ </span>
+ <span class="entry_type_visibility"> [public as rectangle]</span>
+
+
+
+
+
+
+ </td> <!-- entry_type -->
+
+ <td class="entry_description">
+ <p>List of disjoint rectangles indicating the sensor
+optically shielded black pixel regions.<wbr/></p>
+ </td>
+
+ <td class="entry_units">
+ </td>
+
+ <td class="entry_range">
+ </td>
+
+ <td class="entry_tags">
+ </td>
+
+ </tr>
+ <tr class="entries_header">
+ <th class="th_details" colspan="5">Details</th>
+ </tr>
+ <tr class="entry_cont">
+ <td class="entry_details" colspan="5">
+ <p>In most camera sensors,<wbr/> the active array is surrounded by some
+optically shielded pixel areas.<wbr/> By blocking light,<wbr/> these pixels
+provides a reliable black reference for black level compensation
+in active array region.<wbr/></p>
+<p>This key provides a list of disjoint rectangles specifying the
+regions of optically shielded (with metal shield) black pixel
+regions if the camera device is capable of reading out these black
+pixels in the output raw images.<wbr/> In comparison to the fixed black
+level values reported by <a href="#static_android.sensor.blackLevelPattern">android.<wbr/>sensor.<wbr/>black<wbr/>Level<wbr/>Pattern</a>,<wbr/> this key
+may provide a more accurate way for the application to calculate
+black level of each captured raw images.<wbr/></p>
+<p>When this key is reported,<wbr/> the <a href="#dynamic_android.sensor.dynamicBlackLevel">android.<wbr/>sensor.<wbr/>dynamic<wbr/>Black<wbr/>Level</a> and
+<a href="#dynamic_android.sensor.dynamicWhiteLevel">android.<wbr/>sensor.<wbr/>dynamic<wbr/>White<wbr/>Level</a> will also be reported.<wbr/></p>
+ </td>
+ </tr>
+
+ <tr class="entries_header">
+ <th class="th_details" colspan="5">HAL Implementation Details</th>
+ </tr>
+ <tr class="entry_cont">
+ <td class="entry_details" colspan="5">
+ <p>This array contains (xmin,<wbr/> ymin,<wbr/> width,<wbr/> height).<wbr/> The (xmin,<wbr/> ymin)
+must be >= (0,<wbr/>0) and <=
+<a href="#static_android.sensor.info.pixelArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pixel<wbr/>Array<wbr/>Size</a>.<wbr/> The (width,<wbr/> height) must be
+<= <a href="#static_android.sensor.info.pixelArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pixel<wbr/>Array<wbr/>Size</a>.<wbr/> Each region must be
+outside the region reported by
+<a href="#static_android.sensor.info.preCorrectionActiveArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pre<wbr/>Correction<wbr/>Active<wbr/>Array<wbr/>Size</a>.<wbr/></p>
+<p>The HAL must report minimal number of disjoint regions for the
+optically shielded back pixel regions.<wbr/> For example,<wbr/> if a region can
+be covered by one rectangle,<wbr/> the HAL must not split this region into
+multiple rectangles.<wbr/></p>
+ </td>
+ </tr>
+
+ <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+ <!-- end of entry -->
+
+
+ <tr class="entry" id="static_android.sensor.opaqueRawSize">
+ <td class="entry_name
+ " rowspan="5">
+ android.<wbr/>sensor.<wbr/>opaque<wbr/>Raw<wbr/>Size
+ </td>
+ <td class="entry_type">
+ <span class="entry_type_name">int32</span>
+ <span class="entry_type_container">x</span>
+
+ <span class="entry_type_array">
+ n x 3
+ </span>
+ <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+
+ </td> <!-- entry_type -->
+
+ <td class="entry_description">
+ <p>Size in bytes for all the listed opaque RAW buffer sizes</p>
+ </td>
+
+ <td class="entry_units">
+ </td>
+
+ <td class="entry_range">
+ <p>Must be large enough to fit the opaque RAW of corresponding size produced by
+the camera</p>
+ </td>
+
+ <td class="entry_tags">
+ </td>
+
+ </tr>
+ <tr class="entries_header">
+ <th class="th_details" colspan="5">Details</th>
+ </tr>
+ <tr class="entry_cont">
+ <td class="entry_details" colspan="5">
+ <p>This configurations are listed as <code>(width,<wbr/> height,<wbr/> size_<wbr/>in_<wbr/>bytes)</code> tuples.<wbr/>
+This is used for sizing the gralloc buffers for opaque RAW buffers.<wbr/>
+All RAW_<wbr/>OPAQUE output stream configuration listed in
+<a href="#static_android.scaler.availableStreamConfigurations">android.<wbr/>scaler.<wbr/>available<wbr/>Stream<wbr/>Configurations</a> will have a corresponding tuple in
+this key.<wbr/></p>
+ </td>
+ </tr>
+
+ <tr class="entries_header">
+ <th class="th_details" colspan="5">HAL Implementation Details</th>
+ </tr>
+ <tr class="entry_cont">
+ <td class="entry_details" colspan="5">
+ <p>This key is added in HAL3.<wbr/>4.<wbr/>
+For HAL3.<wbr/>4 or above: devices advertising RAW_<wbr/>OPAQUE format output must list this key.<wbr/>
+For HAL3.<wbr/>3 or earlier devices: if RAW_<wbr/>OPAQUE ouput is advertised,<wbr/> camera framework
+will derive this key by assuming each pixel takes two bytes and no padding bytes
+between rows.<wbr/></p>
+ </td>
+ </tr>
+
+ <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+ <!-- end of entry -->
+
<!-- end of kind -->
requested,<wbr/> it will reduce the gain to the nearest supported
value.<wbr/> The final sensitivity used will be available in the
output capture result.<wbr/></p>
+<p>This control is only effective if <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> or <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> is set to
+OFF; otherwise the auto-exposure algorithm will override this value.<wbr/></p>
</td>
</tr>
<tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
<!-- end of entry -->
+
+ <tr class="entry" id="dynamic_android.sensor.dynamicBlackLevel">
+ <td class="entry_name
+ " rowspan="5">
+ android.<wbr/>sensor.<wbr/>dynamic<wbr/>Black<wbr/>Level
+ </td>
+ <td class="entry_type">
+ <span class="entry_type_name">float</span>
+ <span class="entry_type_container">x</span>
+
+ <span class="entry_type_array">
+ 4
+ </span>
+ <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+ <div class="entry_type_notes">2x2 raw count block</div>
+
+
+ </td> <!-- entry_type -->
+
+ <td class="entry_description">
+ <p>A per-frame dynamic black level offset for each of the color filter
+arrangement (CFA) mosaic channels.<wbr/></p>
+ </td>
+
+ <td class="entry_units">
+ </td>
+
+ <td class="entry_range">
+ <p>>= 0 for each.<wbr/></p>
+ </td>
+
+ <td class="entry_tags">
+ <ul class="entry_tags">
+ <li><a href="#tag_RAW">RAW</a></li>
+ </ul>
+ </td>
+
+ </tr>
+ <tr class="entries_header">
+ <th class="th_details" colspan="5">Details</th>
+ </tr>
+ <tr class="entry_cont">
+ <td class="entry_details" colspan="5">
+ <p>Camera sensor black levels may vary dramatically for different
+capture settings (e.<wbr/>g.<wbr/> <a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>).<wbr/> The fixed black
+level reported by <a href="#static_android.sensor.blackLevelPattern">android.<wbr/>sensor.<wbr/>black<wbr/>Level<wbr/>Pattern</a> may be too
+inaccurate to represent the actual value on a per-frame basis.<wbr/> The
+camera device internal pipeline relies on reliable black level values
+to process the raw images appropriately.<wbr/> To get the best image
+quality,<wbr/> the camera device may choose to estimate the per frame black
+level values either based on optically shielded black regions
+(<a href="#static_android.sensor.opticalBlackRegions">android.<wbr/>sensor.<wbr/>optical<wbr/>Black<wbr/>Regions</a>) or its internal model.<wbr/></p>
+<p>This key reports the camera device estimated per-frame zero light
+value for each of the CFA mosaic channels in the camera sensor.<wbr/> The
+<a href="#static_android.sensor.blackLevelPattern">android.<wbr/>sensor.<wbr/>black<wbr/>Level<wbr/>Pattern</a> may only represent a coarse
+approximation of the actual black level values.<wbr/> This value is the
+black level used in camera device internal image processing pipeline
+and generally more accurate than the fixed black level values.<wbr/>
+However,<wbr/> since they are estimated values by the camera device,<wbr/> they
+may not be as accurate as the black level values calculated from the
+optical black pixels reported by <a href="#static_android.sensor.opticalBlackRegions">android.<wbr/>sensor.<wbr/>optical<wbr/>Black<wbr/>Regions</a>.<wbr/></p>
+<p>The values are given in the same order as channels listed for the CFA
+layout key (see <a href="#static_android.sensor.info.colorFilterArrangement">android.<wbr/>sensor.<wbr/>info.<wbr/>color<wbr/>Filter<wbr/>Arrangement</a>),<wbr/> i.<wbr/>e.<wbr/> the
+nth value given corresponds to the black level offset for the nth
+color channel listed in the CFA.<wbr/></p>
+<p>This key will be available if <a href="#static_android.sensor.opticalBlackRegions">android.<wbr/>sensor.<wbr/>optical<wbr/>Black<wbr/>Regions</a> is
+available or the camera device advertises this key via
+<a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#getAvailableCaptureResultKeys">CameraCharacteristics#getAvailableCaptureResultKeys</a>.<wbr/></p>
+ </td>
+ </tr>
+
+ <tr class="entries_header">
+ <th class="th_details" colspan="5">HAL Implementation Details</th>
+ </tr>
+ <tr class="entry_cont">
+ <td class="entry_details" colspan="5">
+ <p>The values are given in row-column scan order,<wbr/> with the first value
+corresponding to the element of the CFA in row=0,<wbr/> column=0.<wbr/></p>
+ </td>
+ </tr>
+
+ <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+ <!-- end of entry -->
+
+
+ <tr class="entry" id="dynamic_android.sensor.dynamicWhiteLevel">
+ <td class="entry_name
+ " rowspan="5">
+ android.<wbr/>sensor.<wbr/>dynamic<wbr/>White<wbr/>Level
+ </td>
+ <td class="entry_type">
+ <span class="entry_type_name">int32</span>
+
+ <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+ </td> <!-- entry_type -->
+
+ <td class="entry_description">
+ <p>Maximum raw value output by sensor for this frame.<wbr/></p>
+ </td>
+
+ <td class="entry_units">
+ </td>
+
+ <td class="entry_range">
+ <p>>= 0</p>
+ </td>
+
+ <td class="entry_tags">
+ <ul class="entry_tags">
+ <li><a href="#tag_RAW">RAW</a></li>
+ </ul>
+ </td>
+
+ </tr>
+ <tr class="entries_header">
+ <th class="th_details" colspan="5">Details</th>
+ </tr>
+ <tr class="entry_cont">
+ <td class="entry_details" colspan="5">
+ <p>Since the <a href="#static_android.sensor.blackLevelPattern">android.<wbr/>sensor.<wbr/>black<wbr/>Level<wbr/>Pattern</a> may change for different
+capture settings (e.<wbr/>g.,<wbr/> <a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>),<wbr/> the white
+level will change accordingly.<wbr/> This key is similar to
+<a href="#static_android.sensor.info.whiteLevel">android.<wbr/>sensor.<wbr/>info.<wbr/>white<wbr/>Level</a>,<wbr/> but specifies the camera device
+estimated white level for each frame.<wbr/></p>
+<p>This key will be available if <a href="#static_android.sensor.opticalBlackRegions">android.<wbr/>sensor.<wbr/>optical<wbr/>Black<wbr/>Regions</a> is
+available or the camera device advertises this key via
+<a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#getAvailableCaptureRequestKeys">CameraCharacteristics#getAvailableCaptureRequestKeys</a>.<wbr/></p>
+ </td>
+ </tr>
+
+ <tr class="entries_header">
+ <th class="th_details" colspan="5">HAL Implementation Details</th>
+ </tr>
+ <tr class="entry_cont">
+ <td class="entry_details" colspan="5">
+ <p>The full bit depth of the sensor must be available in the raw data,<wbr/>
+so the value for linear sensors should not be significantly lower
+than maximum raw value supported,<wbr/> i.<wbr/>e.<wbr/> 2^(sensor bits per pixel).<wbr/></p>
+ </td>
+ </tr>
+
+ <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+ <!-- end of entry -->
+
<!-- end of kind -->
<span class="entry_type_array">
n
</span>
- <span class="entry_type_visibility"> [hidden]</span>
+ <span class="entry_type_visibility"> [ndk_public]</span>
<span class="entry_type_hwlevel">[legacy] </span>
<span class="entry_type_array">
n x 6
</span>
- <span class="entry_type_visibility"> [hidden]</span>
+ <span class="entry_type_visibility"> [ndk_public]</span>
<span class="entry_type_hwlevel">[legacy] </span>
<span class="entry_type_array">
n x 4
</span>
- <span class="entry_type_visibility"> [hidden as rectangle]</span>
+ <span class="entry_type_visibility"> [ndk_public as rectangle]</span>
<span class="entry_type_hwlevel">[legacy] </span>
<span class="entry_type_array">
n
</span>
- <span class="entry_type_visibility"> [hidden]</span>
+ <span class="entry_type_visibility"> [ndk_public]</span>
<span class="entry_type_hwlevel">[legacy] </span>
<span class="entry_type_array">
n
</span>
- <span class="entry_type_visibility"> [public as face]</span>
+ <span class="entry_type_visibility"> [java_public as face]</span>
<span class="entry_type_synthetic">[synthetic] </span>
<span class="entry_type_array">
4 x n x m
</span>
- <span class="entry_type_visibility"> [hidden]</span>
+ <span class="entry_type_visibility"> [ndk_public]</span>
<span class="entry_type_hwlevel">[full] </span>
<td class="entry_description">
<p>The shading map is a low-resolution floating-point map
-that lists the coefficients used to correct for vignetting,<wbr/> for each
-Bayer color channel of RAW image data.<wbr/></p>
+that lists the coefficients used to correct for vignetting and color shading,<wbr/>
+for each Bayer color channel of RAW image data.<wbr/></p>
</td>
<td class="entry_units">
</tr>
<tr class="entry_cont">
<td class="entry_details" colspan="5">
- <p>The least shaded section of the image should have a gain factor
-of 1; all other sections should have gains above 1.<wbr/></p>
+ <p>The lens shading correction is defined as a full shading correction that
+corrects both color shading for the output non-RAW images.<wbr/> After the
+shading map is applied,<wbr/> the output non-RAW images will be flat-field images
+for flat scenes under uniform illumination.<wbr/></p>
+<p>When there is no lens shading correction applied to RAW output images
+(<a href="#static_android.sensor.info.lensShadingApplied">android.<wbr/>sensor.<wbr/>info.<wbr/>lens<wbr/>Shading<wbr/>Applied</a> <code>==</code> false),<wbr/> this map is a full lens
+shading correction map; when there is some lens shading correction applied
+to the RAW output image (<a href="#static_android.sensor.info.lensShadingApplied">android.<wbr/>sensor.<wbr/>info.<wbr/>lens<wbr/>Shading<wbr/>Applied</a> <code>==</code> true),<wbr/>
+this map reports the remaining lens shading correction map that needs to be
+applied to get fully shading corrected images.<wbr/></p>
+<p>For a full shading correction map,<wbr/> the least shaded section of the image
+should have a gain factor of 1; all other sections should have gains above 1.<wbr/></p>
<p>When <a href="#controls_android.colorCorrection.mode">android.<wbr/>color<wbr/>Correction.<wbr/>mode</a> = TRANSFORM_<wbr/>MATRIX,<wbr/> the map
must take into account the colorCorrection settings.<wbr/></p>
<p>The shading map is for the entire active pixel array,<wbr/> and is not
<span class="entry_type_array">
n x 2
</span>
- <span class="entry_type_visibility"> [hidden]</span>
+ <span class="entry_type_visibility"> [ndk_public]</span>
<span class="entry_type_hwlevel">[full] </span>
<span class="entry_type_array">
n x 2
</span>
- <span class="entry_type_visibility"> [hidden]</span>
+ <span class="entry_type_visibility"> [ndk_public]</span>
<span class="entry_type_hwlevel">[full] </span>
<span class="entry_type_array">
n x 2
</span>
- <span class="entry_type_visibility"> [hidden]</span>
+ <span class="entry_type_visibility"> [ndk_public]</span>
<span class="entry_type_hwlevel">[full] </span>
<td class="entry_type">
<span class="entry_type_name">float</span>
- <span class="entry_type_visibility"> [public as tonemapCurve]</span>
+ <span class="entry_type_visibility"> [java_public as tonemapCurve]</span>
<span class="entry_type_synthetic">[synthetic] </span>
<span class="entry_type_array">
n x 2
</span>
- <span class="entry_type_visibility"> [hidden]</span>
+ <span class="entry_type_visibility"> [ndk_public]</span>
<span class="entry_type_hwlevel">[full] </span>
<span class="entry_type_array">
n x 2
</span>
- <span class="entry_type_visibility"> [hidden]</span>
+ <span class="entry_type_visibility"> [ndk_public]</span>
<span class="entry_type_hwlevel">[full] </span>
<span class="entry_type_array">
n x 2
</span>
- <span class="entry_type_visibility"> [hidden]</span>
+ <span class="entry_type_visibility"> [ndk_public]</span>
<span class="entry_type_hwlevel">[full] </span>
<td class="entry_type">
<span class="entry_type_name">float</span>
- <span class="entry_type_visibility"> [public as tonemapCurve]</span>
+ <span class="entry_type_visibility"> [java_public as tonemapCurve]</span>
<span class="entry_type_synthetic">[synthetic] </span>
<ul class="entry_type_enum">
<li>
<span class="entry_type_enum_name">LIMITED</span>
- <span class="entry_type_enum_notes"><p>This camera device has only limited capabilities.<wbr/></p></span>
+ <span class="entry_type_enum_notes"><p>This camera device does not have enough capabilities to qualify as a <code>FULL</code> device or
+better.<wbr/></p>
+<p>Only the stream configurations listed in the <code>LEGACY</code> and <code>LIMITED</code> tables in the
+<a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createCaptureSession">createCaptureSession</a> documentation are guaranteed to be supported.<wbr/></p>
+<p>All <code>LIMITED</code> devices support the <code>BACKWARDS_<wbr/>COMPATIBLE</code> capability,<wbr/> indicating basic
+support for color image capture.<wbr/> The only exception is that the device may
+alternatively support only the <code>DEPTH_<wbr/>OUTPUT</code> capability,<wbr/> if it can only output depth
+measurements and not color images.<wbr/></p>
+<p><code>LIMITED</code> devices and above require the use of <a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a>
+to lock exposure metering (and calculate flash power,<wbr/> for cameras with flash) before
+capturing a high-quality still image.<wbr/></p>
+<p>A <code>LIMITED</code> device that only lists the <code>BACKWARDS_<wbr/>COMPATIBLE</code> capability is only
+required to support full-automatic operation and post-processing (<code>OFF</code> is not
+supported for <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a>,<wbr/> <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a>,<wbr/> or
+<a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>)</p>
+<p>Additional capabilities may optionally be supported by a <code>LIMITED</code>-level device,<wbr/> and
+can be checked for in <a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a>.<wbr/></p></span>
</li>
<li>
<span class="entry_type_enum_name">FULL</span>
- <span class="entry_type_enum_notes"><p>This camera device is capable of supporting advanced imaging applications.<wbr/></p></span>
+ <span class="entry_type_enum_notes"><p>This camera device is capable of supporting advanced imaging applications.<wbr/></p>
+<p>The stream configurations listed in the <code>FULL</code>,<wbr/> <code>LEGACY</code> and <code>LIMITED</code> tables in the
+<a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createCaptureSession">createCaptureSession</a> documentation are guaranteed to be supported.<wbr/></p>
+<p>A <code>FULL</code> device will support below capabilities:</p>
+<ul>
+<li><code>BURST_<wbr/>CAPTURE</code> capability (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains
+ <code>BURST_<wbr/>CAPTURE</code>)</li>
+<li>Per frame control (<a href="#static_android.sync.maxLatency">android.<wbr/>sync.<wbr/>max<wbr/>Latency</a> <code>==</code> PER_<wbr/>FRAME_<wbr/>CONTROL)</li>
+<li>Manual sensor control (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains <code>MANUAL_<wbr/>SENSOR</code>)</li>
+<li>Manual post-processing control (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains
+ <code>MANUAL_<wbr/>POST_<wbr/>PROCESSING</code>)</li>
+<li>The required exposure time range defined in <a href="#static_android.sensor.info.exposureTimeRange">android.<wbr/>sensor.<wbr/>info.<wbr/>exposure<wbr/>Time<wbr/>Range</a></li>
+<li>The required maxFrameDuration defined in <a href="#static_android.sensor.info.maxFrameDuration">android.<wbr/>sensor.<wbr/>info.<wbr/>max<wbr/>Frame<wbr/>Duration</a></li>
+</ul>
+<p>Note:
+Pre-API level 23,<wbr/> FULL devices also supported arbitrary cropping region
+(<a href="#static_android.scaler.croppingType">android.<wbr/>scaler.<wbr/>cropping<wbr/>Type</a> <code>== FREEFORM</code>); this requirement was relaxed in API level
+23,<wbr/> and <code>FULL</code> devices may only support <code>CENTERED</code> cropping.<wbr/></p></span>
</li>
<li>
<span class="entry_type_enum_name">LEGACY</span>
- <span class="entry_type_enum_notes"><p>This camera device is running in backward compatibility mode.<wbr/></p></span>
+ <span class="entry_type_enum_notes"><p>This camera device is running in backward compatibility mode.<wbr/></p>
+<p>Only the stream configurations listed in the <code>LEGACY</code> table in the <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createCaptureSession">createCaptureSession</a>
+documentation are supported.<wbr/></p>
+<p>A <code>LEGACY</code> device does not support per-frame control,<wbr/> manual sensor control,<wbr/> manual
+post-processing,<wbr/> arbitrary cropping regions,<wbr/> and has relaxed performance constraints.<wbr/>
+No additional capabilities beyond <code>BACKWARD_<wbr/>COMPATIBLE</code> will ever be listed by a
+<code>LEGACY</code> device in <a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a>.<wbr/></p>
+<p>In addition,<wbr/> the <a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a> is not functional on <code>LEGACY</code>
+devices.<wbr/> Instead,<wbr/> every request that includes a JPEG-format output target is treated
+as triggering a still capture,<wbr/> internally executing a precapture trigger.<wbr/> This may
+fire the flash for flash power metering during precapture,<wbr/> and then fire the flash
+for the final capture,<wbr/> if a flash is available on the device and the AE mode is set to
+enable the flash.<wbr/></p></span>
+ </li>
+ <li>
+ <span class="entry_type_enum_name">3</span>
+ <span class="entry_type_enum_notes"><p>This camera device is capable of YUV reprocessing and RAW data capture,<wbr/> in addition to
+FULL-level capabilities.<wbr/></p>
+<p>The stream configurations listed in the <code>LEVEL_<wbr/>3</code>,<wbr/> <code>RAW</code>,<wbr/> <code>FULL</code>,<wbr/> <code>LEGACY</code> and
+<code>LIMITED</code> tables in the <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createCaptureSession">createCaptureSession</a>
+documentation are guaranteed to be supported.<wbr/></p>
+<p>The following additional capabilities are guaranteed to be supported:</p>
+<ul>
+<li><code>YUV_<wbr/>REPROCESSING</code> capability (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains
+ <code>YUV_<wbr/>REPROCESSING</code>)</li>
+<li><code>RAW</code> capability (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains
+ <code>RAW</code>)</li>
+</ul></span>
</li>
</ul>
</tr>
<tr class="entry_cont">
<td class="entry_details" colspan="5">
- <p>Camera devices will come in three flavors: LEGACY,<wbr/> LIMITED and FULL.<wbr/></p>
-<p>A FULL device will support below capabilities:</p>
+ <p>The supported hardware level is a high-level description of the camera device's
+capabilities,<wbr/> summarizing several capabilities into one field.<wbr/> Each level adds additional
+features to the previous one,<wbr/> and is always a strict superset of the previous level.<wbr/>
+The ordering is <code>LEGACY < LIMITED < FULL < LEVEL_<wbr/>3</code>.<wbr/></p>
+<p>Starting from <code>LEVEL_<wbr/>3</code>,<wbr/> the level enumerations are guaranteed to be in increasing
+numerical value as well.<wbr/> To check if a given device is at least at a given hardware level,<wbr/>
+the following code snippet can be used:</p>
+<pre><code>//<wbr/> Returns true if the device supports the required hardware level,<wbr/> or better.<wbr/>
+boolean isHardwareLevelSupported(CameraCharacteristics c,<wbr/> int requiredLevel) {
+ int deviceLevel = c.<wbr/>get(Camera<wbr/>Characteristics.<wbr/>INFO_<wbr/>SUPPORTED_<wbr/>HARDWARE_<wbr/>LEVEL);
+ if (deviceLevel == Camera<wbr/>Characteristics.<wbr/>INFO_<wbr/>SUPPORTED_<wbr/>HARDWARE_<wbr/>LEVEL_<wbr/>LEGACY) {
+ return requiredLevel == deviceLevel;
+ }
+ //<wbr/> deviceLevel is not LEGACY,<wbr/> can use numerical sort
+ return requiredLevel <= deviceLevel;
+}
+</code></pre>
+<p>At a high level,<wbr/> the levels are:</p>
<ul>
-<li>BURST_<wbr/>CAPTURE capability (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains BURST_<wbr/>CAPTURE)</li>
-<li>Per frame control (<a href="#static_android.sync.maxLatency">android.<wbr/>sync.<wbr/>max<wbr/>Latency</a> <code>==</code> PER_<wbr/>FRAME_<wbr/>CONTROL)</li>
-<li>Manual sensor control (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains MANUAL_<wbr/>SENSOR)</li>
-<li>Manual post-processing control (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains
- MANUAL_<wbr/>POST_<wbr/>PROCESSING)</li>
-<li>At least 3 processed (but not stalling) format output streams
- (<a href="#static_android.request.maxNumOutputProc">android.<wbr/>request.<wbr/>max<wbr/>Num<wbr/>Output<wbr/>Proc</a> <code>>=</code> 3)</li>
-<li>The required stream configurations defined in <a href="#static_android.scaler.availableStreamConfigurations">android.<wbr/>scaler.<wbr/>available<wbr/>Stream<wbr/>Configurations</a></li>
-<li>The required exposure time range defined in <a href="#static_android.sensor.info.exposureTimeRange">android.<wbr/>sensor.<wbr/>info.<wbr/>exposure<wbr/>Time<wbr/>Range</a></li>
-<li>The required maxFrameDuration defined in <a href="#static_android.sensor.info.maxFrameDuration">android.<wbr/>sensor.<wbr/>info.<wbr/>max<wbr/>Frame<wbr/>Duration</a></li>
+<li><code>LEGACY</code> devices operate in a backwards-compatibility mode for older
+ Android devices,<wbr/> and have very limited capabilities.<wbr/></li>
+<li><code>LIMITED</code> devices represent the
+ baseline feature set,<wbr/> and may also include additional capabilities that are
+ subsets of <code>FULL</code>.<wbr/></li>
+<li><code>FULL</code> devices additionally support per-frame manual control of sensor,<wbr/> flash,<wbr/> lens and
+ post-processing settings,<wbr/> and image capture at a high rate.<wbr/></li>
+<li><code>LEVEL_<wbr/>3</code> devices additionally support YUV reprocessing and RAW image capture,<wbr/> along
+ with additional output stream configurations.<wbr/></li>
</ul>
-<p>A LIMITED device may have some or none of the above characteristics.<wbr/>
-To find out more refer to <a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a>.<wbr/></p>
+<p>See the individual level enums for full descriptions of the supported capabilities.<wbr/> The
+<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> entry describes the device's capabilities at a
+finer-grain level,<wbr/> if needed.<wbr/> In addition,<wbr/> many controls have their available settings or
+ranges defined in individual <a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html">CameraCharacteristics</a> entries.<wbr/></p>
<p>Some features are not part of any particular hardware level or capability and must be
queried separately.<wbr/> These include:</p>
<ul>
(<a href="#static_android.lens.info.availableOpticalStabilization">android.<wbr/>lens.<wbr/>info.<wbr/>available<wbr/>Optical<wbr/>Stabilization</a>,<wbr/>
<a href="#static_android.control.availableVideoStabilizationModes">android.<wbr/>control.<wbr/>available<wbr/>Video<wbr/>Stabilization<wbr/>Modes</a>)</li>
</ul>
-<p>A LEGACY device does not support per-frame control,<wbr/> manual sensor control,<wbr/> manual
-post-processing,<wbr/> arbitrary cropping regions,<wbr/> and has relaxed performance constraints.<wbr/></p>
-<p>Each higher level supports everything the lower level supports
-in this order: FULL <code>></code> LIMITED <code>></code> LEGACY.<wbr/></p>
-<p>Note:
-Pre-API level 23,<wbr/> FULL devices also supported arbitrary cropping region
-(<a href="#static_android.scaler.croppingType">android.<wbr/>scaler.<wbr/>cropping<wbr/>Type</a> <code>==</code> FREEFORM); this requirement was relaxed in API level 23,<wbr/>
-and FULL devices may only support CENTERED cropping.<wbr/></p>
</td>
</tr>
</tr>
<tr class="entry_cont">
<td class="entry_details" colspan="5">
- <p>The camera 3 HAL device can implement one of two possible
-operational modes; limited and full.<wbr/> Full support is
-expected from new higher-end devices.<wbr/> Limited mode has
-hardware requirements roughly in line with those for a
-camera HAL device v1 implementation,<wbr/> and is expected from
-older or inexpensive devices.<wbr/> Full is a strict superset of
-limited,<wbr/> and they share the same essential operational flow.<wbr/></p>
+ <p>The camera 3 HAL device can implement one of three possible operational modes; LIMITED,<wbr/>
+FULL,<wbr/> and LEVEL_<wbr/>3.<wbr/></p>
+<p>FULL support or better is expected from new higher-end devices.<wbr/> Limited
+mode has hardware requirements roughly in line with those for a camera HAL device v1
+implementation,<wbr/> and is expected from older or inexpensive devices.<wbr/> Each level is a strict
+superset of the previous level,<wbr/> and they share the same essential operational flow.<wbr/></p>
<p>For full details refer to "S3.<wbr/> Operational Modes" in camera3.<wbr/>h</p>
-<p>Camera HAL3+ must not implement LEGACY mode.<wbr/> It is there
-for backwards compatibility in the <code>android.<wbr/>hardware.<wbr/>camera2</code>
-user-facing API only.<wbr/></p>
+<p>Camera HAL3+ must not implement LEGACY mode.<wbr/> It is there for backwards compatibility in
+the <code>android.<wbr/>hardware.<wbr/>camera2</code> user-facing API only on HALv1 devices,<wbr/> and is implemented
+by the camera framework code.<wbr/></p>
</td>
</tr>
<td class="entry_type">
<span class="entry_type_name entry_type_name_enum">int64</span>
- <span class="entry_type_visibility"> [hidden]</span>
+ <span class="entry_type_visibility"> [ndk_public]</span>
<span class="entry_type_hwlevel">[legacy] </span>
<code>4 - 2 = 2</code>.<wbr/></p>
<p>Use <code>frame_<wbr/>count</code> from camera3_<wbr/>request_<wbr/>t instead of
<a href="#controls_android.request.frameCount">android.<wbr/>request.<wbr/>frame<wbr/>Count</a> or
-<code>@link{android.<wbr/>hardware.<wbr/>camera2.<wbr/>Capture<wbr/>Result#get<wbr/>Frame<wbr/>Number}</code>.<wbr/></p>
+<code><a href="https://developer.android.com/reference/android/hardware/camera2/CaptureResult.html#getFrameNumber">CaptureResult#getFrameNumber</a></code>.<wbr/></p>
<p>LIMITED devices are strongly encouraged to use a non-negative
value.<wbr/> If UNKNOWN is used here then app developers do not have a way
to know when sensor settings have been applied.<wbr/></p>
<td class="entry_type">
<span class="entry_type_name">float</span>
- <span class="entry_type_visibility"> [public]</span>
+ <span class="entry_type_visibility"> [java_public]</span>
<span class="entry_type_hwlevel">[limited] </span>
<td class="entry_type">
<span class="entry_type_name">float</span>
- <span class="entry_type_visibility"> [public]</span>
+ <span class="entry_type_visibility"> [java_public]</span>
<span class="entry_type_hwlevel">[limited] </span>
<td class="entry_type">
<span class="entry_type_name">int32</span>
- <span class="entry_type_visibility"> [public]</span>
+ <span class="entry_type_visibility"> [java_public]</span>
<span class="entry_type_hwlevel">[limited] </span>
<span class="entry_type_array">
n x 4
</span>
- <span class="entry_type_visibility"> [hidden as streamConfiguration]</span>
+ <span class="entry_type_visibility"> [ndk_public as streamConfiguration]</span>
<span class="entry_type_hwlevel">[limited] </span>
<span class="entry_type_array">
4 x n
</span>
- <span class="entry_type_visibility"> [hidden as streamConfigurationDuration]</span>
+ <span class="entry_type_visibility"> [ndk_public as streamConfigurationDuration]</span>
<span class="entry_type_hwlevel">[limited] </span>
<span class="entry_type_array">
4 x n
</span>
- <span class="entry_type_visibility"> [hidden as streamConfigurationDuration]</span>
+ <span class="entry_type_visibility"> [ndk_public as streamConfigurationDuration]</span>
<span class="entry_type_hwlevel">[limited] </span>
<li><a href="#dynamic_android.sensor.profileHueSatMap">android.sensor.profileHueSatMap</a> (dynamic)</li>
<li><a href="#dynamic_android.sensor.profileToneCurve">android.sensor.profileToneCurve</a> (dynamic)</li>
<li><a href="#dynamic_android.sensor.greenSplit">android.sensor.greenSplit</a> (dynamic)</li>
+ <li><a href="#dynamic_android.sensor.dynamicBlackLevel">android.sensor.dynamicBlackLevel</a> (dynamic)</li>
+ <li><a href="#dynamic_android.sensor.dynamicWhiteLevel">android.sensor.dynamicWhiteLevel</a> (dynamic)</li>
<li><a href="#controls_android.statistics.hotPixelMapMode">android.statistics.hotPixelMapMode</a> (controls)</li>
<li><a href="#static_android.statistics.info.availableHotPixelMapModes">android.statistics.info.availableHotPixelMapModes</a> (static)</li>
<li><a href="#dynamic_android.statistics.hotPixelMap">android.statistics.hotPixelMap</a> (dynamic)</li>
<head>
<!-- automatically generated from html.mako. do NOT edit directly -->
<meta charset="utf-8" />
- <title>Android Camera HAL3.2 Properties</title>
+ <title>Android Camera HAL3.4 Properties</title>
<style type="text/css">
body { background-color: #f7f7f7; font-family: Roboto, sans-serif;}
h1 { color: #333333; }
# docs.html
# ../src/camera_metadata_tag_info.c
# ../src/camera_metadata_tags.h
-# ../../../../cts/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureResultTest.java
+# ../../../../frameworks/av/include/camera/ndk/NdkCameraMetadataTags.h
+# ../../../../frameworks/av/camera/ndk/impl/ACameraMetadata.cpp
+# ../../../../cts/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java
# ../../../../frameworks/base/core/java/android/hardware/camera2/CameraCharacteristics.java
# ../../../../frameworks/base/core/java/android/hardware/camera2/CaptureRequest.java
# ../../../../frameworks/base/core/java/android/hardware/camera2/CaptureResult.java
thisdir=$(cd "$(dirname "$0")"; pwd)
fwkdir="$ANDROID_BUILD_TOP/frameworks/base/core/java/android/hardware/camera2/"
fwkdir_html="$ANDROID_BUILD_TOP/frameworks/base/docs/html"
-ctsdir="$ANDROID_BUILD_TOP/cts/tests/tests/hardware/src/android/hardware/camera2/cts"
+ctsdir="$ANDROID_BUILD_TOP/cts/tests/camera/src/android/hardware/camera2/cts"
outdir="$ANDROID_PRODUCT_OUT/obj/ETC/system-media-camera-docs_intermediates"
+ndk_header_dir="$ANDROID_BUILD_TOP/frameworks/av/include/camera/ndk"
+ndk_impl_dir="$ANDROID_BUILD_TOP/frameworks/av/camera/ndk/impl"
+device_info_dir="$ANDROID_BUILD_TOP/cts/tools/cts-device-info/"`
+ `"src/com/android/cts/deviceinfo"
out_files=()
function relpath() {
gen_file camera_metadata_tag_info.mako ../src/camera_metadata_tag_info.c || exit 1
gen_file camera_metadata_tags.mako ../include/system/camera_metadata_tags.h || exit 1
+#Generate NDK header
+gen_file_abs ndk_camera_metadata_tags.mako "$ndk_header_dir/NdkCameraMetadataTags.h" || exit 1
+
# Generate Java API definitions
mkdir -p "${outdir}"
gen_file_abs CameraMetadataEnums.mako "$outdir/CameraMetadataEnums.java.part" no || exit 1
gen_file_abs CameraCharacteristicsKeys.mako "$outdir/CameraCharacteristicsKeys.java.part" no || exit 1
gen_file_abs CaptureRequestKeys.mako "$outdir/CaptureRequestKeys.java.part" no || exit 1
gen_file_abs CaptureResultKeys.mako "$outdir/CaptureResultKeys.java.part" no || exit 1
-gen_file_abs CaptureResultTest.mako "$outdir/CaptureResultTest.java.part" no || exit 1
insert_file "$outdir/CameraMetadataEnums.java.part" "$fwkdir/CameraMetadata.java" || exit 1
insert_file "$outdir/CameraCharacteristicsKeys.java.part" "$fwkdir/CameraCharacteristics.java" || exit 1
insert_file "$outdir/CaptureRequestKeys.java.part" "$fwkdir/CaptureRequest.java" || exit 1
insert_file "$outdir/CaptureResultKeys.java.part" "$fwkdir/CaptureResult.java" || exit 1
+
+# Generate CTS test code
+gen_file_abs CaptureResultTest.mako "$outdir/CaptureResultTest.java.part" no || exit 1
insert_file "$outdir/CaptureResultTest.java.part" "$ctsdir/CaptureResultTest.java" || exit 1
+# Generate NDK implementation
+gen_file_abs ACameraMetadata.mako "$outdir/ACameraMetadata.cpp.part" no || exit 1
+insert_file "$outdir/ACameraMetadata.cpp.part" "$ndk_impl_dir/ACameraMetadata.cpp" || exit 1
+
+# Generate CameraDeviceInfo code
+gen_file_abs CameraDeviceInfo.mako "$outdir/CameraDeviceInfo.java.part" no || exit 1
+insert_file "$outdir/CameraDeviceInfo.java.part" "$device_info_dir/CameraDeviceInfo.java" || exit 1
+
+# Generate protocol buffer definition corresponding to CameraDeviceInfo
+gen_file camera_device_info.mako ./camera_device_info.proto || exit 1
+
# Copy ./images directory into javadoc directory
copy_directory "images" "$fwkdir_html" || exit 1
return ".".join((i.name for i in path))
+def ndk(name):
+ """
+ Return the NDK version of given name, which replace
+ the leading "android" to "acamera"
+
+ Args:
+ name: name string of an entry
+
+ Returns:
+ A NDK version name string of the input name
+ """
+ name_list = name.split(".")
+ if name_list[0] == "android":
+ name_list[0] = "acamera"
+ return ".".join(name_list)
+
+def protobuf_type(entry):
+ """
+ Return the protocol buffer message type for input metadata entry.
+ Only support types used by static metadata right now
+
+ Returns:
+ A string of protocol buffer type. Ex: "optional int32" or "repeated RangeInt"
+ """
+ typeName = None
+ if entry.typedef is None:
+ typeName = entry.type
+ else:
+ typeName = entry.typedef.name
+
+ typename_to_protobuftype = {
+ "rational" : "Rational",
+ "size" : "Size",
+ "sizeF" : "SizeF",
+ "rectangle" : "Rect",
+ "streamConfigurationMap" : "StreamConfigurations",
+ "rangeInt" : "RangeInt",
+ "rangeLong" : "RangeLong",
+ "colorSpaceTransform" : "ColorSpaceTransform",
+ "blackLevelPattern" : "BlackLevelPattern",
+ "byte" : "int32", # protocol buffer don't support byte
+ "boolean" : "bool",
+ "float" : "float",
+ "double" : "double",
+ "int32" : "int32",
+ "int64" : "int64",
+ "enumList" : "int32"
+ }
+
+ if typeName not in typename_to_protobuftype:
+ print >> sys.stderr,\
+ " ERROR: Could not find protocol buffer type for {%s} type {%s} typedef {%s}" % \
+ (entry.name, entry.type, entry.typedef)
+
+ proto_type = typename_to_protobuftype[typeName]
+
+ prefix = "optional"
+ if entry.container == 'array':
+ has_variable_size = False
+ for size in entry.container_sizes:
+ try:
+ size_int = int(size)
+ except ValueError:
+ has_variable_size = True
+
+ if has_variable_size:
+ prefix = "repeated"
+
+ return "%s %s" %(prefix, proto_type)
+
+
+def protobuf_name(entry):
+ """
+ Return the protocol buffer field name for input metadata entry
+
+ Returns:
+ A string. Ex: "android_colorCorrection_availableAberrationModes"
+ """
+ return entry.name.replace(".", "_")
+
def has_descendants_with_enums(node):
"""
Determine whether or not the current node is or has any descendants with an
# Convert metadata entry "android.x.y.z" to form
# "{@link CaptureRequest#X_Y_Z android.x.y.z}"
def javadoc_crossref_filter(node):
- if node.applied_visibility == 'public':
+ if node.applied_visibility in ('public', 'java_public'):
return '{@link %s#%s %s}' % (kind_mapping[node.kind],
jkey_identifier(node.name),
node.name)
# For each public tag "android.x.y.z" referenced, add a
# "@see CaptureRequest#X_Y_Z"
def javadoc_crossref_see_filter(node_set):
- node_set = (x for x in node_set if x.applied_visibility == 'public')
+ node_set = (x for x in node_set if x.applied_visibility in ('public', 'java_public'))
text = '\n'
for node in node_set:
return javadoc_formatter
+def ndkdoc(metadata, indent = 4):
+ """
+ Returns a function to format a markdown syntax text block as a
+ NDK camera API C/C++ comment section, given a set of metadata
+
+ Args:
+ metadata: A Metadata instance, representing the the top-level root
+ of the metadata for cross-referencing
+ indent: baseline level of indentation for comment block
+ Returns:
+ A function that transforms a String text block as follows:
+ - Indent and * for insertion into a comment block
+ - Trailing whitespace removed
+ - Entire body rendered via markdown
+ - All tag names converted to appropriate NDK tag name for each tag
+
+ Example:
+ "This is a comment for NDK\n" +
+ " with multiple lines, that should be \n" +
+ " formatted better\n" +
+ "\n" +
+ " That covers multiple lines as well\n"
+ " And references android.control.mode\n"
+
+ transforms to
+ " * This is a comment for NDK\n" +
+ " * with multiple lines, that should be\n" +
+ " * formatted better\n" +
+ " * That covers multiple lines as well\n" +
+ " * and references ACAMERA_CONTROL_MODE\n" +
+ " *\n" +
+ " * @see ACAMERA_CONTROL_MODE\n"
+ """
+ def ndkdoc_formatter(text):
+ # render with markdown => HTML
+ ndktext = md(text, JAVADOC_IMAGE_SRC_METADATA)
+
+ # Convert metadata entry "android.x.y.z" to form
+ # NDK tag format of "ACAMERA_X_Y_Z"
+ def ndkdoc_crossref_filter(node):
+ if node.applied_ndk_visible == 'true':
+ return csym(ndk(node.name))
+ else:
+ return node.name
+
+ # For each public tag "android.x.y.z" referenced, add a
+ # "@see ACAMERA_X_Y_Z"
+ def ndkdoc_crossref_see_filter(node_set):
+ node_set = (x for x in node_set if x.applied_ndk_visible == 'true')
+
+ text = '\n'
+ for node in node_set:
+ text = text + '\n@see %s' % (csym(ndk(node.name)))
+
+ return text if text != '\n' else ''
+
+ ndktext = filter_tags(ndktext, metadata, ndkdoc_crossref_filter, ndkdoc_crossref_see_filter)
+
+ ndktext = ndk_replace_tag_wildcards(ndktext, metadata)
+
+ comment_prefix = " " * indent + " * ";
+
+ def line_filter(line):
+ # Indent each line
+ # Add ' * ' to it for stylistic reasons
+ # Strip right side of trailing whitespace
+ return (comment_prefix + line).rstrip()
+
+ # Process each line with above filter
+ ndktext = "\n".join(line_filter(i) for i in ndktext.split("\n")) + "\n"
+
+ return ndktext
+
+ return ndkdoc_formatter
+
def dedent(text):
"""
Remove all common indentation from every line but the 0th.
else:
return text
+def ndk_replace_tag_wildcards(text, metadata):
+ """
+ Find all references to tags in the form android.xxx.* or android.xxx.yyy.*
+ in the provided text, and replace them by NDK format of "ACAMERA_XXX_*" or
+ "ACAMERA_XXX_YYY_*"
+
+ Args:
+ text: A string representing a block of text destined for output
+ metadata: A Metadata instance, the root of the metadata properties tree
+ """
+ tag_match = r"android\.([a-zA-Z0-9\n]+)\.\*"
+ tag_match_2 = r"android\.([a-zA-Z0-9\n]+)\.([a-zA-Z0-9\n]+)\*"
+
+ def filter_sub(match):
+ return "ACAMERA_" + match.group(1).upper() + "_*"
+ def filter_sub_2(match):
+ return "ACAMERA_" + match.group(1).upper() + match.group(2).upper() + "_*"
+
+ text = re.sub(tag_match, filter_sub, text)
+ text = re.sub(tag_match_2, filter_sub_2, text)
+ return text
+
def filter_links(text, filter_function, summary_function = None):
"""
Find all references to tags in the form {@link xxx#yyy [zzz]} in the
"""
return (e for e in entries if not e.synthetic)
+def filter_ndk_visible(entries):
+ """
+ Filter the given entries by removing those that are not NDK visible.
+
+ Args:
+ entries: An iterable of Entry nodes
+
+ Yields:
+ An iterable of Entry nodes
+ """
+ return (e for e in entries if e.applied_ndk_visible == 'true')
+
def wbr(text):
"""
Insert word break hints for the browser in the form of <wbr> HTML tags.
self._entry_map[p.kind].pop(p.name)
self._entries_ordered.remove(p)
+ def is_entry_this_kind(self, entry, kind):
+ """
+ Check if input entry if of input kind
+
+ Args:
+ entry: an Entry object
+ kind: a string. Possible values are "static", "dynamic", "controls"
+
+ Returns:
+ A boolean indicating whether input entry is of input kind.
+ """
+ if kind not in ("static", "dynamic", "controls"):
+ assert(False), "Unknown kind value " + kind
+
+ return entry.name in self._entry_map[kind]
# After all entries/clones are inserted,
# invoke this to generate the parent/child node graph all these objects
deprecated: A boolean, True if the enum should be deprecated.
optional: A boolean
hidden: A boolean, True if the enum should be hidden.
+ ndk_hidden: A boolean, True if the enum should be hidden in NDK
notes: A string describing the notes, or None.
parent: An edge to the parent, always an Enum instance.
"""
- def __init__(self, name, parent, id=None, deprecated=False, optional=False, hidden=False, notes=None):
+ def __init__(self, name, parent,
+ id=None, deprecated=False, optional=False, hidden=False, notes=None, ndk_hidden=False):
self._name = name # str, e.g. 'ON' or 'OFF'
self._id = id # int, e.g. '0'
self._deprecated = deprecated # bool
self._optional = optional # bool
self._hidden = hidden # bool
+ self._ndk_hidden = ndk_hidden # bool
self._notes = notes # None or str
self._parent = parent
return self._hidden
@property
+ def ndk_hidden(self):
+ return self._ndk_hidden
+
+ @property
def notes(self):
return self._notes
has_values_with_id: A boolean representing if any of the children have a
non-empty id property.
"""
- def __init__(self, parent, values, ids={}, deprecateds=[], optionals=[], hiddens=[], notes={}):
+ def __init__(self, parent, values, ids={}, deprecateds=[],
+ optionals=[], hiddens=[], notes={}, ndk_hiddens=[]):
self._values = \
[ EnumValue(val, self, ids.get(val), val in deprecateds, val in optionals, val in hiddens, \
- notes.get(val)) \
+ notes.get(val), val in ndk_hiddens) \
for val in values ]
self._parent = parent
public entries are visible in the Android SDK.
applied_visibility: As visibility, but always valid, defaulting to 'system'
if no visibility is given for an entry.
+ applied_ndk_visible: Always valid. Default is 'false'.
+ Set to 'true' when the visibility implied entry is visible
+ in NDK.
synthetic: The C-level visibility of this entry ('false', 'true').
Synthetic entries will not be generated into the native metadata
list of entries (in C code). In general a synthetic entry is
return self._visibility or 'system'
@property
+ def applied_ndk_visible(self):
+ if self._visibility in ("public", "ndk_public"):
+ return "true"
+ return "false"
+
+ @property
def synthetic(self):
return self._synthetic
enum_deprecateds = kwargs.get('enum_deprecateds')
enum_optionals = kwargs.get('enum_optionals')
enum_hiddens = kwargs.get('enum_hiddens')
+ enum_ndk_hiddens = kwargs.get('enum_ndk_hiddens')
enum_notes = kwargs.get('enum_notes') # { value => notes }
enum_ids = kwargs.get('enum_ids') # { value => notes }
self._tuple_values = kwargs.get('tuple_values')
if kwargs.get('enum', False):
self._enum = Enum(self, enum_values, enum_ids, enum_deprecateds, enum_optionals,
- enum_hiddens, enum_notes)
+ enum_hiddens, enum_notes, enum_ndk_hiddens)
else:
self._enum = None
self._hwlevel = kwargs.get('hwlevel')
self._deprecated = kwargs.get('deprecated', False)
self._optional = kwargs.get('optional')
+ self._ndk_visible = kwargs.get('ndk_visible')
self._property_keys = kwargs
'type',
'type_notes',
'visibility',
+ 'ndk_visible',
'synthetic',
'hwlevel',
'deprecated',
enum_deprecateds = []
enum_optionals = []
enum_hiddens = []
+ enum_ndk_hiddens = []
enum_notes = {}
enum_ids = {}
for value in entry.enum.find_all('value'):
if value.attrs.get('hidden', 'false') == 'true':
enum_hiddens.append(value_body)
+ if value.attrs.get('ndk_hidden', 'false') == 'true':
+ enum_ndk_hiddens.append(value_body)
+
notes = value.find('notes')
if notes is not None:
enum_notes[value_body] = notes.string
d['enum_deprecateds'] = enum_deprecateds
d['enum_optionals'] = enum_optionals
d['enum_hiddens'] = enum_hiddens
+ d['enum_ndk_hiddens'] = enum_ndk_hiddens
d['enum_notes'] = enum_notes
d['enum_ids'] = enum_ids
d['enum'] = True
while in HDR mode.
Since substantial post-processing is generally needed to
- produce an HDR image, only YUV and JPEG outputs are
- supported for LIMITED/FULL device HDR captures, and only
- JPEG outputs are supported for LEGACY HDR
- captures. Using a RAW output for HDR capture is not
+ produce an HDR image, only YUV, PRIVATE, and JPEG
+ outputs are supported for LIMITED/FULL device HDR
+ captures, and only JPEG outputs are supported for LEGACY
+ HDR captures. Using a RAW output for HDR capture is not
supported.
+
+ Some devices may also support always-on HDR, which
+ applies HDR processing at full frame rate. For these
+ devices, intents other than STILL_CAPTURE will also
+ produce an HDR output with no frame rate impact compared
+ to normal operation, though the quality may be lower
+ than for STILL_CAPTURE intents.
+
+ If SCENE_MODE_HDR is used with unsupported output types
+ or capture intents, the images captured will be as if
+ the SCENE_MODE was not enabled at all.
</notes>
</value>
<value optional="true" hidden="true">FACE_PRIORITY_LOW_LIGHT
remain active when FACE_PRIORITY_LOW_LIGHT is set.
</notes>
</value>
+ <value optional="true" hidden="true" id="100">DEVICE_CUSTOM_START
+ <notes>
+ Scene mode values within the range of
+ `[DEVICE_CUSTOM_START, DEVICE_CUSTOM_END]` are reserved for device specific
+ customized scene modes.
+ </notes>
+ </value>
+ <value optional="true" hidden="true" id="127">DEVICE_CUSTOM_END
+ <notes>
+ Scene mode values within the range of
+ `[DEVICE_CUSTOM_START, DEVICE_CUSTOM_END]` are reserved for device specific
+ customized scene modes.
+ </notes>
+ </value>
</enum>
<description>
Control for which scene mode is currently active.
<details>
For devices at the LEGACY level or above:
- * This list will always include (30, 30).
- * Also, for constant-framerate recording, for each normal
+ * For constant-framerate recording, for each normal
+ {@link android.media.CamcorderProfile CamcorderProfile}, that is, a
{@link android.media.CamcorderProfile CamcorderProfile} that has
{@link android.media.CamcorderProfile#quality quality} in
the range [{@link android.media.CamcorderProfile#QUALITY_LOW QUALITY_LOW},
supported by the device and has
{@link android.media.CamcorderProfile#videoFrameRate videoFrameRate} `x`, this list will
always include (`x`,`x`).
- * For preview streaming use case, this list will always include (`min`, `max`) where
- `min` <= 15 and `max` >= 30.
+
+ * Also, a camera device must either not support any
+ {@link android.media.CamcorderProfile CamcorderProfile},
+ or support at least one
+ normal {@link android.media.CamcorderProfile CamcorderProfile} that has
+ {@link android.media.CamcorderProfile#videoFrameRate videoFrameRate} `x` >= 24.
For devices at the LIMITED level or above:
</details>
<tag id="BC" />
</entry>
- <entry name="maxRegions" type="int32" visibility="hidden"
+ <entry name="maxRegions" type="int32" visibility="ndk_public"
container="array" hwlevel="legacy">
<array>
<size>3</size>
`(AE, AWB, AF)`.</range>
<tag id="BC" />
</entry>
- <entry name="maxRegionsAe" type="int32" visibility="public"
+ <entry name="maxRegionsAe" type="int32" visibility="java_public"
synthetic="true" hwlevel="legacy">
<description>
The maximum number of metering regions that can be used by the auto-exposure (AE)
maxRegions to have this entry be automatically populated.
</hal_details>
</entry>
- <entry name="maxRegionsAwb" type="int32" visibility="public"
+ <entry name="maxRegionsAwb" type="int32" visibility="java_public"
synthetic="true" hwlevel="legacy">
<description>
The maximum number of metering regions that can be used by the auto-white balance (AWB)
maxRegions to have this entry be automatically populated.
</hal_details>
</entry>
- <entry name="maxRegionsAf" type="int32" visibility="public"
+ <entry name="maxRegionsAf" type="int32" visibility="java_public"
synthetic="true" hwlevel="legacy">
<description>
The maximum number of metering regions that can be used by the auto-focus (AF) routine.
devices will always support OFF, AUTO modes.
</details>
</entry>
+ <entry name="postRawSensitivityBoostRange" type="int32" visibility="public"
+ type_notes="Range of supported post RAW sensitivitiy boosts"
+ container="array" typedef="rangeInt">
+ <array>
+ <size>2</size>
+ </array>
+ <description>Range of boosts for android.control.postRawSensitivityBoost supported
+ by this camera device.
+ </description>
+ <units>ISO arithmetic units, the same as android.sensor.sensitivity</units>
+ <details>
+ Devices support post RAW sensitivity boost will advertise
+ android.control.postRawSensitivityBoost key for controling
+ post RAW sensitivity boost.
+
+ This key will be `null` for devices that do not support any RAW format
+ outputs. For devices that do support RAW format outputs, this key will always
+ present, and if a device does not support post RAW sensitivity boost, it will
+ list `(100, 100)` in this key.
+ </details>
+ <hal_details>
+ This key is added in HAL3.4. For HAL3.3 or earlier devices, camera framework will
+ generate this key as `(100, 100)` if device supports any of RAW output formats.
+ All HAL3.4 and above devices should list this key if device supports any of RAW
+ output formats.
+ </hal_details>
+ </entry>
</static>
+ <controls>
+ <entry name="postRawSensitivityBoost" type="int32" visibility="public">
+ <description>The amount of additional sensitivity boost applied to output images
+ after RAW sensor data is captured.
+ </description>
+ <units>ISO arithmetic units, the same as android.sensor.sensitivity</units>
+ <range>android.control.postRawSensitivityBoostRange</range>
+ <details>
+ Some camera devices support additional digital sensitivity boosting in the
+ camera processing pipeline after sensor RAW image is captured.
+ Such a boost will be applied to YUV/JPEG format output images but will not
+ have effect on RAW output formats like RAW_SENSOR, RAW10, RAW12 or RAW_OPAQUE.
+
+ This key will be `null` for devices that do not support any RAW format
+ outputs. For devices that do support RAW format outputs, this key will always
+ present, and if a device does not support post RAW sensitivity boost, it will
+ list `100` in this key.
+
+ If the camera device cannot apply the exact boost requested, it will reduce the
+ boost to the nearest supported value.
+ The final boost value used will be available in the output capture result.
+
+ For devices that support post RAW sensitivity boost, the YUV/JPEG output images
+ of such device will have the total sensitivity of
+ `android.sensor.sensitivity * android.control.postRawSensitivityBoost / 100`
+ The sensitivity of RAW format images will always be `android.sensor.sensitivity`
+
+ This control is only effective if android.control.aeMode or android.control.mode is set to
+ OFF; otherwise the auto-exposure algorithm will override this value.
+ </details>
+ </entry>
+ </controls>
+ <dynamic>
+ <clone entry="android.control.postRawSensitivityBoost" kind="controls">
+ </clone>
+ </dynamic>
</section>
<section name="demosaic">
<controls>
</section>
<section name="jpeg">
<controls>
- <entry name="gpsLocation" type="byte" visibility="public" synthetic="true"
+ <entry name="gpsLocation" type="byte" visibility="java_public" synthetic="true"
typedef="location" hwlevel="legacy">
<description>
A location object to use when generating image GPS metadata.
viewed by anyone who receives the JPEG image.
</details>
</entry>
- <entry name="gpsCoordinates" type="double" visibility="hidden"
+ <entry name="gpsCoordinates" type="double" visibility="ndk_public"
type_notes="latitude, longitude, altitude. First two in degrees, the third in meters"
container="array" hwlevel="legacy">
<array>
<range>(-180 - 180], [-90,90], [-inf, inf]</range>
<tag id="BC" />
</entry>
- <entry name="gpsProcessingMethod" type="byte" visibility="hidden"
+ <entry name="gpsProcessingMethod" type="byte" visibility="ndk_public"
typedef="string" hwlevel="legacy">
<description>32 characters describing GPS algorithm to
include in EXIF.</description>
<units>UTF-8 null-terminated string</units>
<tag id="BC" />
</entry>
- <entry name="gpsTimestamp" type="int64" visibility="hidden" hwlevel="legacy">
+ <entry name="gpsTimestamp" type="int64" visibility="ndk_public" hwlevel="legacy">
<description>Time GPS fix was made to include in
EXIF.</description>
<units>UTC in seconds since January 1, 1970</units>
the MANUAL_SENSOR capability.</hal_details>
<tag id="V1" />
</entry>
- <entry name="shadingMapSize" type="int32" visibility="hidden"
+ <entry name="shadingMapSize" type="int32" visibility="ndk_public"
type_notes="width and height (N, M) of lens shading map provided by the camera device."
container="array" typedef="size" hwlevel="full">
<array>
</entry>
</controls>
<static>
- <entry name="maxNumOutputStreams" type="int32" visibility="hidden"
- container="array" hwlevel="legacy">
+ <entry name="maxNumOutputStreams" type="int32" visibility="ndk_public"
+ container="array" hwlevel="legacy">
<array>
<size>3</size>
</array>
</details>
<tag id="BC" />
</entry>
- <entry name="maxNumOutputRaw" type="int32" visibility="public" synthetic="true" hwlevel="legacy">
+ <entry name="maxNumOutputRaw" type="int32" visibility="java_public" synthetic="true"
+ hwlevel="legacy">
<description>The maximum numbers of different types of output streams
that can be configured and used simultaneously by a camera device
for any `RAW` formats.
never support raw streams.
</details>
</entry>
- <entry name="maxNumOutputProc" type="int32" visibility="public" synthetic="true" hwlevel="legacy">
+ <entry name="maxNumOutputProc" type="int32" visibility="java_public" synthetic="true"
+ hwlevel="legacy">
<description>The maximum numbers of different types of output streams
that can be configured and used simultaneously by a camera device
for any processed (but not-stalling) formats.
LEGACY devices will support at least 2 processing/non-stalling streams.
</details>
</entry>
- <entry name="maxNumOutputProcStalling" type="int32" visibility="public" synthetic="true" hwlevel="legacy">
+ <entry name="maxNumOutputProcStalling" type="int32" visibility="java_public" synthetic="true"
+ hwlevel="legacy">
<description>The maximum numbers of different types of output streams
that can be configured and used simultaneously by a camera device
for any processed (and stalling) formats.
by the camera device.
</notes>
</value>
- <value optional="true">PRIVATE_REPROCESSING
+ <value optional="true" ndk_hidden="true">PRIVATE_REPROCESSING
<notes>
The camera device supports the Zero Shutter Lag reprocessing use case.
consistent image output.
</notes>
</value>
- <value optional="true">YUV_REPROCESSING
+ <value optional="true" ndk_hidden="true">YUV_REPROCESSING
<notes>
The camera device supports the YUV_420_888 reprocessing use case, similar as
PRIVATE_REPROCESSING, This capability requires the camera device to support the
rate, including depth stall time.
</notes>
</value>
- <value optional="true">CONSTRAINED_HIGH_SPEED_VIDEO
+ <value optional="true" ndk_hidden="true">CONSTRAINED_HIGH_SPEED_VIDEO
<notes>
The device supports constrained high speed video recording (frame rate >=120fps)
use case. The camera device will support high speed capture session created by
DEPTH).
</hal_details>
</entry>
- <entry name="availableRequestKeys" type="int32" visibility="hidden"
- container="array" hwlevel="legacy">
+ <entry name="availableRequestKeys" type="int32" visibility="ndk_public"
+ container="array" hwlevel="legacy">
<array>
<size>n</size>
</array>
{@link android.hardware.camera2.CameraCharacteristics#getAvailableCaptureRequestKeys}.
</hal_details>
</entry>
- <entry name="availableResultKeys" type="int32" visibility="hidden"
- container="array" hwlevel="legacy">
+ <entry name="availableResultKeys" type="int32" visibility="ndk_public"
+ container="array" hwlevel="legacy">
<array>
<size>n</size>
</array>
android.hardware.camera2.CameraCharacteristics#getAvailableCaptureResultKeys}.
</hal_details>
</entry>
- <entry name="availableCharacteristicsKeys" type="int32" visibility="hidden"
- container="array" hwlevel="legacy">
+ <entry name="availableCharacteristicsKeys" type="int32" visibility="ndk_public"
+ container="array" hwlevel="legacy">
<array>
<size>n</size>
</array>
</value>
<value optional="true" id="0x24">RAW_OPAQUE
<notes>
- RAW_OPAQUE is a format for raw image buffers coming from an
- image sensor.
+ RAW_OPAQUE (or
+ {@link android.graphics.ImageFormat#RAW_PRIVATE RAW_PRIVATE}
+ as referred in public API) is a format for raw image buffers
+ coming from an image sensor.
The actual structure of buffers of this format is
platform-specific, but must follow several constraints:
</hal_details>
<tag id="REPROC" />
</entry>
- <entry name="availableStreamConfigurations" type="int32" visibility="hidden"
- enum="true" container="array"
- typedef="streamConfiguration" hwlevel="legacy">
+ <entry name="availableStreamConfigurations" type="int32" visibility="ndk_public"
+ enum="true" container="array" typedef="streamConfiguration" hwlevel="legacy">
<array>
<size>n</size>
<size>4</size>
* available[Processed,Raw,Jpeg]Sizes
</hal_details>
</entry>
- <entry name="availableMinFrameDurations" type="int64" visibility="hidden"
- container="array"
- typedef="streamConfigurationDuration" hwlevel="legacy">
+ <entry name="availableMinFrameDurations" type="int64" visibility="ndk_public"
+ container="array" typedef="streamConfigurationDuration" hwlevel="legacy">
<array>
<size>4</size>
<size>n</size>
</details>
<tag id="V1" />
</entry>
- <entry name="availableStallDurations" type="int64" visibility="hidden"
+ <entry name="availableStallDurations" type="int64" visibility="ndk_public"
container="array" typedef="streamConfigurationDuration" hwlevel="legacy">
<array>
<size>4</size>
</hal_details>
<tag id="V1" />
</entry>
- <entry name="streamConfigurationMap" type="int32" visibility="public"
+ <entry name="streamConfigurationMap" type="int32" visibility="java_public"
synthetic="true" typedef="streamConfigurationMap"
hwlevel="legacy">
<description>The available stream configurations that this
requested, it will reduce the gain to the nearest supported
value. The final sensitivity used will be available in the
output capture result.
+
+ This control is only effective if android.control.aeMode or android.control.mode is set to
+ OFF; otherwise the auto-exposure algorithm will override this value.
</details>
<hal_details>ISO 12232:2006 REI method is acceptable.</hal_details>
<tag id="V1" />
(8-14 bits is expected), or by the point where the sensor response
becomes too non-linear to be useful. The default value for this is
maximum representable value for a 16-bit raw sample (2^16 - 1).
+
+ The white level values of captured images may vary for different
+ capture settings (e.g., android.sensor.sensitivity). This key
+ represents a coarse approximation for such case. It is recommended
+ to use android.sensor.dynamicWhiteLevel for captures when supported
+ by the camera device, which provides more accurate white level values.
</details>
<hal_details>
The full bit depth of the sensor must be available in the raw data,
layout key (see android.sensor.info.colorFilterArrangement), i.e. the
nth value given corresponds to the black level offset for the nth
color channel listed in the CFA.
+
+ The black level values of captured images may vary for different
+ capture settings (e.g., android.sensor.sensitivity). This key
+ represents a coarse approximation for such case. It is recommended to
+ use android.sensor.dynamicBlackLevel or use pixels from
+ android.sensor.opticalBlackRegions directly for captures when
+ supported by the camera device, which provides more accurate black
+ level values. For raw capture in particular, it is recommended to use
+ pixels from android.sensor.opticalBlackRegions to calculate black
+ level values for each frame.
</details>
<hal_details>
The values are given in row-column scan order, with the first value
<tag id="V1" />
</entry>
</dynamic>
+ <static>
+ <entry name="opticalBlackRegions" type="int32" visibility="public" optional="true"
+ container="array" typedef="rectangle">
+ <array>
+ <size>4</size>
+ <size>num_regions</size>
+ </array>
+ <description>List of disjoint rectangles indicating the sensor
+ optically shielded black pixel regions.
+ </description>
+ <details>
+ In most camera sensors, the active array is surrounded by some
+ optically shielded pixel areas. By blocking light, these pixels
+ provides a reliable black reference for black level compensation
+ in active array region.
+
+ This key provides a list of disjoint rectangles specifying the
+ regions of optically shielded (with metal shield) black pixel
+ regions if the camera device is capable of reading out these black
+ pixels in the output raw images. In comparison to the fixed black
+ level values reported by android.sensor.blackLevelPattern, this key
+ may provide a more accurate way for the application to calculate
+ black level of each captured raw images.
+
+ When this key is reported, the android.sensor.dynamicBlackLevel and
+ android.sensor.dynamicWhiteLevel will also be reported.
+ </details>
+ <hal_details>
+ This array contains (xmin, ymin, width, height). The (xmin, ymin)
+ must be &gt;= (0,0) and &lt;=
+ android.sensor.info.pixelArraySize. The (width, height) must be
+ &lt;= android.sensor.info.pixelArraySize. Each region must be
+ outside the region reported by
+ android.sensor.info.preCorrectionActiveArraySize.
+
+ The HAL must report minimal number of disjoint regions for the
+ optically shielded back pixel regions. For example, if a region can
+ be covered by one rectangle, the HAL must not split this region into
+ multiple rectangles.
+ </hal_details>
+ </entry>
+ </static>
+ <dynamic>
+ <entry name="dynamicBlackLevel" type="float" visibility="public"
+ optional="true" type_notes="2x2 raw count block" container="array">
+ <array>
+ <size>4</size>
+ </array>
+ <description>
+ A per-frame dynamic black level offset for each of the color filter
+ arrangement (CFA) mosaic channels.
+ </description>
+ <range>&gt;= 0 for each.</range>
+ <details>
+ Camera sensor black levels may vary dramatically for different
+ capture settings (e.g. android.sensor.sensitivity). The fixed black
+ level reported by android.sensor.blackLevelPattern may be too
+ inaccurate to represent the actual value on a per-frame basis. The
+ camera device internal pipeline relies on reliable black level values
+ to process the raw images appropriately. To get the best image
+ quality, the camera device may choose to estimate the per frame black
+ level values either based on optically shielded black regions
+ (android.sensor.opticalBlackRegions) or its internal model.
+
+ This key reports the camera device estimated per-frame zero light
+ value for each of the CFA mosaic channels in the camera sensor. The
+ android.sensor.blackLevelPattern may only represent a coarse
+ approximation of the actual black level values. This value is the
+ black level used in camera device internal image processing pipeline
+ and generally more accurate than the fixed black level values.
+ However, since they are estimated values by the camera device, they
+ may not be as accurate as the black level values calculated from the
+ optical black pixels reported by android.sensor.opticalBlackRegions.
+
+ The values are given in the same order as channels listed for the CFA
+ layout key (see android.sensor.info.colorFilterArrangement), i.e. the
+ nth value given corresponds to the black level offset for the nth
+ color channel listed in the CFA.
+
+ This key will be available if android.sensor.opticalBlackRegions is
+ available or the camera device advertises this key via
+ {@link android.hardware.camera2.CameraCharacteristics#getAvailableCaptureResultKeys}.
+ </details>
+ <hal_details>
+ The values are given in row-column scan order, with the first value
+ corresponding to the element of the CFA in row=0, column=0.
+ </hal_details>
+ <tag id="RAW" />
+ </entry>
+ <entry name="dynamicWhiteLevel" type="int32" visibility="public"
+ optional="true" >
+ <description>
+ Maximum raw value output by sensor for this frame.
+ </description>
+ <range> &gt;= 0</range>
+ <details>
+ Since the android.sensor.blackLevelPattern may change for different
+ capture settings (e.g., android.sensor.sensitivity), the white
+ level will change accordingly. This key is similar to
+ android.sensor.info.whiteLevel, but specifies the camera device
+ estimated white level for each frame.
+
+ This key will be available if android.sensor.opticalBlackRegions is
+ available or the camera device advertises this key via
+ {@link android.hardware.camera2.CameraCharacteristics#getAvailableCaptureRequestKeys}.
+ </details>
+ <hal_details>
+ The full bit depth of the sensor must be available in the raw data,
+ so the value for linear sensors should not be significantly lower
+ than maximum raw value supported, i.e. 2^(sensor bits per pixel).
+ </hal_details>
+ <tag id="RAW" />
+ </entry>
+ </dynamic>
+ <static>
+ <entry name="opaqueRawSize" type="int32" visibility="system" container="array">
+ <array>
+ <size>n</size>
+ <size>3</size>
+ </array>
+ <description>Size in bytes for all the listed opaque RAW buffer sizes</description>
+ <range>Must be large enough to fit the opaque RAW of corresponding size produced by
+ the camera</range>
+ <details>
+ This configurations are listed as `(width, height, size_in_bytes)` tuples.
+ This is used for sizing the gralloc buffers for opaque RAW buffers.
+ All RAW_OPAQUE output stream configuration listed in
+ android.scaler.availableStreamConfigurations will have a corresponding tuple in
+ this key.
+ </details>
+ <hal_details>
+ This key is added in HAL3.4.
+ For HAL3.4 or above: devices advertising RAW_OPAQUE format output must list this key.
+ For HAL3.3 or earlier devices: if RAW_OPAQUE ouput is advertised, camera framework
+ will derive this key by assuming each pixel takes two bytes and no padding bytes
+ between rows.
+ </hal_details>
+ </entry>
+ </static>
</section>
<section name="shading">
<controls>
<dynamic>
<clone entry="android.statistics.faceDetectMode"
kind="controls"></clone>
- <entry name="faceIds" type="int32" visibility="hidden" container="array"
- hwlevel="legacy">
+ <entry name="faceIds" type="int32" visibility="ndk_public"
+ container="array" hwlevel="legacy">
<array>
<size>n</size>
</array>
Only available if android.statistics.faceDetectMode == FULL</details>
<tag id="BC" />
</entry>
- <entry name="faceLandmarks" type="int32" visibility="hidden"
- type_notes="(leftEyeX, leftEyeY, rightEyeX, rightEyeY, mouthX, mouthY)"
- container="array" hwlevel="legacy">
+ <entry name="faceLandmarks" type="int32" visibility="ndk_public"
+ type_notes="(leftEyeX, leftEyeY, rightEyeX, rightEyeY, mouthX, mouthY)"
+ container="array" hwlevel="legacy">
<array>
<size>n</size>
<size>6</size>
Only available if android.statistics.faceDetectMode == FULL</details>
<tag id="BC" />
</entry>
- <entry name="faceRectangles" type="int32" visibility="hidden"
- type_notes="(xmin, ymin, xmax, ymax). (0,0) is top-left of active pixel area"
- container="array" typedef="rectangle" hwlevel="legacy">
+ <entry name="faceRectangles" type="int32" visibility="ndk_public"
+ type_notes="(xmin, ymin, xmax, ymax). (0,0) is top-left of active pixel area"
+ container="array" typedef="rectangle" hwlevel="legacy">
<array>
<size>n</size>
<size>4</size>
Only available if android.statistics.faceDetectMode != OFF</details>
<tag id="BC" />
</entry>
- <entry name="faceScores" type="byte" visibility="hidden" container="array"
- hwlevel="legacy">
+ <entry name="faceScores" type="byte" visibility="ndk_public"
+ container="array" hwlevel="legacy">
<array>
<size>n</size>
</array>
all times is illegal).</hal_details>
<tag id="BC" />
</entry>
- <entry name="faces" type="int32" visibility="public" synthetic="true"
+ <entry name="faces" type="int32" visibility="java_public" synthetic="true"
container="array" typedef="face" hwlevel="legacy">
<array>
<size>n</size>
![Image of a uniform white wall (inverse shading map)](android.statistics.lensShadingMap/inv_shading.png)
</details>
</entry>
- <entry name="lensShadingMap" type="float" visibility="hidden"
+ <entry name="lensShadingMap" type="float" visibility="ndk_public"
type_notes="2D array of float gain factors per channel to correct lens shading"
container="array" hwlevel="full">
<array>
<size>m</size>
</array>
<description>The shading map is a low-resolution floating-point map
- that lists the coefficients used to correct for vignetting, for each
- Bayer color channel of RAW image data.</description>
+ that lists the coefficients used to correct for vignetting and color shading,
+ for each Bayer color channel of RAW image data.</description>
<range>Each gain factor is &gt;= 1</range>
- <details>The least shaded section of the image should have a gain factor
- of 1; all other sections should have gains above 1.
+ <details>
+ The lens shading correction is defined as a full shading correction that
+ corrects both color shading for the output non-RAW images. After the
+ shading map is applied, the output non-RAW images will be flat-field images
+ for flat scenes under uniform illumination.
+
+ When there is no lens shading correction applied to RAW output images
+ (android.sensor.info.lensShadingApplied `==` false), this map is a full lens
+ shading correction map; when there is some lens shading correction applied
+ to the RAW output image (android.sensor.info.lensShadingApplied `==` true),
+ this map reports the remaining lens shading correction map that needs to be
+ applied to get fully shading corrected images.
+
+ For a full shading correction map, the least shaded section of the image
+ should have a gain factor of 1; all other sections should have gains above 1.
When android.colorCorrection.mode = TRANSFORM_MATRIX, the map
must take into account the colorCorrection settings.
</section>
<section name="tonemap">
<controls>
- <entry name="curveBlue" type="float" visibility="hidden"
+ <entry name="curveBlue" type="float" visibility="ndk_public"
type_notes="1D array of float pairs (P_IN, P_OUT). The maximum number of pairs is specified by android.tonemap.maxCurvePoints."
container="array" hwlevel="full">
<array>
CONTRAST_CURVE.</description>
<details>See android.tonemap.curveRed for more details.</details>
</entry>
- <entry name="curveGreen" type="float" visibility="hidden"
+ <entry name="curveGreen" type="float" visibility="ndk_public"
type_notes="1D array of float pairs (P_IN, P_OUT). The maximum number of pairs is specified by android.tonemap.maxCurvePoints."
container="array" hwlevel="full">
<array>
CONTRAST_CURVE.</description>
<details>See android.tonemap.curveRed for more details.</details>
</entry>
- <entry name="curveRed" type="float" visibility="hidden"
+ <entry name="curveRed" type="float" visibility="ndk_public"
type_notes="1D array of float pairs (P_IN, P_OUT). The maximum number of pairs is specified by android.tonemap.maxCurvePoints."
container="array" hwlevel="full">
<array>
control points used as are available.
</hal_details>
</entry>
- <entry name="curve" type="float" visibility="public" synthetic="true"
+ <entry name="curve" type="float" visibility="java_public" synthetic="true"
typedef="tonemapCurve"
hwlevel="full">
<description>Tonemapping / contrast / gamma curve to use when android.tonemap.mode
<value>
LIMITED
<notes>
- This camera device has only limited capabilities.
+ This camera device does not have enough capabilities to qualify as a `FULL` device or
+ better.
+
+ Only the stream configurations listed in the `LEGACY` and `LIMITED` tables in the
+ {@link android.hardware.camera2.CameraDevice#createCaptureSession
+ createCaptureSession} documentation are guaranteed to be supported.
+
+ All `LIMITED` devices support the `BACKWARDS_COMPATIBLE` capability, indicating basic
+ support for color image capture. The only exception is that the device may
+ alternatively support only the `DEPTH_OUTPUT` capability, if it can only output depth
+ measurements and not color images.
+
+ `LIMITED` devices and above require the use of android.control.aePrecaptureTrigger
+ to lock exposure metering (and calculate flash power, for cameras with flash) before
+ capturing a high-quality still image.
+
+ A `LIMITED` device that only lists the `BACKWARDS_COMPATIBLE` capability is only
+ required to support full-automatic operation and post-processing (`OFF` is not
+ supported for android.control.aeMode, android.control.afMode, or
+ android.control.awbMode)
+
+ Additional capabilities may optionally be supported by a `LIMITED`-level device, and
+ can be checked for in android.request.availableCapabilities.
</notes>
</value>
<value>
FULL
<notes>
This camera device is capable of supporting advanced imaging applications.
+
+ The stream configurations listed in the `FULL`, `LEGACY` and `LIMITED` tables in the
+ {@link android.hardware.camera2.CameraDevice#createCaptureSession
+ createCaptureSession} documentation are guaranteed to be supported.
+
+ A `FULL` device will support below capabilities:
+
+ * `BURST_CAPTURE` capability (android.request.availableCapabilities contains
+ `BURST_CAPTURE`)
+ * Per frame control (android.sync.maxLatency `==` PER_FRAME_CONTROL)
+ * Manual sensor control (android.request.availableCapabilities contains `MANUAL_SENSOR`)
+ * Manual post-processing control (android.request.availableCapabilities contains
+ `MANUAL_POST_PROCESSING`)
+ * The required exposure time range defined in android.sensor.info.exposureTimeRange
+ * The required maxFrameDuration defined in android.sensor.info.maxFrameDuration
+
+ Note:
+ Pre-API level 23, FULL devices also supported arbitrary cropping region
+ (android.scaler.croppingType `== FREEFORM`); this requirement was relaxed in API level
+ 23, and `FULL` devices may only support `CENTERED` cropping.
</notes>
</value>
<value>
LEGACY
<notes>
This camera device is running in backward compatibility mode.
+
+ Only the stream configurations listed in the `LEGACY` table in the {@link
+ android.hardware.camera2.CameraDevice#createCaptureSession createCaptureSession}
+ documentation are supported.
+
+ A `LEGACY` device does not support per-frame control, manual sensor control, manual
+ post-processing, arbitrary cropping regions, and has relaxed performance constraints.
+ No additional capabilities beyond `BACKWARD_COMPATIBLE` will ever be listed by a
+ `LEGACY` device in android.request.availableCapabilities.
+
+ In addition, the android.control.aePrecaptureTrigger is not functional on `LEGACY`
+ devices. Instead, every request that includes a JPEG-format output target is treated
+ as triggering a still capture, internally executing a precapture trigger. This may
+ fire the flash for flash power metering during precapture, and then fire the flash
+ for the final capture, if a flash is available on the device and the AE mode is set to
+ enable the flash.
+ </notes>
+ </value>
+ <value>
+ 3
+ <notes>
+ This camera device is capable of YUV reprocessing and RAW data capture, in addition to
+ FULL-level capabilities.
+
+ The stream configurations listed in the `LEVEL_3`, `RAW`, `FULL`, `LEGACY` and
+ `LIMITED` tables in the {@link
+ android.hardware.camera2.CameraDevice#createCaptureSession createCaptureSession}
+ documentation are guaranteed to be supported.
+
+ The following additional capabilities are guaranteed to be supported:
+
+ * `YUV_REPROCESSING` capability (android.request.availableCapabilities contains
+ `YUV_REPROCESSING`)
+ * `RAW` capability (android.request.availableCapabilities contains
+ `RAW`)
</notes>
</value>
</enum>
Generally classifies the overall set of the camera device functionality.
</description>
<details>
- Camera devices will come in three flavors: LEGACY, LIMITED and FULL.
+ The supported hardware level is a high-level description of the camera device's
+ capabilities, summarizing several capabilities into one field. Each level adds additional
+ features to the previous one, and is always a strict superset of the previous level.
+ The ordering is `LEGACY < LIMITED < FULL < LEVEL_3`.
+
+ Starting from `LEVEL_3`, the level enumerations are guaranteed to be in increasing
+ numerical value as well. To check if a given device is at least at a given hardware level,
+ the following code snippet can be used:
+
+ // Returns true if the device supports the required hardware level, or better.
+ boolean isHardwareLevelSupported(CameraCharacteristics c, int requiredLevel) {
+ int deviceLevel = c.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
+ if (deviceLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
+ return requiredLevel == deviceLevel;
+ }
+ // deviceLevel is not LEGACY, can use numerical sort
+ return requiredLevel <= deviceLevel;
+ }
- A FULL device will support below capabilities:
+ At a high level, the levels are:
- * BURST_CAPTURE capability (android.request.availableCapabilities contains BURST_CAPTURE)
- * Per frame control (android.sync.maxLatency `==` PER_FRAME_CONTROL)
- * Manual sensor control (android.request.availableCapabilities contains MANUAL_SENSOR)
- * Manual post-processing control (android.request.availableCapabilities contains
- MANUAL_POST_PROCESSING)
- * At least 3 processed (but not stalling) format output streams
- (android.request.maxNumOutputProc `>=` 3)
- * The required stream configurations defined in android.scaler.availableStreamConfigurations
- * The required exposure time range defined in android.sensor.info.exposureTimeRange
- * The required maxFrameDuration defined in android.sensor.info.maxFrameDuration
+ * `LEGACY` devices operate in a backwards-compatibility mode for older
+ Android devices, and have very limited capabilities.
+ * `LIMITED` devices represent the
+ baseline feature set, and may also include additional capabilities that are
+ subsets of `FULL`.
+ * `FULL` devices additionally support per-frame manual control of sensor, flash, lens and
+ post-processing settings, and image capture at a high rate.
+ * `LEVEL_3` devices additionally support YUV reprocessing and RAW image capture, along
+ with additional output stream configurations.
- A LIMITED device may have some or none of the above characteristics.
- To find out more refer to android.request.availableCapabilities.
+ See the individual level enums for full descriptions of the supported capabilities. The
+ android.request.availableCapabilities entry describes the device's capabilities at a
+ finer-grain level, if needed. In addition, many controls have their available settings or
+ ranges defined in individual {@link android.hardware.camera2.CameraCharacteristics} entries.
Some features are not part of any particular hardware level or capability and must be
queried separately. These include:
(android.lens.info.availableOpticalStabilization,
android.control.availableVideoStabilizationModes)
- A LEGACY device does not support per-frame control, manual sensor control, manual
- post-processing, arbitrary cropping regions, and has relaxed performance constraints.
-
- Each higher level supports everything the lower level supports
- in this order: FULL `>` LIMITED `>` LEGACY.
-
- Note:
- Pre-API level 23, FULL devices also supported arbitrary cropping region
- (android.scaler.croppingType `==` FREEFORM); this requirement was relaxed in API level 23,
- and FULL devices may only support CENTERED cropping.
</details>
<hal_details>
- The camera 3 HAL device can implement one of two possible
- operational modes; limited and full. Full support is
- expected from new higher-end devices. Limited mode has
- hardware requirements roughly in line with those for a
- camera HAL device v1 implementation, and is expected from
- older or inexpensive devices. Full is a strict superset of
- limited, and they share the same essential operational flow.
+ The camera 3 HAL device can implement one of three possible operational modes; LIMITED,
+ FULL, and LEVEL_3.
+
+ FULL support or better is expected from new higher-end devices. Limited
+ mode has hardware requirements roughly in line with those for a camera HAL device v1
+ implementation, and is expected from older or inexpensive devices. Each level is a strict
+ superset of the previous level, and they share the same essential operational flow.
For full details refer to "S3. Operational Modes" in camera3.h
- Camera HAL3+ must not implement LEGACY mode. It is there
- for backwards compatibility in the `android.hardware.camera2`
- user-facing API only.
+ Camera HAL3+ must not implement LEGACY mode. It is there for backwards compatibility in
+ the `android.hardware.camera2` user-facing API only on HALv1 devices, and is implemented
+ by the camera framework code.
</hal_details>
</entry>
</static>
</section>
<section name="sync">
<dynamic>
- <entry name="frameNumber" type="int64" visibility="hidden" enum="true"
- hwlevel="legacy">
+ <entry name="frameNumber" type="int64" visibility="ndk_public"
+ enum="true" hwlevel="legacy">
<enum>
<value id="-1">CONVERGING
<notes>
Use `frame_count` from camera3_request_t instead of
android.request.frameCount or
- `@link{android.hardware.camera2.CaptureResult#getFrameNumber}`.
+ `{@link android.hardware.camera2.CaptureResult#getFrameNumber}`.
LIMITED devices are strongly encouraged to use a non-negative
value. If UNKNOWN is used here then app developers do not have a way
</section>
<section name="reprocess">
<controls>
- <entry name="effectiveExposureFactor" type="float" visibility="public" hwlevel="limited">
+ <entry name="effectiveExposureFactor" type="float" visibility="java_public" hwlevel="limited">
<description>
The amount of exposure time increase factor applied to the original output
frame by the application processing before sending for reprocessing.
</clone>
</dynamic>
<static>
- <entry name="maxCaptureStall" type="int32" visibility="public" hwlevel="limited">
+ <entry name="maxCaptureStall" type="int32" visibility="java_public" hwlevel="limited">
<description>
The maximal camera capture pipeline stall (in unit of frame count) introduced by a
reprocess capture request.
</details>
<tag id="DEPTH" />
</entry>
- <entry name="availableDepthStreamConfigurations" type="int32" visibility="hidden"
- enum="true" container="array"
- typedef="streamConfiguration" hwlevel="limited">
+ <entry name="availableDepthStreamConfigurations" type="int32" visibility="ndk_public"
+ enum="true" container="array" typedef="streamConfiguration" hwlevel="limited">
<array>
<size>n</size>
<size>4</size>
</details>
<tag id="DEPTH" />
</entry>
- <entry name="availableDepthMinFrameDurations" type="int64" visibility="hidden"
- container="array"
- typedef="streamConfigurationDuration" hwlevel="limited">
+ <entry name="availableDepthMinFrameDurations" type="int64" visibility="ndk_public"
+ container="array" typedef="streamConfigurationDuration" hwlevel="limited">
<array>
<size>4</size>
<size>n</size>
</details>
<tag id="DEPTH" />
</entry>
- <entry name="availableDepthStallDurations" type="int64" visibility="hidden"
+ <entry name="availableDepthStallDurations" type="int64" visibility="ndk_public"
container="array" typedef="streamConfigurationDuration" hwlevel="limited">
<array>
<size>4</size>
<attribute name="visibility">
<simpleType>
<restriction base="string">
- <enumeration value="system" /> <!-- do not expose to java -->
- <enumeration value="hidden" /> <!-- java as @hide -->
- <enumeration value="public" /> <!-- java as public SDK -->
+ <enumeration value="system" /> <!-- do not expose to java/NDK API -->
+ <enumeration value="java_public" /> <!-- java as public SDK. Not included in NDK -->
+ <enumeration value="ndk_public" /> <!-- public in NDK. @hide in java -->
+ <enumeration value="hidden" /> <!-- java as @hide. Not included in NDK -->
+ <enumeration value="public" /> <!-- public to both java and NDK -->
</restriction>
</simpleType>
</attribute>
</restriction>
</simpleType>
</attribute>
+ <attribute name="ndk_hidden">
+ <simpleType>
+ <restriction base="string">
+ <enumeration value="true"></enumeration>
+ <enumeration value="false"></enumeration>
+ </restriction>
+ </simpleType>
+ </attribute>
<attribute name="id" type="string" />
</complexType>
% if value.hidden:
hidden="true"
% endif:
+ % if value.ndk_hidden:
+ ndk_hidden="true"
+ % endif:
% if value.id is not None:
id="${value.id}"
% endif
--- /dev/null
+## -*- coding: utf-8 -*-
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file defines an NDK API.
+ * Do not remove methods.
+ * Do not change method signatures.
+ * Do not change the value of constants.
+ * Do not change the size of any of the classes defined in here.
+ * Do not reference types that are not part of the NDK.
+ * Do not #include files that aren't part of the NDK.
+ */
+
+#ifndef _NDK_CAMERA_METADATA_TAGS_H
+#define _NDK_CAMERA_METADATA_TAGS_H
+<%!
+ def annotated_type(entry):
+ type = entry.type
+ if entry.container == 'array':
+ type += '[' + '*'.join(entry.container_sizes) + ']'
+ if entry.enum:
+ type += ' (enum)'
+
+ return type
+%>\
+\
+
+typedef enum acamera_metadata_section {
+ % for i in find_all_sections(metadata):
+ ${ndk(path_name(i)) | csym},
+ % endfor
+ ACAMERA_SECTION_COUNT,
+
+ ACAMERA_VENDOR = 0x8000
+} acamera_metadata_section_t;
+
+/**
+ * Hierarchy positions in enum space.
+ */
+typedef enum acamera_metadata_section_start {
+ % for i in find_all_sections(metadata):
+ ${ndk(path_name(i)) + '.start' | csym,ljust(30)} = ${ndk(path_name(i)) | csym,pad(64)} << 16,
+ % endfor
+ ACAMERA_VENDOR_START = ACAMERA_VENDOR << 16
+} acamera_metadata_section_start_t;
+
+/**
+ * Main enum for camera metadata tags.
+ */
+typedef enum acamera_metadata_tag {
+ % for sec in find_all_sections(metadata):
+<%
+ entries = remove_synthetic(find_unique_entries(sec))
+ skip_sec = all(e.applied_ndk_visible == "false" for e in entries)
+ if skip_sec:
+ continue
+%>\
+ % for idx,entry in enumerate(remove_synthetic(find_unique_entries(sec))):
+ % if entry.applied_ndk_visible == "true":
+ % if entry.deprecated:
+ ${ndk(entry.name) + " = " | csym,ljust(60)}// Deprecated! DO NOT USE
+ % else:
+ % if entry.description or entry.details:
+ /**
+${entry.description | ndkdoc(metadata)}\
+ *
+ * <p>This tag may appear in:</p>
+ * <ul>
+ % if metadata.is_entry_this_kind(entry, 'static'):
+ * <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+ % endif
+ % if metadata.is_entry_this_kind(entry, 'dynamic'):
+ * <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
+ % endif
+ % if metadata.is_entry_this_kind(entry, 'controls'):
+ * <li>ACaptureRequest</li>
+ % endif
+ * </ul>
+ *
+${entry.details | ndkdoc(metadata)}\
+ */
+ % endif
+ ${ndk(entry.name) + " = " | csym,ljust(60)}// ${annotated_type(entry)}
+ % endif
+ % if idx == 0:
+ ${ndk(path_name(find_parent_section(entry))) | csym}_START,
+ % else:
+ ${ndk(path_name(find_parent_section(entry))) | csym}_START + ${idx},
+ % endif
+ % endif
+ % endfor
+ ${ndk(path_name(sec)) | csym}_END,
+
+ %endfor
+} acamera_metadata_tag_t;
+
+/**
+ * Enumeration definitions for the various entries that need them
+ */
+
+% for sec in find_all_sections(metadata):
+ % for entry in filter_ndk_visible(remove_synthetic(find_unique_entries(sec))):
+ % if entry.enum:
+// ${ndk(entry.name) | csym}
+typedef enum acamera_metadata_enum_${csym(ndk(entry.name)).lower()} {
+<%
+ i = 0
+%>\
+ % for val in entry.enum.values:
+ % if val.ndk_hidden:
+<%
+ print " WARNING: {}_{} is marked as hidden".format(csym(ndk(entry.name)), val.name) + \
+ " enum in NDK. Please double check this value is properly hidden" + \
+ " in NDK API implementation"
+%>\
+ % endif
+ % if val.hidden or val.ndk_hidden:
+ % if val.id:
+<%
+ i = int(val.id, 0) + 1
+ continue
+%>\
+ % else:
+<%
+ i += 1
+ continue
+%>\
+ % endif
+ % endif
+ % if (val.notes or val.deprecated):
+ /**
+ % if val.notes:
+${val.notes | ndkdoc(metadata)}\
+ % endif
+ % if val.deprecated:
+ *
+ * <b>Deprecated</b>: please refer to this API documentation to find the alternatives
+ % endif
+ */
+ % endif
+ % if val.id:
+ ${'%s_%s'%(csym(ndk(entry.name)), val.name) | pad(70)} = ${val.id},
+<%
+ i = int(val.id, 0)
+%>\
+ % else:
+ ${'%s_%s'%(csym(ndk(entry.name)), val.name) | pad(70)} = ${i},
+ % endif
+<%
+ i += 1
+%>
+ % endfor
+} acamera_metadata_enum_${csym(entry.name).lower()}_t;
+
+ % endif
+ % endfor
+
+% endfor
+
+#endif //_NDK_CAMERA_METADATA_TAGS_H
ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
// byte[] | public
ANDROID_CONTROL_AWB_AVAILABLE_MODES, // byte[] | public
- ANDROID_CONTROL_MAX_REGIONS, // int32[] | hidden
+ ANDROID_CONTROL_MAX_REGIONS, // int32[] | ndk_public
ANDROID_CONTROL_SCENE_MODE_OVERRIDES, // byte[] | system
ANDROID_CONTROL_AE_PRECAPTURE_ID, // int32 | system
ANDROID_CONTROL_AE_STATE, // enum | public
ANDROID_CONTROL_AE_LOCK_AVAILABLE, // enum | public
ANDROID_CONTROL_AWB_LOCK_AVAILABLE, // enum | public
ANDROID_CONTROL_AVAILABLE_MODES, // byte[] | public
+ ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE, // int32[] | public
+ ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST, // int32 | public
ANDROID_CONTROL_END,
ANDROID_DEMOSAIC_MODE = // enum | system
ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES, // byte[] | public
ANDROID_HOT_PIXEL_END,
- ANDROID_JPEG_GPS_COORDINATES = // double[] | hidden
+ ANDROID_JPEG_GPS_COORDINATES = // double[] | ndk_public
ANDROID_JPEG_START,
- ANDROID_JPEG_GPS_PROCESSING_METHOD, // byte | hidden
- ANDROID_JPEG_GPS_TIMESTAMP, // int64 | hidden
+ ANDROID_JPEG_GPS_PROCESSING_METHOD, // byte | ndk_public
+ ANDROID_JPEG_GPS_TIMESTAMP, // int64 | ndk_public
ANDROID_JPEG_ORIENTATION, // int32 | public
ANDROID_JPEG_QUALITY, // byte | public
ANDROID_JPEG_THUMBNAIL_QUALITY, // byte | public
ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,// byte[] | public
ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE, // float | public
ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE, // float | public
- ANDROID_LENS_INFO_SHADING_MAP_SIZE, // int32[] | hidden
+ ANDROID_LENS_INFO_SHADING_MAP_SIZE, // int32[] | ndk_public
ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION, // enum | public
ANDROID_LENS_INFO_END,
ANDROID_REQUEST_METADATA_MODE, // enum | system
ANDROID_REQUEST_OUTPUT_STREAMS, // int32[] | system
ANDROID_REQUEST_TYPE, // enum | system
- ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, // int32[] | hidden
+ ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, // int32[] | ndk_public
ANDROID_REQUEST_MAX_NUM_REPROCESS_STREAMS, // int32[] | system
ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, // int32 | public
ANDROID_REQUEST_PIPELINE_DEPTH, // byte | public
ANDROID_REQUEST_PIPELINE_MAX_DEPTH, // byte | public
ANDROID_REQUEST_PARTIAL_RESULT_COUNT, // int32 | public
ANDROID_REQUEST_AVAILABLE_CAPABILITIES, // enum[] | public
- ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, // int32[] | hidden
- ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, // int32[] | hidden
- ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, // int32[] | hidden
+ ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, // int32[] | ndk_public
+ ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, // int32[] | ndk_public
+ ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, // int32[] | ndk_public
ANDROID_REQUEST_END,
ANDROID_SCALER_CROP_REGION = // int32[] | public
ANDROID_SCALER_AVAILABLE_RAW_MIN_DURATIONS, // int64[] | system
ANDROID_SCALER_AVAILABLE_RAW_SIZES, // int32[] | system
ANDROID_SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP,// int32 | hidden
- ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, // enum[] | hidden
- ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS, // int64[] | hidden
- ANDROID_SCALER_AVAILABLE_STALL_DURATIONS, // int64[] | hidden
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, // enum[] | ndk_public
+ ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS, // int64[] | ndk_public
+ ANDROID_SCALER_AVAILABLE_STALL_DURATIONS, // int64[] | ndk_public
ANDROID_SCALER_CROPPING_TYPE, // enum | public
ANDROID_SCALER_END,
ANDROID_SENSOR_TEST_PATTERN_MODE, // enum | public
ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, // int32[] | public
ANDROID_SENSOR_ROLLING_SHUTTER_SKEW, // int64 | public
+ ANDROID_SENSOR_OPTICAL_BLACK_REGIONS, // int32[] | public
+ ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL, // float[] | public
+ ANDROID_SENSOR_DYNAMIC_WHITE_LEVEL, // int32 | public
+ ANDROID_SENSOR_OPAQUE_RAW_SIZE, // int32[] | system
ANDROID_SENSOR_END,
ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE = // int32[] | public
ANDROID_STATISTICS_HISTOGRAM_MODE, // enum | system
ANDROID_STATISTICS_SHARPNESS_MAP_MODE, // enum | system
ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE, // enum | public
- ANDROID_STATISTICS_FACE_IDS, // int32[] | hidden
- ANDROID_STATISTICS_FACE_LANDMARKS, // int32[] | hidden
- ANDROID_STATISTICS_FACE_RECTANGLES, // int32[] | hidden
- ANDROID_STATISTICS_FACE_SCORES, // byte[] | hidden
+ ANDROID_STATISTICS_FACE_IDS, // int32[] | ndk_public
+ ANDROID_STATISTICS_FACE_LANDMARKS, // int32[] | ndk_public
+ ANDROID_STATISTICS_FACE_RECTANGLES, // int32[] | ndk_public
+ ANDROID_STATISTICS_FACE_SCORES, // byte[] | ndk_public
ANDROID_STATISTICS_HISTOGRAM, // int32[] | system
ANDROID_STATISTICS_SHARPNESS_MAP, // int32[] | system
ANDROID_STATISTICS_LENS_SHADING_CORRECTION_MAP, // byte | public
- ANDROID_STATISTICS_LENS_SHADING_MAP, // float[] | hidden
+ ANDROID_STATISTICS_LENS_SHADING_MAP, // float[] | ndk_public
ANDROID_STATISTICS_PREDICTED_COLOR_GAINS, // float[] | hidden
ANDROID_STATISTICS_PREDICTED_COLOR_TRANSFORM, // rational[] | hidden
ANDROID_STATISTICS_SCENE_FLICKER, // enum | public
// byte[] | public
ANDROID_STATISTICS_INFO_END,
- ANDROID_TONEMAP_CURVE_BLUE = // float[] | hidden
+ ANDROID_TONEMAP_CURVE_BLUE = // float[] | ndk_public
ANDROID_TONEMAP_START,
- ANDROID_TONEMAP_CURVE_GREEN, // float[] | hidden
- ANDROID_TONEMAP_CURVE_RED, // float[] | hidden
+ ANDROID_TONEMAP_CURVE_GREEN, // float[] | ndk_public
+ ANDROID_TONEMAP_CURVE_RED, // float[] | ndk_public
ANDROID_TONEMAP_MODE, // enum | public
ANDROID_TONEMAP_MAX_CURVE_POINTS, // int32 | public
ANDROID_TONEMAP_AVAILABLE_TONE_MAP_MODES, // byte[] | public
ANDROID_BLACK_LEVEL_START,
ANDROID_BLACK_LEVEL_END,
- ANDROID_SYNC_FRAME_NUMBER = // enum | hidden
+ ANDROID_SYNC_FRAME_NUMBER = // enum | ndk_public
ANDROID_SYNC_START,
ANDROID_SYNC_MAX_LATENCY, // enum | public
ANDROID_SYNC_END,
- ANDROID_REPROCESS_EFFECTIVE_EXPOSURE_FACTOR = // float | public
+ ANDROID_REPROCESS_EFFECTIVE_EXPOSURE_FACTOR = // float | java_public
ANDROID_REPROCESS_START,
- ANDROID_REPROCESS_MAX_CAPTURE_STALL, // int32 | public
+ ANDROID_REPROCESS_MAX_CAPTURE_STALL, // int32 | java_public
ANDROID_REPROCESS_END,
ANDROID_DEPTH_MAX_DEPTH_SAMPLES = // int32 | system
ANDROID_DEPTH_START,
ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
- // enum[] | hidden
- ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS,// int64[] | hidden
- ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS, // int64[] | hidden
+ // enum[] | ndk_public
+ ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS,// int64[] | ndk_public
+ ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS, // int64[] | ndk_public
ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE, // enum | public
ANDROID_DEPTH_END,
ANDROID_CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO,
ANDROID_CONTROL_SCENE_MODE_HDR,
ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY_LOW_LIGHT,
+ ANDROID_CONTROL_SCENE_MODE_DEVICE_CUSTOM_START = 100,
+ ANDROID_CONTROL_SCENE_MODE_DEVICE_CUSTOM_END = 127,
} camera_metadata_enum_android_control_scene_mode_t;
// ANDROID_CONTROL_VIDEO_STABILIZATION_MODE
ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED,
ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY,
+ ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_3,
} camera_metadata_enum_android_info_supported_hardware_level_t;
LOCAL_CFLAGS += \
-Wall \
+ -Wextra \
+ -Werror \
-fvisibility=hidden \
-std=c99
if (dst == NULL) return ERROR;
if (dst->entry_count == dst->entry_capacity) return ERROR;
- if (data == NULL) return ERROR;
+ if (data_count && data == NULL) return ERROR;
size_t data_bytes =
calculate_camera_metadata_entry_data_size(type, data_count);
int set_camera_metadata_vendor_tag_ops(const vendor_tag_query_ops_t* ops) {
// **DEPRECATED**
+ (void) ops;
ALOGE("%s: This function has been deprecated", __FUNCTION__);
return ERROR;
}
{ "awbLockAvailable", TYPE_BYTE },
[ ANDROID_CONTROL_AVAILABLE_MODES - ANDROID_CONTROL_START ] =
{ "availableModes", TYPE_BYTE },
+ [ ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE - ANDROID_CONTROL_START ] =
+ { "postRawSensitivityBoostRange", TYPE_INT32 },
+ [ ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST - ANDROID_CONTROL_START ] =
+ { "postRawSensitivityBoost", TYPE_INT32 },
};
static tag_info_t android_demosaic[ANDROID_DEMOSAIC_END -
{ "availableTestPatternModes", TYPE_INT32 },
[ ANDROID_SENSOR_ROLLING_SHUTTER_SKEW - ANDROID_SENSOR_START ] =
{ "rollingShutterSkew", TYPE_INT64 },
+ [ ANDROID_SENSOR_OPTICAL_BLACK_REGIONS - ANDROID_SENSOR_START ] =
+ { "opticalBlackRegions", TYPE_INT32 },
+ [ ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL - ANDROID_SENSOR_START ] =
+ { "dynamicBlackLevel", TYPE_FLOAT },
+ [ ANDROID_SENSOR_DYNAMIC_WHITE_LEVEL - ANDROID_SENSOR_START ] =
+ { "dynamicWhiteLevel", TYPE_INT32 },
+ [ ANDROID_SENSOR_OPAQUE_RAW_SIZE - ANDROID_SENSOR_START ] =
+ { "opaqueRawSize", TYPE_INT32 },
};
static tag_info_t android_sensor_info[ANDROID_SENSOR_INFO_END -
msg = "FACE_PRIORITY_LOW_LIGHT";
ret = 0;
break;
+ case ANDROID_CONTROL_SCENE_MODE_DEVICE_CUSTOM_START:
+ msg = "DEVICE_CUSTOM_START";
+ ret = 0;
+ break;
+ case ANDROID_CONTROL_SCENE_MODE_DEVICE_CUSTOM_END:
+ msg = "DEVICE_CUSTOM_END";
+ ret = 0;
+ break;
default:
msg = "error: enum value out of range";
}
case ANDROID_CONTROL_AVAILABLE_MODES: {
break;
}
+ case ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE: {
+ break;
+ }
+ case ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST: {
+ break;
+ }
case ANDROID_DEMOSAIC_MODE: {
switch (value) {
case ANDROID_SENSOR_ROLLING_SHUTTER_SKEW: {
break;
}
+ case ANDROID_SENSOR_OPTICAL_BLACK_REGIONS: {
+ break;
+ }
+ case ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL: {
+ break;
+ }
+ case ANDROID_SENSOR_DYNAMIC_WHITE_LEVEL: {
+ break;
+ }
+ case ANDROID_SENSOR_OPAQUE_RAW_SIZE: {
+ break;
+ }
case ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE: {
break;
msg = "LEGACY";
ret = 0;
break;
+ case ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_3:
+ msg = "3";
+ ret = 0;
+ break;
default:
msg = "error: enum value out of range";
}
LOCAL_SRC_FILES := \
camera_metadata_tests.cpp
+LOCAL_CFLAGS += -Wall -Wextra -Werror
+
LOCAL_MODULE := camera_metadata_tests
LOCAL_MODULE_TAGS := tests
LOCAL_MODULE_STEM_32 := camera_metadata_tests
result = get_camera_metadata_entry(m,
index, &entry);
EXPECT_EQ(OK, result);
- EXPECT_EQ(index, (int)entry.index);
+ EXPECT_EQ(index, entry.index);
EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, entry.tag);
EXPECT_EQ(TYPE_INT64, entry.type);
EXPECT_EQ((size_t)1, entry.count);
const size_t entry_capacity = 50;
const size_t data_capacity = 450;
- int result;
-
m = allocate_camera_metadata(entry_capacity, data_capacity);
add_test_metadata(m, entry_capacity);
const size_t extra_space = 10;
- int result;
-
m = allocate_camera_metadata(entry_capacity, data_capacity);
add_test_metadata(m, entry_capacity);
const size_t entry_capacity = 5;
const size_t data_capacity = 50;
- int result;
-
m = allocate_camera_metadata(entry_capacity, data_capacity);
add_test_metadata(m, entry_capacity);
EXPECT_EQ(OK, validate_camera_metadata_structure(m2, &m_size));
- delete dst;
+ delete[] dst;
FINISH_USING_CAMERA_METADATA(m);
}
get_fakevendor_tags,
get_fakevendor_section_name,
get_fakevendor_tag_name,
- get_fakevendor_tag_type
+ get_fakevendor_tag_type,
+ {NULL}
};
const char *get_fakevendor_section_name(const vendor_tag_ops_t *v,
RADIO_METADATA_KEY_GENRE = 8, /* Musical genre - text */
RADIO_METADATA_KEY_ICON = 9, /* Station icon - raw */
RADIO_METADATA_KEY_ART = 10, /* Album art - raw */
+ RADIO_METADATA_KEY_CLOCK = 11, /* Clock - radio_metadata_clock_t */
RADIO_METADATA_KEY_MIN = RADIO_METADATA_KEY_RDS_PI,
- RADIO_METADATA_KEY_MAX = RADIO_METADATA_KEY_ART,
+ RADIO_METADATA_KEY_MAX = RADIO_METADATA_KEY_CLOCK,
};
typedef int radio_metadata_key_t;
-
enum {
RADIO_METADATA_TYPE_INVALID = -1,
RADIO_METADATA_TYPE_INT = 0, /* signed 32 bit integer */
RADIO_METADATA_TYPE_TEXT = 1, /* text in UTF-8 format, NUL terminated.
RADIO_METADATA_TEXT_LEN_MAX length including NUL. */
RADIO_METADATA_TYPE_RAW = 2, /* raw binary data (icon or art) */
+ RADIO_METADATA_TYPE_CLOCK = 3, /* clock data, see radio_metadata_clock_t */
};
typedef int radio_metadata_type_t;
+typedef struct radio_metadata_clock {
+ uint64_t utc_seconds_since_epoch; /* Seconds since epoch at GMT + 0. */
+ int32_t timezone_offset_in_minutes; /* Minutes offset from the GMT. */
+} radio_metadata_clock_t;
+
/*
* Return the type of the meta data corresponding to the key specified
*
const unsigned int size);
/*
+ * Add a clock meta data to the buffer.
+ *
+ * arguments:
+ * - metadata: the address of the meta data buffer. I/O. the meta data can be modified if the
+ * buffer is re-allocated.
+ * - key: the meta data key.
+ * - value: the meta data value.
+ *
+ * returns:
+ * 0 if successfully added
+ * - EINVAL if the buffer passed is invalid or the key does not match a raw type
+ * - ENOMEM if meta data buffer cannot be re-allocated
+ */
+ANDROID_API
+int radio_metadata_add_clock(radio_metadata_t **metadata,
+ const radio_metadata_key_t key,
+ const radio_metadata_clock_t *clock);
+
+/*
* add all meta data in source buffer to destinaiton buffer.
*
* arguments:
LOCAL_MODULE := libradio_metadata
LOCAL_MODULE_TAGS := optional
-LOCAL_CFLAGS += \
- -fvisibility=hidden
+LOCAL_CFLAGS := -Werror -Wall
+LOCAL_CFLAGS += -fvisibility=hidden
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/../include
RADIO_METADATA_TYPE_TEXT,
RADIO_METADATA_TYPE_RAW,
RADIO_METADATA_TYPE_RAW,
+ RADIO_METADATA_TYPE_CLOCK,
};
/**
return add_metadata((radio_metadata_buffer_t **)metadata, key, type, value, size);
}
+int radio_metadata_add_clock(radio_metadata_t **metadata,
+ const radio_metadata_key_t key,
+ const radio_metadata_clock_t *clock) {
+ radio_metadata_type_t type = radio_metadata_type_of_key(key);
+ if (metadata == NULL || *metadata == NULL || type != RADIO_METADATA_TYPE_CLOCK ||
+ clock == NULL || clock->timezone_offset_in_minutes < (-12 * 60) ||
+ clock->timezone_offset_in_minutes > (14 * 60)) {
+ return -EINVAL;
+ }
+ return add_metadata(
+ (radio_metadata_buffer_t **)metadata, key, type, clock, sizeof(radio_metadata_clock_t));
+}
+
int radio_metadata_add_metadata(radio_metadata_t **dst_metadata,
radio_metadata_t *src_metadata)
{
void **value,
unsigned int *size)
{
- unsigned int index_offset;
- unsigned int data_offset;
radio_metadata_entry_t *entry;
radio_metadata_buffer_t *metadata_buf =
(radio_metadata_buffer_t *)metadata;