Merge "aaudio examples: make tests portable to O"
diff --git a/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp b/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp
index cb69f91..eaa3390 100644
--- a/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp
+++ b/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp
@@ -89,7 +89,7 @@
     // asset_id change. If it sends an EcmContainer with 2 Ecms with different
     // asset_ids (old and new) then it might be best to prefetch the Emm.
     if ((asset_.id() != 0) && (*asset_id != asset_.id())) {
-        ALOGW("Asset_id change from %" PRIu64 " to %" PRIu64, asset_.id(), *asset_id);
+        ALOGW("Asset_id change from %llu to %" PRIu64, asset_.id(), *asset_id);
         asset_.Clear();
     }
 
diff --git a/drm/mediacas/plugins/clearkey/ecm.cpp b/drm/mediacas/plugins/clearkey/ecm.cpp
index b3b5218..9fde13a 100644
--- a/drm/mediacas/plugins/clearkey/ecm.cpp
+++ b/drm/mediacas/plugins/clearkey/ecm.cpp
@@ -17,8 +17,6 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "ecm"
 
-#include <inttypes.h>
-
 #include "ecm.h"
 #include "ecm_generator.h"
 #include "protos/license_protos.pb.h"
@@ -78,7 +76,7 @@
         return status;
     }
     if (asset.id() != asset_from_emm.id()) {
-        ALOGE("Asset_id from Emm (%" PRIu64 ") does not match asset_id from Ecm (%" PRIu64 ").",
+        ALOGE("Asset_id from Emm (%llu) does not match asset_id from Ecm (%llu).",
                 asset_from_emm.id(), asset.id());
         return CLEARKEY_STATUS_INVALID_PARAMETER;
     }
diff --git a/media/libeffects/visualizer/Android.mk b/media/libeffects/visualizer/Android.mk
index 3534149..35e2f3d 100644
--- a/media/libeffects/visualizer/Android.mk
+++ b/media/libeffects/visualizer/Android.mk
@@ -9,6 +9,7 @@
 
 LOCAL_CFLAGS+= -O2 -fvisibility=hidden
 LOCAL_CFLAGS += -Wall -Werror
+LOCAL_CFLAGS += -DBUILD_FLOAT -DSUPPORT_MC
 
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
index e2ccfb7..00bc371 100644
--- a/media/libeffects/visualizer/EffectVisualizer.cpp
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -32,8 +32,6 @@
 #include <audio_effects/effect_visualizer.h>
 #include <audio_utils/primitives.h>
 
-#define BUILD_FLOAT
-
 #ifdef BUILD_FLOAT
 
 static constexpr audio_format_t kProcessFormat = AUDIO_FORMAT_PCM_FLOAT;
@@ -157,7 +155,12 @@
     if (pConfig->inputCfg.samplingRate != pConfig->outputCfg.samplingRate) return -EINVAL;
     if (pConfig->inputCfg.channels != pConfig->outputCfg.channels) return -EINVAL;
     if (pConfig->inputCfg.format != pConfig->outputCfg.format) return -EINVAL;
-    if (pConfig->inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO) return -EINVAL;
+    const uint32_t channelCount = audio_channel_count_from_out_mask(pConfig->inputCfg.channels);
+#ifdef SUPPORT_MC
+    if (channelCount < 1 || channelCount > FCC_8) return -EINVAL;
+#else
+    if (channelCount != FCC_2) return -EINVAL;
+#endif
     if (pConfig->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_WRITE &&
             pConfig->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_ACCUMULATE) return -EINVAL;
     if (pConfig->inputCfg.format != kProcessFormat) return -EINVAL;
@@ -356,7 +359,7 @@
         // store the measurement
         pContext->mPastMeasurements[pContext->mMeasurementBufferIdx].mPeakU16 = (uint16_t)maxSample;
         pContext->mPastMeasurements[pContext->mMeasurementBufferIdx].mRmsSquared =
-                rmsSqAcc / (inBuffer->frameCount * pContext->mChannelCount);
+                rmsSqAcc / sampleLen;
         pContext->mPastMeasurements[pContext->mMeasurementBufferIdx].mIsValid = true;
         if (++pContext->mMeasurementBufferIdx >= pContext->mMeasurementWindowSizeInBuffers) {
             pContext->mMeasurementBufferIdx = 0;
@@ -375,12 +378,17 @@
 
 #ifdef BUILD_FLOAT
         float maxSample = 0.f;
-        for (size_t inIdx = 0; inIdx < sampleLen; ++inIdx) {
-            maxSample = fmax(maxSample, fabs(inBuffer->f32[inIdx]));
+        for (size_t inIdx = 0; inIdx < sampleLen; ) {
+            // we reconstruct the actual summed value to ensure proper normalization
+            // for multichannel outputs (channels > 2 may often be 0).
+            float smp = 0.f;
+            for (int i = 0; i < pContext->mChannelCount; ++i) {
+                smp += inBuffer->f32[inIdx++];
+            }
+            maxSample = fmax(maxSample, fabs(smp));
         }
         if (maxSample > 0.f) {
-            constexpr float halfish = 127.f / 256.f;
-            fscale = halfish / maxSample;
+            fscale = 127.f / maxSample;
             int exp; // unused
             const float significand = frexp(fscale, &exp);
             if (significand == 0.5f) {
@@ -412,7 +420,8 @@
     } else {
         assert(pContext->mScalingMode == VISUALIZER_SCALING_MODE_AS_PLAYED);
 #ifdef BUILD_FLOAT
-        fscale = 0.5f;  // default divide by 2 to account for sum of L + R.
+        // Note: if channels are uncorrelated, 1/sqrt(N) could be used at the risk of clipping.
+        fscale = 1.f / pContext->mChannelCount;  // account for summing all the channels together.
 #else
         shift = 9;
 #endif // BUILD_FLOAT
@@ -422,17 +431,19 @@
     uint32_t inIdx;
     uint8_t *buf = pContext->mCaptureBuf;
     for (inIdx = 0, captIdx = pContext->mCaptureIdx;
-         inIdx < inBuffer->frameCount;
-         inIdx++, captIdx++) {
-        if (captIdx >= CAPTURE_BUF_SIZE) {
-            // wrap around
-            captIdx = 0;
-        }
+         inIdx < sampleLen;
+         captIdx++) {
+        if (captIdx >= CAPTURE_BUF_SIZE) captIdx = 0; // wrap
+
 #ifdef BUILD_FLOAT
-        const float smp = (inBuffer->f32[2 * inIdx] + inBuffer->f32[2 * inIdx + 1]) * fscale;
-        buf[captIdx] = clamp8_from_float(smp);
+        float smp = 0.f;
+        for (uint32_t i = 0; i < pContext->mChannelCount; ++i) {
+            smp += inBuffer->f32[inIdx++];
+        }
+        buf[captIdx] = clamp8_from_float(smp * fscale);
 #else
-        const int32_t smp = (inBuffer->s16[2 * inIdx] + inBuffer->s16[2 * inIdx + 1]) >> shift;
+        const int32_t smp = (inBuffer->s16[inIdx] + inBuffer->s16[inIdx + 1]) >> shift;
+        inIdx += FCC_2;  // integer supports stereo only.
         buf[captIdx] = ((uint8_t)smp)^0x80;
 #endif // BUILD_FLOAT
     }
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 25d28ff..3d9e62e 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -291,6 +291,7 @@
         "libmediaextractor",
         "libmediandk",
         "libnativewindow",
+        "libmediandk_utils",
         "libstagefright_foundation",
         "libui",
         "libutils",
@@ -305,6 +306,10 @@
         "media_plugin_headers",
     ],
 
+    include_dirs: [
+        "frameworks/av/media/ndk",
+    ],
+
     static_libs: [
         "libstagefright_rtsp",
         "libstagefright_timedtext",
diff --git a/media/libmedia/NdkWrapper.cpp b/media/libmedia/NdkWrapper.cpp
index 9e09c7e..eed96e7 100644
--- a/media/libmedia/NdkWrapper.cpp
+++ b/media/libmedia/NdkWrapper.cpp
@@ -31,6 +31,8 @@
 #include <media/stagefright/foundation/AMessage.h>
 #include <utils/Errors.h>
 
+#include "NdkMediaDataSourceCallbacksPriv.h"
+
 namespace android {
 
 static const size_t kAESBlockSize = 16;  // AES_BLOCK_SIZE
@@ -1244,8 +1246,14 @@
     return new AMediaCodecCryptoInfoWrapper(AMediaExtractor_getSampleCryptoInfo(mAMediaExtractor));
 }
 
+AMediaDataSourceWrapper::AMediaDataSourceWrapper(const sp<DataSource> &dataSource)
+    : mDataSource(dataSource),
+      mAMediaDataSource(convertDataSourceToAMediaDataSource(dataSource)) {
+}
+
 AMediaDataSourceWrapper::AMediaDataSourceWrapper(AMediaDataSource *aDataSource)
-    : mAMediaDataSource(aDataSource) {
+    : mDataSource(NULL),
+      mAMediaDataSource(aDataSource) {
 }
 
 AMediaDataSourceWrapper::~AMediaDataSourceWrapper() {
diff --git a/media/libmedia/include/media/NdkWrapper.h b/media/libmedia/include/media/NdkWrapper.h
index b3b0688..8a417f6 100644
--- a/media/libmedia/include/media/NdkWrapper.h
+++ b/media/libmedia/include/media/NdkWrapper.h
@@ -280,13 +280,10 @@
 
 struct AMediaDataSourceWrapper : public RefBase {
 
+    AMediaDataSourceWrapper(const sp<DataSource>&);
     AMediaDataSourceWrapper(AMediaDataSource*);
-    AMediaDataSourceWrapper(int fd, int64_t offset, int64_t length);
 
     AMediaDataSource *getAMediaDataSource();
-    int getFd() { return mFd; }
-    int64_t getOffset() { return mOffset; }
-    int64_t getLength() { return mLength; }
 
     void close();
 
@@ -294,10 +291,8 @@
     virtual ~AMediaDataSourceWrapper();
 
 private:
+    sp<DataSource> mDataSource;
     AMediaDataSource *mAMediaDataSource;
-    int mFd;
-    int64_t mOffset;
-    int64_t mLength;
 
     DISALLOW_EVIL_CONSTRUCTORS(AMediaDataSourceWrapper);
 };
diff --git a/media/libmediaplayer2/nuplayer2/GenericSource2.cpp b/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
index f795478..1860b0c 100644
--- a/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
+++ b/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
@@ -34,7 +34,6 @@
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/NdkUtils.h>
 #include <media/stagefright/Utils.h>
-#include "NdkMediaDataSourceCallbacksPriv.h"
 
 namespace android {
 
@@ -137,8 +136,7 @@
     ALOGV("setDataSource (source: %p)", source.get());
 
     resetDataSource();
-    AMediaDataSource *aSource = convertDataSourceToAMediaDataSource(source);
-    mDataSourceWrapper = new AMediaDataSourceWrapper(aSource);
+    mDataSourceWrapper = new AMediaDataSourceWrapper(source);
     return OK;
 }
 
diff --git a/media/ndk/NdkImageReaderPriv.h b/media/ndk/NdkImageReaderPriv.h
index a9b54a8..d9ddfd9 100644
--- a/media/ndk/NdkImageReaderPriv.h
+++ b/media/ndk/NdkImageReaderPriv.h
@@ -170,9 +170,7 @@
 };
 
 // Retrieves HGraphicBufferProducer corresponding to the native_handle_t
-// provided. This method also deletes the HalToken corresponding to the
-// native_handle_t. Thus, if it is used twice in succession, the second call
-// returns nullptr;
+// provided (this native handle MUST have been obtained by AImageReader_getWindowNativeHandle()).
 sp<HGraphicBufferProducer> AImageReader_getHGBPFromHandle(const native_handle_t *handle);
 
 #endif // _NDK_IMAGE_READER_PRIV_H