Merge "Camera: fix codegen"
diff --git a/audio_utils/include/audio_utils/primitives.h b/audio_utils/include/audio_utils/primitives.h
index e0f952e..95eaffb 100644
--- a/audio_utils/include/audio_utils/primitives.h
+++ b/audio_utils/include/audio_utils/primitives.h
@@ -578,6 +578,78 @@
uint32_t dst_mask, uint32_t src_mask);
/**
+ * Add and clamp signed 16-bit samples.
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to add
+ *
+ * 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 accumulate_i16(int16_t *dst, const int16_t *src, size_t count);
+
+/**
+ * Add and clamp unsigned 8-bit samples.
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to add
+ *
+ * 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 accumulate_u8(uint8_t *dst, const uint8_t *src, size_t count);
+
+/**
+ * Add and clamp packed 24-bit Q0.23 samples.
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to add
+ *
+ * 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 accumulate_p24(uint8_t *dst, const uint8_t *src, size_t count);
+
+/**
+ * Add and clamp 32-bit Q8.23 samples.
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to add
+ *
+ * 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 accumulate_q8_23(int32_t *dst, const int32_t *src, size_t count);
+
+/**
+ * Add and clamp signed 32-bit Q0.31 samples.
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to add
+ *
+ * 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 accumulate_i32(int32_t *dst, const int32_t *src, size_t count);
+
+/**
+ * Add float samples. Result is not clamped.
+ *
+ * \param dst Destination buffer
+ * \param src Source buffer
+ * \param count Number of samples to add
+ *
+ * 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 accumulate_float(float *dst, const float *src, size_t count);
+
+/**
* Clamp (aka hard limit or clip) a signed 32-bit sample to 16-bit range.
*/
static inline int16_t clamp16(int32_t sample)
@@ -588,6 +660,16 @@
}
/**
+ * Clamp (aka hard limit or clip) a signed 64-bit sample to 32-bit range.
+ */
+static inline int32_t clamp32(int64_t sample)
+{
+ if ((sample>>31) ^ (sample>>63))
+ sample = 0x7fffffff ^ (sample>>63);
+ 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).
diff --git a/audio_utils/primitives.c b/audio_utils/primitives.c
index f4bd645..9a4cc3b 100644
--- a/audio_utils/primitives.c
+++ b/audio_utils/primitives.c
@@ -524,3 +524,58 @@
}
return dst_idx;
}
+
+void accumulate_i16(int16_t *dst, const int16_t *src, size_t count) {
+ while (count--) {
+ *dst = clamp16((int32_t)*dst + *src++);
+ ++dst;
+ }
+}
+
+void accumulate_u8(uint8_t *dst, const uint8_t *src, size_t count) {
+ int32_t sum;
+ while (count--) {
+ // 8-bit samples are centered around 0x80.
+ sum = *dst + *src++ - 0x80;
+ // Clamp to [0, 0xff].
+ *dst++ = (sum & 0x100) ? (~sum >> 9) : sum;
+ }
+}
+
+void accumulate_p24(uint8_t *dst, const uint8_t *src, size_t count) {
+ while (count--) {
+ // Unpack.
+ int32_t dst_q8_23 = 0;
+ int32_t src_q8_23 = 0;
+ memcpy_to_q8_23_from_p24(&dst_q8_23, dst, 1);
+ memcpy_to_q8_23_from_p24(&src_q8_23, src, 1);
+
+ // Accumulate and overwrite.
+ dst_q8_23 += src_q8_23;
+ memcpy_to_p24_from_q8_23(dst, &dst_q8_23, 1);
+
+ // Move on to next sample.
+ dst += 3;
+ src += 3;
+ }
+}
+
+void accumulate_q8_23(int32_t *dst, const int32_t *src, size_t count) {
+ while (count--) {
+ *dst = clamp24_from_q8_23(*dst + *src++);
+ ++dst;
+ }
+}
+
+void accumulate_i32(int32_t *dst, const int32_t *src, size_t count) {
+ while (count--) {
+ *dst = clamp32((int64_t)*dst + *src++);
+ ++dst;
+ }
+}
+
+void accumulate_float(float *dst, const float *src, size_t count) {
+ while (count--) {
+ *dst++ += *src++;
+ }
+}
diff --git a/audio_utils/tests/primitives_tests.cpp b/audio_utils/tests/primitives_tests.cpp
index 44ba6b8..fadcdf7 100644
--- a/audio_utils/tests/primitives_tests.cpp
+++ b/audio_utils/tests/primitives_tests.cpp
@@ -35,6 +35,8 @@
static const int32_t lim16neg = -(1 << 15);
static const int32_t lim24pos = (1 << 23) - 1;
static const int32_t lim24neg = -(1 << 23);
+static const int64_t lim32pos = 0x000000007fffffff;
+static const int64_t lim32neg = 0xffffffff80000000;
inline void testClamp8(float f)
{
@@ -689,3 +691,161 @@
delete[] u16expand;
delete[] u16ary;
}
+
+template<typename T, typename TComparison>
+void checkAddedClamped(T *out, const T *in1, const T *in2, size_t size,
+ TComparison limNeg, TComparison limPos)
+{
+ for (size_t i = 0; i < size; ++i) {
+ TComparison added = (TComparison)in1[i] + in2[i];
+ if (added <= limNeg) {
+ EXPECT_EQ(limNeg, out[i]);
+ } else if (added >= limPos) {
+ EXPECT_EQ(limPos, out[i]);
+ } else {
+ EXPECT_EQ(added, out[i]);
+ }
+ }
+}
+
+void checkAddedClampedp24(uint8_t *pary, const uint8_t *in1,
+ const uint8_t *in2, size_t size) {
+ // Convert to q8_23 for comparison.
+ int32_t *outi32ary = new int32_t[size];
+ int32_t *in1i32ary = new int32_t[size];
+ int32_t *in2i32ary = new int32_t[size];
+ memcpy_to_q8_23_from_p24(outi32ary, pary, size);
+ memcpy_to_q8_23_from_p24(in1i32ary, in1, size);
+ memcpy_to_q8_23_from_p24(in2i32ary, in2, size);
+ checkAddedClamped(
+ outi32ary, in1i32ary, in2i32ary, size, lim24neg, lim24pos);
+ delete[] in2i32ary;
+ delete[] in1i32ary;
+ delete[] outi32ary;
+}
+
+void checkAddedClampedu8(uint8_t *out, const uint8_t *in1,
+ const uint8_t *in2, size_t size) {
+ // uint8_t data is centered around 0x80, not 0, so checkAddedClamped
+ // won't work. Convert to i16 first.
+ int16_t *outi16ary = new int16_t[size];
+ int16_t *in1i16ary = new int16_t[size];
+ int16_t *in2i16ary = new int16_t[size];
+ memcpy_to_i16_from_u8(outi16ary, out, size);
+ memcpy_to_i16_from_u8(in1i16ary, in1, size);
+ memcpy_to_i16_from_u8(in2i16ary, in2, size);
+ // Only the higher order bits are used.
+ checkAddedClamped(outi16ary, in1i16ary, in2i16ary, size,
+ -0x8000, 0x7f00);
+ delete[] in2i16ary;
+ delete[] in1i16ary;
+ delete[] outi16ary;
+}
+
+TEST(audio_utils_primitives, accumulate) {
+ int16_t *i16ref = new int16_t[65536];
+ int16_t *i16add = new int16_t[65536];
+ int16_t *i16ary = new int16_t[65536];
+
+ for (size_t i = 0; i < 65536; ++i) {
+ i16ref[i] = i16ary[i] = i16add[(i+1) % 65536] = i - 32768;
+ }
+
+ // Test i16.
+ accumulate_i16(i16ary, i16add, 65536);
+ checkAddedClamped(i16ary, i16ref, i16add, 65536, lim16neg,
+ lim16pos);
+
+ // Test i32.
+ int32_t *i32ary = new int32_t[65536];
+ int32_t *i32add = new int32_t[65536];
+ int32_t *i32ref = new int32_t[65536];
+ // Convert sample data to i32 to perform accumulate function.
+ memcpy_to_i32_from_i16(i32ary, i16ref, 65536);
+ memcpy_to_i32_from_i16(i32add, i16add, 65536);
+ // Ensure the reference matches the inital output after conversion.
+ memcpy(i32ref, i32ary, 65536 * sizeof(i32ary[0]));
+ // Accumulate and check.
+ accumulate_i32(i32ary, i32add, 65536);
+ checkAddedClamped(
+ i32ary, i32ref, i32add, 65536, lim32neg, lim32pos);
+ // Cleanup
+ delete[] i32ref;
+ delete[] i32add;
+ delete[] i32ary;
+
+ // Test u8.
+ uint8_t *u8ary = new uint8_t[65536];
+ uint8_t *u8add = new uint8_t[65536];
+ uint8_t *u8ref = new uint8_t[65536];
+ // Convert sample data to u8 to perform accumulate function.
+ memcpy_to_u8_from_i16(u8ary, i16ref, 65536);
+ memcpy_to_u8_from_i16(u8add, i16add, 65536);
+ // Ensure the reference matches the inital output after conversion.
+ memcpy(u8ref, u8ary, 65536 * sizeof(u8ary[0]));
+ // Accumulate and check.
+ accumulate_u8(u8ary, u8add, 65536);
+ checkAddedClampedu8(u8ary, u8ref, u8add, 65536);
+ // Cleanup.
+ delete[] u8ref;
+ delete[] u8add;
+ delete[] u8ary;
+
+ // Test 24 bit packed.
+ uint8_t *pary = new uint8_t[65536 * 3];
+ uint8_t *padd = new uint8_t[65536 * 3];
+ uint8_t *pref = new uint8_t[65536 * 3];
+ // Convert sample data to p24 to perform accumulate function.
+ memcpy_to_p24_from_i16(pary, i16ref, 65536);
+ memcpy_to_p24_from_i16(padd, i16add, 65536);
+ // Ensure the reference matches the inital output after conversion.
+ memcpy(pref, pary, 65536 * sizeof(pary[0]) * 3);
+ // Accumulate and check.
+ accumulate_p24(pary, padd, 65536);
+ checkAddedClampedp24(pary, pref, padd, 65536);
+ // Cleanup.
+ delete[] pref;
+ delete[] padd;
+ delete[] pary;
+
+ // Test 24 bit unpacked.
+ int32_t *q8_23ary = new int32_t[65536];
+ int32_t *q8_23add = new int32_t[65536];
+ int32_t *q8_23ref = new int32_t[65536];
+ // Convert sample data to q8_23 to perform accumulate function.
+ memcpy_to_q8_23_from_i16(q8_23ary, i16ref, 65536);
+ memcpy_to_q8_23_from_i16(q8_23add, i16add, 65536);
+ // Ensure the reference matches the inital output after conversion.
+ memcpy(q8_23ref, q8_23ary, 65536 * sizeof(q8_23ary[0]));
+ // Accumulate and check.
+ accumulate_q8_23(q8_23ary, q8_23add, 65536);
+ checkAddedClamped(
+ q8_23ary, q8_23ref, q8_23add, 65536, lim24neg, lim24pos);
+ // Cleanup.
+ delete[] q8_23ref;
+ delete[] q8_23add;
+ delete[] q8_23ary;
+
+ // Test float.
+ float *fary = new float[65536];
+ float *fadd = new float[65536];
+ float *fref = new float[65536];
+ // Convert sample data to float to perform accumulate function.
+ memcpy_to_float_from_i16(fary, i16ref, 65536);
+ memcpy_to_float_from_i16(fadd, i16add, 65536);
+ // Ensure the reference matches the inital output after conversion.
+ memcpy(fref, fary, 65536 * sizeof(fary[0]));
+ // Accumulate and check. Floats aren't clamped by accumulate,
+ // but given the input is in the [-1.0, 1.0) range output should be in
+ // [-2.0, 2.0) range.
+ accumulate_float(fary, fadd, 65536);
+ checkAddedClamped(fary, fref, fadd, 65536, -2.0f, 2.0f);
+ // Cleanup.
+ delete[] fref;
+ delete[] fadd;
+ delete[] fary;
+
+ delete[] i16ary;
+ delete[] i16add;
+ delete[] i16ref;
+}
diff --git a/camera/docs/metadata_helpers.py b/camera/docs/metadata_helpers.py
index a501524..22d636f 100644
--- a/camera/docs/metadata_helpers.py
+++ b/camera/docs/metadata_helpers.py
@@ -904,6 +904,7 @@
"""
def ndkdoc_formatter(text):
# render with markdown => HTML
+ # Turn off the table plugin since doxygen doesn't recognize generated <thead> <tbody> tags
ndktext = md(text, NDKDOC_IMAGE_SRC_METADATA, False)
# Convert metadata entry "android.x.y.z" to form
diff --git a/camera/docs/ndk_camera_metadata_tags.mako b/camera/docs/ndk_camera_metadata_tags.mako
index 8232e50..f2ba1b0 100644
--- a/camera/docs/ndk_camera_metadata_tags.mako
+++ b/camera/docs/ndk_camera_metadata_tags.mako
@@ -36,13 +36,20 @@
#ifndef _NDK_CAMERA_METADATA_TAGS_H
#define _NDK_CAMERA_METADATA_TAGS_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+#if __ANDROID_API__ >= 24
<%!
+ from metadata_helpers import csym
def annotated_type(entry):
type = entry.type
if entry.container == 'array':
type += '[' + '*'.join(entry.container_sizes) + ']'
if entry.enum:
- type += ' (enum)'
+ type += ' (acamera_metadata_enum_%s_t)'%(csym(entry.name).lower())
return type
%>\
@@ -85,9 +92,13 @@
% else:
% if entry.description or entry.details:
/**
+ % if entry.description:
${entry.description | ndkdoc(metadata)}\
+ % endif
*
- * <p>This tag may appear in:</p>
+ * <p>Type: ${annotated_type(entry)}</p>
+ *
+ * <p>This tag may appear in:
* <ul>
% if metadata.is_entry_this_kind(entry, 'static'):
* <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
@@ -98,9 +109,11 @@
% if metadata.is_entry_this_kind(entry, 'controls'):
* <li>ACaptureRequest</li>
% endif
- * </ul>
+ * </ul></p>
*
+ % if entry.details:
${entry.details | ndkdoc(metadata)}\
+ % endif
*/
% endif
${ndk(entry.name) + " = " | csym,ljust(60)}// ${annotated_type(entry)}
@@ -179,7 +192,10 @@
% endfor
% endfor
+#endif /* __ANDROID_API__ >= 24 */
-#endif //_NDK_CAMERA_METADATA_TAGS_H
+__END_DECLS
+
+#endif /* _NDK_CAMERA_METADATA_TAGS_H */
/** @} */