Merge "audio policy: enable more than one sink per audio patch." into lmp-dev
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 3dd34ce..3a6bb9e 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -252,10 +252,19 @@
             int32_t width, int32_t height,
             OMX_VIDEO_CODINGTYPE compressionFormat);
 
+    typedef struct drcParams {
+        int32_t drcCut;
+        int32_t drcBoost;
+        int32_t heavyCompression;
+        int32_t targetRefLevel;
+        int32_t encodedTargetLevel;
+    } drcParams_t;
+
     status_t setupAACCodec(
             bool encoder,
             int32_t numChannels, int32_t sampleRate, int32_t bitRate,
-            int32_t aacProfile, bool isADTS, int32_t sbrMode);
+            int32_t aacProfile, bool isADTS, int32_t sbrMode,
+            int32_t maxOutputChannelCount, const drcParams_t& drc);
 
     status_t setupAC3Codec(bool encoder, int32_t numChannels, int32_t sampleRate);
 
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 1616448..6676461 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -228,13 +228,7 @@
     }
 
     if (mVideoTrack.mSource != NULL) {
-        sp<MetaData> meta = mVideoTrack.mSource->getFormat();
-
-        int32_t width, height;
-        CHECK(meta->findInt32(kKeyWidth, &width));
-        CHECK(meta->findInt32(kKeyHeight, &height));
-
-        notifyVideoSizeChanged(width, height);
+        notifyVideoSizeChanged(getFormat(false /* audio */));
     }
 
     notifyFlagsChanged(
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
index e8431e9..c713d39 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
@@ -210,9 +210,9 @@
             int32_t height;
             if (format != NULL &&
                     format->findInt32("width", &width) && format->findInt32("height", &height)) {
-                notifyVideoSizeChanged(width, height);
+                notifyVideoSizeChanged(format);
             } else {
-                notifyVideoSizeChanged(0, 0);
+                notifyVideoSizeChanged();
             }
 
             uint32_t flags = FLAG_CAN_PAUSE;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index fe115c6..6f6c9d9 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -852,60 +852,10 @@
                     mRenderer->signalAudioSinkChanged();
                 } else {
                     // video
+                    sp<AMessage> inputFormat =
+                            mSource->getFormat(false /* audio */);
 
-                    int32_t width, height;
-                    CHECK(format->findInt32("width", &width));
-                    CHECK(format->findInt32("height", &height));
-
-                    int32_t cropLeft, cropTop, cropRight, cropBottom;
-                    CHECK(format->findRect(
-                                "crop",
-                                &cropLeft, &cropTop, &cropRight, &cropBottom));
-
-                    int32_t displayWidth = cropRight - cropLeft + 1;
-                    int32_t displayHeight = cropBottom - cropTop + 1;
-
-                    ALOGV("Video output format changed to %d x %d "
-                         "(crop: %d x %d @ (%d, %d))",
-                         width, height,
-                         displayWidth,
-                         displayHeight,
-                         cropLeft, cropTop);
-
-                    sp<AMessage> videoInputFormat =
-                        mSource->getFormat(false /* audio */);
-
-                    // Take into account sample aspect ratio if necessary:
-                    int32_t sarWidth, sarHeight;
-                    if (videoInputFormat->findInt32("sar-width", &sarWidth)
-                            && videoInputFormat->findInt32(
-                                "sar-height", &sarHeight)) {
-                        ALOGV("Sample aspect ratio %d : %d",
-                              sarWidth, sarHeight);
-
-                        displayWidth = (displayWidth * sarWidth) / sarHeight;
-
-                        ALOGV("display dimensions %d x %d",
-                              displayWidth, displayHeight);
-                    }
-
-                    int32_t rotationDegrees;
-                    if (!videoInputFormat->findInt32(
-                            "rotation-degrees", &rotationDegrees)) {
-                        rotationDegrees = 0;
-                    }
-
-                    if (rotationDegrees == 90 || rotationDegrees == 270) {
-                        notifyListener(
-                                MEDIA_SET_VIDEO_SIZE,
-                                displayHeight,
-                                displayWidth);
-                    } else {
-                        notifyListener(
-                                MEDIA_SET_VIDEO_SIZE,
-                                displayWidth,
-                                displayHeight);
-                    }
+                    updateVideoSize(inputFormat, format);
                 }
             } else if (what == Decoder::kWhatShutdownCompleted) {
                 ALOGV("%s shutdown completed", audio ? "audio" : "video");
@@ -1383,6 +1333,72 @@
     mRenderer->queueBuffer(audio, buffer, reply);
 }
 
+void NuPlayer::updateVideoSize(
+        const sp<AMessage> &inputFormat,
+        const sp<AMessage> &outputFormat) {
+    if (inputFormat == NULL) {
+        ALOGW("Unknown video size, reporting 0x0!");
+        notifyListener(MEDIA_SET_VIDEO_SIZE, 0, 0);
+        return;
+    }
+
+    int32_t displayWidth, displayHeight;
+    int32_t cropLeft, cropTop, cropRight, cropBottom;
+
+    if (outputFormat != NULL) {
+        int32_t width, height;
+        CHECK(outputFormat->findInt32("width", &width));
+        CHECK(outputFormat->findInt32("height", &height));
+
+        int32_t cropLeft, cropTop, cropRight, cropBottom;
+        CHECK(outputFormat->findRect(
+                    "crop",
+                    &cropLeft, &cropTop, &cropRight, &cropBottom));
+
+        displayWidth = cropRight - cropLeft + 1;
+        displayHeight = cropBottom - cropTop + 1;
+
+        ALOGV("Video output format changed to %d x %d "
+             "(crop: %d x %d @ (%d, %d))",
+             width, height,
+             displayWidth,
+             displayHeight,
+             cropLeft, cropTop);
+    } else {
+        CHECK(inputFormat->findInt32("width", &displayWidth));
+        CHECK(inputFormat->findInt32("height", &displayHeight));
+
+        ALOGV("Video input format %d x %d", displayWidth, displayHeight);
+    }
+
+    // Take into account sample aspect ratio if necessary:
+    int32_t sarWidth, sarHeight;
+    if (inputFormat->findInt32("sar-width", &sarWidth)
+            && inputFormat->findInt32("sar-height", &sarHeight)) {
+        ALOGV("Sample aspect ratio %d : %d", sarWidth, sarHeight);
+
+        displayWidth = (displayWidth * sarWidth) / sarHeight;
+
+        ALOGV("display dimensions %d x %d", displayWidth, displayHeight);
+    }
+
+    int32_t rotationDegrees;
+    if (!inputFormat->findInt32("rotation-degrees", &rotationDegrees)) {
+        rotationDegrees = 0;
+    }
+
+    if (rotationDegrees == 90 || rotationDegrees == 270) {
+        int32_t tmp = displayWidth;
+        displayWidth = displayHeight;
+        displayHeight = tmp;
+    }
+
+    notifyListener(
+            MEDIA_SET_VIDEO_SIZE,
+            displayWidth,
+            displayHeight);
+}
+
 void NuPlayer::notifyListener(int msg, int ext1, int ext2, const Parcel *in) {
     if (mDriver == NULL) {
         return;
@@ -1441,19 +1457,19 @@
     }
 }
 
-sp<AMessage> NuPlayer::Source::getFormat(bool audio) {
-    sp<MetaData> meta = getFormatMeta(audio);
+void NuPlayer::queueDecoderShutdown(
+        bool audio, bool video, const sp<AMessage> &reply) {
+    ALOGI("queueDecoderShutdown audio=%d, video=%d", audio, video);
 
-    if (meta == NULL) {
-        return NULL;
-    }
+    mDeferredActions.push_back(
+            new ShutdownDecoderAction(audio, video));
 
-    sp<AMessage> msg = new AMessage;
+    mDeferredActions.push_back(
+            new SimpleAction(&NuPlayer::performScanSources));
 
-    if(convertMetaDataToMessage(meta, &msg) == OK) {
-        return msg;
-    }
-    return NULL;
+    mDeferredActions.push_back(new PostMessageAction(reply));
+
+    processDeferredActions();
 }
 
 status_t NuPlayer::setVideoScalingMode(int32_t mode) {
@@ -1729,11 +1745,10 @@
 
         case Source::kWhatVideoSizeChanged:
         {
-            int32_t width, height;
-            CHECK(msg->findInt32("width", &width));
-            CHECK(msg->findInt32("height", &height));
+            sp<AMessage> format;
+            CHECK(msg->findMessage("format", &format));
 
-            notifyListener(MEDIA_SET_VIDEO_SIZE, width, height);
+            updateVideoSize(format);
             break;
         }
 
@@ -1889,6 +1904,21 @@
 }
 ////////////////////////////////////////////////////////////////////////////////
 
+sp<AMessage> NuPlayer::Source::getFormat(bool audio) {
+    sp<MetaData> meta = getFormatMeta(audio);
+
+    if (meta == NULL) {
+        return NULL;
+    }
+
+    sp<AMessage> msg = new AMessage;
+
+    if(convertMetaDataToMessage(meta, &msg) == OK) {
+        return msg;
+    }
+    return NULL;
+}
+
 void NuPlayer::Source::notifyFlagsChanged(uint32_t flags) {
     sp<AMessage> notify = dupNotify();
     notify->setInt32("what", kWhatFlagsChanged);
@@ -1896,11 +1926,10 @@
     notify->post();
 }
 
-void NuPlayer::Source::notifyVideoSizeChanged(int32_t width, int32_t height) {
+void NuPlayer::Source::notifyVideoSizeChanged(const sp<AMessage> &format) {
     sp<AMessage> notify = dupNotify();
     notify->setInt32("what", kWhatVideoSizeChanged);
-    notify->setInt32("width", width);
-    notify->setInt32("height", height);
+    notify->setMessage("format", format);
     notify->post();
 }
 
@@ -1915,19 +1944,4 @@
     TRESPASS();
 }
 
-void NuPlayer::queueDecoderShutdown(
-        bool audio, bool video, const sp<AMessage> &reply) {
-    ALOGI("queueDecoderShutdown audio=%d, video=%d", audio, video);
-
-    mDeferredActions.push_back(
-            new ShutdownDecoderAction(audio, video));
-
-    mDeferredActions.push_back(
-            new SimpleAction(&NuPlayer::performScanSources));
-
-    mDeferredActions.push_back(new PostMessageAction(reply));
-
-    processDeferredActions();
-}
-
 }  // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 8bcf10e..486b7cc 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -167,6 +167,10 @@
 
     status_t instantiateDecoder(bool audio, sp<Decoder> *decoder);
 
+    void updateVideoSize(
+            const sp<AMessage> &inputFormat,
+            const sp<AMessage> &outputFormat = NULL);
+
     status_t feedDecoderInputData(bool audio, const sp<AMessage> &msg);
     void renderBuffer(bool audio, const sp<AMessage> &msg);
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
index 0ec017e..06bbbec 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -110,7 +110,7 @@
     sp<AMessage> dupNotify() const { return mNotify->dup(); }
 
     void notifyFlagsChanged(uint32_t flags);
-    void notifyVideoSizeChanged(int32_t width, int32_t height);
+    void notifyVideoSizeChanged(const sp<AMessage> &format = NULL);
     void notifyPrepared(status_t err = OK);
 
 private:
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index 2338b23..a911f6c 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -356,7 +356,7 @@
         {
             onConnected();
 
-            notifyVideoSizeChanged(0, 0);
+            notifyVideoSizeChanged();
 
             uint32_t flags = 0;
 
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
index 28f0d50..2e9a29a 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -44,7 +44,7 @@
 }
 
 void NuPlayer::StreamingSource::prepareAsync() {
-    notifyVideoSizeChanged(0, 0);
+    notifyVideoSizeChanged();
     notifyFlagsChanged(0);
     notifyPrepared();
 }
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 524e201..503ce81 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1332,6 +1332,8 @@
         } else {
             int32_t isADTS, aacProfile;
             int32_t sbrMode;
+            int32_t maxOutputChannelCount;
+            drcParams_t drc;
             if (!msg->findInt32("is-adts", &isADTS)) {
                 isADTS = 0;
             }
@@ -1342,9 +1344,33 @@
                 sbrMode = -1;
             }
 
+            if (!msg->findInt32("aac-max-output-channel_count", &maxOutputChannelCount)) {
+                maxOutputChannelCount = -1;
+            }
+            if (!msg->findInt32("aac-encoded-target-level", &drc.encodedTargetLevel)) {
+                // value is unknown
+                drc.encodedTargetLevel = -1;
+            }
+            if (!msg->findInt32("aac-drc-cut-level", &drc.drcCut)) {
+                // value is unknown
+                drc.drcCut = -1;
+            }
+            if (!msg->findInt32("aac-drc-boost-level", &drc.drcBoost)) {
+                // value is unknown
+                drc.drcBoost = -1;
+            }
+            if (!msg->findInt32("aac-drc-heavy-compression", &drc.heavyCompression)) {
+                // value is unknown
+                drc.heavyCompression = -1;
+            }
+            if (!msg->findInt32("aac-target-ref-level", &drc.targetRefLevel)) {
+                // value is unknown
+                drc.targetRefLevel = -1;
+            }
+
             err = setupAACCodec(
                     encoder, numChannels, sampleRate, bitRate, aacProfile,
-                    isADTS != 0, sbrMode);
+                    isADTS != 0, sbrMode, maxOutputChannelCount, drc);
         }
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
         err = setupAMRCodec(encoder, false /* isWAMR */, bitRate);
@@ -1506,7 +1532,8 @@
 
 status_t ACodec::setupAACCodec(
         bool encoder, int32_t numChannels, int32_t sampleRate,
-        int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode) {
+        int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode,
+        int32_t maxOutputChannelCount, const drcParams_t& drc) {
     if (encoder && isADTS) {
         return -EINVAL;
     }
@@ -1629,8 +1656,23 @@
             ? OMX_AUDIO_AACStreamFormatMP4ADTS
             : OMX_AUDIO_AACStreamFormatMP4FF;
 
-    return mOMX->setParameter(
-            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
+    OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation;
+    presentation.nMaxOutputChannels = maxOutputChannelCount;
+    presentation.nDrcCut = drc.drcCut;
+    presentation.nDrcBoost = drc.drcBoost;
+    presentation.nHeavyCompression = drc.heavyCompression;
+    presentation.nTargetReferenceLevel = drc.targetRefLevel;
+    presentation.nEncodedTargetLevel = drc.encodedTargetLevel;
+
+    status_t res = mOMX->setParameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
+    if (res == OK) {
+        // optional parameters, will not cause configuration failure
+        mOMX->setParameter(mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation,
+                &presentation, sizeof(presentation));
+    } else {
+        ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res);
+    }
+    return res;
 }
 
 status_t ACodec::setupAC3Codec(
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index ab30865..09c6e69 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -19,6 +19,8 @@
 #include <utils/Log.h>
 
 #include "SoftAAC2.h"
+#include <OMX_AudioExt.h>
+#include <OMX_IndexExt.h>
 
 #include <cutils/properties.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -119,6 +121,7 @@
 }
 
 status_t SoftAAC2::initDecoder() {
+    ALOGV("initDecoder()");
     status_t status = UNKNOWN_ERROR;
     mAACDecoder = aacDecoder_Open(TT_MP4_ADIF, /* num layers */ 1);
     if (mAACDecoder != NULL) {
@@ -275,7 +278,7 @@
 
 OMX_ERRORTYPE SoftAAC2::internalSetParameter(
         OMX_INDEXTYPE index, const OMX_PTR params) {
-    switch (index) {
+    switch ((int)index) {
         case OMX_IndexParamStandardComponentRole:
         {
             const OMX_PARAM_COMPONENTROLETYPE *roleParams =
@@ -311,6 +314,67 @@
             return OMX_ErrorNone;
         }
 
+        case OMX_IndexParamAudioAndroidAacPresentation:
+        {
+            const OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE *aacPresParams =
+                    (const OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE *)params;
+            // for the following parameters of the OMX_AUDIO_PARAM_AACPROFILETYPE structure,
+            // a value of -1 implies the parameter is not set by the application:
+            //   nMaxOutputChannels     uses default platform properties, see configureDownmix()
+            //   nDrcCut                uses default platform properties, see initDecoder()
+            //   nDrcBoost                idem
+            //   nHeavyCompression        idem
+            //   nTargetReferenceLevel    idem
+            //   nEncodedTargetLevel      idem
+            if (aacPresParams->nMaxOutputChannels >= 0) {
+                int max;
+                if (aacPresParams->nMaxOutputChannels >= 8) { max = 8; }
+                else if (aacPresParams->nMaxOutputChannels >= 6) { max = 6; }
+                else if (aacPresParams->nMaxOutputChannels >= 2) { max = 2; }
+                else {
+                    // -1 or 0: disable downmix,  1: mono
+                    max = aacPresParams->nMaxOutputChannels;
+                }
+                ALOGV("set nMaxOutputChannels=%d", max);
+                aacDecoder_SetParam(mAACDecoder, AAC_PCM_MAX_OUTPUT_CHANNELS, max);
+            }
+            bool updateDrcWrapper = false;
+            if (aacPresParams->nDrcBoost >= 0) {
+                ALOGV("set nDrcBoost=%d", aacPresParams->nDrcBoost);
+                mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR,
+                        aacPresParams->nDrcBoost);
+                updateDrcWrapper = true;
+            }
+            if (aacPresParams->nDrcCut >= 0) {
+                ALOGV("set nDrcCut=%d", aacPresParams->nDrcCut);
+                mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, aacPresParams->nDrcCut);
+                updateDrcWrapper = true;
+            }
+            if (aacPresParams->nHeavyCompression >= 0) {
+                ALOGV("set nHeavyCompression=%d", aacPresParams->nHeavyCompression);
+                mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY,
+                        aacPresParams->nHeavyCompression);
+                updateDrcWrapper = true;
+            }
+            if (aacPresParams->nTargetReferenceLevel >= 0) {
+                ALOGV("set nTargetReferenceLevel=%d", aacPresParams->nTargetReferenceLevel);
+                mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET,
+                        aacPresParams->nTargetReferenceLevel);
+                updateDrcWrapper = true;
+            }
+            if (aacPresParams->nEncodedTargetLevel >= 0) {
+                ALOGV("set nEncodedTargetLevel=%d", aacPresParams->nEncodedTargetLevel);
+                mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET,
+                        aacPresParams->nEncodedTargetLevel);
+                updateDrcWrapper = true;
+            }
+            if (updateDrcWrapper) {
+                mDrcWrap.update();
+            }
+
+            return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamAudioPcm:
         {
             const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
diff --git a/media/libstagefright/foundation/AString.cpp b/media/libstagefright/foundation/AString.cpp
index bf474e1..9835ca3 100644
--- a/media/libstagefright/foundation/AString.cpp
+++ b/media/libstagefright/foundation/AString.cpp
@@ -358,7 +358,7 @@
 }
 
 status_t AString::writeToParcel(Parcel *parcel) const {
-    CHECK_LE(mSize, (size_t)INT32_MAX);
+    CHECK_LE(mSize, static_cast<size_t>(INT32_MAX));
     status_t err = parcel->writeInt32(mSize);
     if (err == OK) {
         err = parcel->write(mData, mSize);