Merge "Clean up AudioTrack position and timestamp handling" into lmp-dev
diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
index 2f63bdd..828577a 100644
--- a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
+++ b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
@@ -137,29 +137,10 @@
 
             uint32_t width = mImg->d_w;
             uint32_t height = mImg->d_h;
-
-            if (width != mWidth || height != mHeight) {
-                mWidth = width;
-                mHeight = height;
-
-                if (!mIsAdaptive || width > mAdaptiveMaxWidth || height > mAdaptiveMaxHeight) {
-                    if (mIsAdaptive) {
-                        if (width > mAdaptiveMaxWidth) {
-                            mAdaptiveMaxWidth = width;
-                        }
-                        if (height > mAdaptiveMaxHeight) {
-                            mAdaptiveMaxHeight = height;
-                        }
-                    }
-                    updatePortDefinitions();
-                    notify(OMX_EventPortSettingsChanged, kOutputPortIndex, 0, NULL);
-                    mOutputPortSettingsChange = AWAITING_DISABLED;
-                    return;
-                } else {
-                    updatePortDefinitions();
-                    notify(OMX_EventPortSettingsChanged, kOutputPortIndex,
-                           OMX_IndexConfigCommonOutputCrop, NULL);
-                }
+            bool portWillReset = false;
+            handlePortSettingsChange(&portWillReset, width, height);
+            if (portWillReset) {
+                return;
             }
 
             outHeader->nOffset = 0;
@@ -167,36 +148,14 @@
             outHeader->nFlags = EOSseen ? OMX_BUFFERFLAG_EOS : 0;
             outHeader->nTimeStamp = inHeader->nTimeStamp;
 
-            uint32_t buffer_stride = mIsAdaptive ? mAdaptiveMaxWidth : mWidth;
-            uint32_t buffer_height = mIsAdaptive ? mAdaptiveMaxHeight : mHeight;
-
-            const uint8_t *srcLine = (const uint8_t *)mImg->planes[PLANE_Y];
             uint8_t *dst = outHeader->pBuffer;
-            for (size_t i = 0; i < buffer_height; ++i) {
-                if (i < mImg->d_h) {
-                    memcpy(dst, srcLine, mImg->d_w);
-                    srcLine += mImg->stride[PLANE_Y];
-                }
-                dst += buffer_stride;
-            }
-
-            srcLine = (const uint8_t *)mImg->planes[PLANE_U];
-            for (size_t i = 0; i < buffer_height / 2; ++i) {
-                if (i < mImg->d_h / 2) {
-                    memcpy(dst, srcLine, mImg->d_w / 2);
-                    srcLine += mImg->stride[PLANE_U];
-                }
-                dst += buffer_stride / 2;
-            }
-
-            srcLine = (const uint8_t *)mImg->planes[PLANE_V];
-            for (size_t i = 0; i < buffer_height / 2; ++i) {
-                if (i < mImg->d_h / 2) {
-                    memcpy(dst, srcLine, mImg->d_w / 2);
-                    srcLine += mImg->stride[PLANE_V];
-                }
-                dst += buffer_stride / 2;
-            }
+            const uint8_t *srcY = (const uint8_t *)mImg->planes[PLANE_Y];
+            const uint8_t *srcU = (const uint8_t *)mImg->planes[PLANE_U];
+            const uint8_t *srcV = (const uint8_t *)mImg->planes[PLANE_V];
+            size_t srcYStride = mImg->stride[PLANE_Y];
+            size_t srcUStride = mImg->stride[PLANE_U];
+            size_t srcVStride = mImg->stride[PLANE_V];
+            copyYV12FrameToOutputBuffer(dst, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride);
 
             mImg = NULL;
             outInfo->mOwnedByUs = false;
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
index a7bde97..cf3c3e3 100644
--- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
@@ -58,7 +58,6 @@
             320 /* width */, 240 /* height */, callbacks, appData, component),
       mHandle(NULL),
       mInputBufferCount(0),
-      mPictureSize(mWidth * mHeight * 3 / 2),
       mFirstPicture(NULL),
       mFirstPictureId(-1),
       mPicId(0),
@@ -118,7 +117,7 @@
     }
 
     H264SwDecRet ret = H264SWDEC_PIC_RDY;
-    bool portSettingsChanged = false;
+    bool portWillReset = false;
     while ((mEOSStatus != INPUT_DATA_AVAILABLE || !inQueue.empty())
             && outQueue.size() == kNumOutputBuffers) {
 
@@ -161,17 +160,13 @@
                     H264SwDecInfo decoderInfo;
                     CHECK(H264SwDecGetInfo(mHandle, &decoderInfo) == H264SWDEC_OK);
 
-                    if (handlePortSettingChangeEvent(&decoderInfo)) {
-                        portSettingsChanged = true;
-                    }
-
-                    if (decoderInfo.croppingFlag &&
-                        handleCropRectEvent(&decoderInfo.cropParams)) {
-                        portSettingsChanged = true;
-                    }
+                    bool cropChanged = handleCropChange(decoderInfo);
+                    handlePortSettingsChange(
+                            &portWillReset, decoderInfo.picWidth, decoderInfo.picHeight,
+                            cropChanged);
                 }
             } else {
-                if (portSettingsChanged) {
+                if (portWillReset) {
                     if (H264SwDecNextPicture(mHandle, &decodedPicture, 0)
                         == H264SWDEC_PIC_RDY) {
 
@@ -199,8 +194,7 @@
         inInfo->mOwnedByUs = false;
         notifyEmptyBufferDone(inHeader);
 
-        if (portSettingsChanged) {
-            portSettingsChanged = false;
+        if (portWillReset) {
             return;
         }
 
@@ -215,44 +209,33 @@
     }
 }
 
-bool SoftAVC::handlePortSettingChangeEvent(const H264SwDecInfo *info) {
-    if (mWidth != info->picWidth || mHeight != info->picHeight) {
-        mWidth  = info->picWidth;
-        mHeight = info->picHeight;
-        mPictureSize = mWidth * mHeight * 3 / 2;
-        updatePortDefinitions();
-        notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
-        mOutputPortSettingsChange = AWAITING_DISABLED;
-        return true;
+bool SoftAVC::handleCropChange(const H264SwDecInfo& decInfo) {
+    if (!decInfo.croppingFlag) {
+        return false;
     }
 
-    return false;
-}
-
-bool SoftAVC::handleCropRectEvent(const CropParams *crop) {
-    if (mCropLeft != crop->cropLeftOffset ||
-        mCropTop != crop->cropTopOffset ||
-        mCropWidth != crop->cropOutWidth ||
-        mCropHeight != crop->cropOutHeight) {
-        mCropLeft = crop->cropLeftOffset;
-        mCropTop = crop->cropTopOffset;
-        mCropWidth = crop->cropOutWidth;
-        mCropHeight = crop->cropOutHeight;
-
-        notify(OMX_EventPortSettingsChanged, 1,
-                OMX_IndexConfigCommonOutputCrop, NULL);
-
-        return true;
+    const CropParams& crop = decInfo.cropParams;
+    if (mCropLeft == crop.cropLeftOffset &&
+        mCropTop == crop.cropTopOffset &&
+        mCropWidth == crop.cropOutWidth &&
+        mCropHeight == crop.cropOutHeight) {
+        return false;
     }
-    return false;
+
+    mCropLeft = crop.cropLeftOffset;
+    mCropTop = crop.cropTopOffset;
+    mCropWidth = crop.cropOutWidth;
+    mCropHeight = crop.cropOutHeight;
+    return true;
 }
 
 void SoftAVC::saveFirstOutputBuffer(int32_t picId, uint8_t *data) {
     CHECK(mFirstPicture == NULL);
     mFirstPictureId = picId;
 
-    mFirstPicture = new uint8_t[mPictureSize];
-    memcpy(mFirstPicture, data, mPictureSize);
+    uint32_t pictureSize = mWidth * mHeight * 3 / 2;
+    mFirstPicture = new uint8_t[pictureSize];
+    memcpy(mFirstPicture, data, pictureSize);
 }
 
 void SoftAVC::drainOneOutputBuffer(int32_t picId, uint8_t* data) {
@@ -263,9 +246,17 @@
     OMX_BUFFERHEADERTYPE *header = mPicToHeaderMap.valueFor(picId);
     outHeader->nTimeStamp = header->nTimeStamp;
     outHeader->nFlags = header->nFlags;
-    outHeader->nFilledLen = mPictureSize;
-    memcpy(outHeader->pBuffer + outHeader->nOffset,
-            data, mPictureSize);
+    outHeader->nFilledLen = mWidth * mHeight * 3 / 2;
+
+    uint8_t *dst = outHeader->pBuffer + outHeader->nOffset;
+    const uint8_t *srcY = data;
+    const uint8_t *srcU = srcY + mWidth * mHeight;
+    const uint8_t *srcV = srcU + mWidth * mHeight / 4;
+    size_t srcYStride = mWidth;
+    size_t srcUStride = mWidth / 2;
+    size_t srcVStride = srcUStride;
+    copyYV12FrameToOutputBuffer(dst, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride);
+
     mPicToHeaderMap.removeItem(picId);
     delete header;
     outInfo->mOwnedByUs = false;
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.h b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
index ee69926..253a406 100644
--- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
@@ -55,8 +55,6 @@
 
     size_t mInputBufferCount;
 
-    uint32_t mPictureSize;
-
     uint8_t *mFirstPicture;
     int32_t mFirstPictureId;
 
@@ -75,8 +73,7 @@
     void drainAllOutputBuffers(bool eos);
     void drainOneOutputBuffer(int32_t picId, uint8_t *data);
     void saveFirstOutputBuffer(int32_t pidId, uint8_t *data);
-    bool handleCropRectEvent(const CropParams* crop);
-    bool handlePortSettingChangeEvent(const H264SwDecInfo *info);
+    bool handleCropChange(const H264SwDecInfo& decInfo);
 
     DISALLOW_EVIL_CONSTRUCTORS(SoftAVC);
 };
diff --git a/media/libstagefright/include/SoftVideoDecoderOMXComponent.h b/media/libstagefright/include/SoftVideoDecoderOMXComponent.h
index ee553d9..4a6ab63 100644
--- a/media/libstagefright/include/SoftVideoDecoderOMXComponent.h
+++ b/media/libstagefright/include/SoftVideoDecoderOMXComponent.h
@@ -63,7 +63,14 @@
             OMX_U32 numOutputBuffers,
             const char *mimeType);
 
-    virtual void updatePortDefinitions();
+    virtual void updatePortDefinitions(bool updateCrop = true);
+
+    void handlePortSettingsChange(
+            bool *portWillReset, uint32_t width, uint32_t height, bool cropChanged = false);
+
+    void copyYV12FrameToOutputBuffer(
+            uint8_t *dst, const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV,
+            size_t srcYStride, size_t srcUStride, size_t srcVStride);
 
     enum {
         kInputPortIndex  = 0,
diff --git a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
index 69b572e..e533fdd 100644
--- a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
@@ -123,13 +123,15 @@
     updatePortDefinitions();
 }
 
-void SoftVideoDecoderOMXComponent::updatePortDefinitions() {
+void SoftVideoDecoderOMXComponent::updatePortDefinitions(bool updateCrop) {
     OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef;
     def->format.video.nFrameWidth = mWidth;
     def->format.video.nFrameHeight = mHeight;
     def->format.video.nStride = def->format.video.nFrameWidth;
     def->format.video.nSliceHeight = def->format.video.nFrameHeight;
 
+    def->nBufferSize = def->format.video.nFrameWidth * def->format.video.nFrameHeight * 3 / 2;
+
     def = &editPortInfo(kOutputPortIndex)->mDef;
     def->format.video.nFrameWidth = mIsAdaptive ? mAdaptiveMaxWidth : mWidth;
     def->format.video.nFrameHeight = mIsAdaptive ? mAdaptiveMaxHeight : mHeight;
@@ -140,10 +142,77 @@
             (def->format.video.nFrameWidth *
              def->format.video.nFrameHeight * 3) / 2;
 
-    mCropLeft = 0;
-    mCropTop = 0;
-    mCropWidth = mWidth;
-    mCropHeight = mHeight;
+    if (updateCrop) {
+        mCropLeft = 0;
+        mCropTop = 0;
+        mCropWidth = mWidth;
+        mCropHeight = mHeight;
+    }
+}
+
+void SoftVideoDecoderOMXComponent::handlePortSettingsChange(
+        bool *portWillReset, uint32_t width, uint32_t height, bool cropChanged) {
+    *portWillReset = false;
+    bool sizeChanged = (width != mWidth || height != mHeight);
+
+    if (sizeChanged || cropChanged) {
+        mWidth = width;
+        mHeight = height;
+
+        bool updateCrop = !cropChanged;
+        if ((sizeChanged && !mIsAdaptive)
+            || width > mAdaptiveMaxWidth
+            || height > mAdaptiveMaxHeight) {
+            if (mIsAdaptive) {
+                if (width > mAdaptiveMaxWidth) {
+                    mAdaptiveMaxWidth = width;
+                }
+                if (height > mAdaptiveMaxHeight) {
+                    mAdaptiveMaxHeight = height;
+                }
+            }
+            updatePortDefinitions(updateCrop);
+            notify(OMX_EventPortSettingsChanged, kOutputPortIndex, 0, NULL);
+            mOutputPortSettingsChange = AWAITING_DISABLED;
+            *portWillReset = true;
+        } else {
+            updatePortDefinitions(updateCrop);
+            notify(OMX_EventPortSettingsChanged, kOutputPortIndex,
+                   OMX_IndexConfigCommonOutputCrop, NULL);
+        }
+    }
+}
+
+void SoftVideoDecoderOMXComponent::copyYV12FrameToOutputBuffer(
+        uint8_t *dst, const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV,
+        size_t srcYStride, size_t srcUStride, size_t srcVStride) {
+    size_t dstYStride = mIsAdaptive ? mAdaptiveMaxWidth : mWidth;
+    size_t dstUVStride = dstYStride / 2;
+    size_t dstHeight = mIsAdaptive ? mAdaptiveMaxHeight : mHeight;
+
+    for (size_t i = 0; i < dstHeight; ++i) {
+        if (i < mHeight) {
+            memcpy(dst, srcY, mWidth);
+            srcY += srcYStride;
+        }
+        dst += dstYStride;
+    }
+
+    for (size_t i = 0; i < dstHeight / 2; ++i) {
+        if (i < mHeight / 2) {
+            memcpy(dst, srcU, mWidth / 2);
+            srcU += srcUStride;
+        }
+        dst += dstUVStride;
+    }
+
+    for (size_t i = 0; i < dstHeight / 2; ++i) {
+        if (i < mHeight / 2) {
+            memcpy(dst, srcV, mWidth / 2);
+            srcV += srcVStride;
+        }
+        dst += dstUVStride;
+    }
 }
 
 OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalGetParameter(
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp
index 6adcde4..22c4e04 100644
--- a/services/audiopolicy/AudioPolicyManager.cpp
+++ b/services/audiopolicy/AudioPolicyManager.cpp
@@ -64,6 +64,7 @@
 const StringToEnum sDeviceNameToEnumTable[] = {
     STRING_TO_ENUM(AUDIO_DEVICE_OUT_EARPIECE),
     STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPEAKER),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPEAKER_SAFE),
     STRING_TO_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADSET),
     STRING_TO_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
     STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO),
@@ -3824,6 +3825,14 @@
             break;
         }
     }
+
+    /*Filter SPEAKER_SAFE out of results, as AudioService doesn't know about it
+      and doesn't really need to.*/
+    if (devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
+        devices |= AUDIO_DEVICE_OUT_SPEAKER;
+        devices &= ~AUDIO_DEVICE_OUT_SPEAKER_SAFE;
+    }
+
     return devices;
 }
 
@@ -3926,12 +3935,20 @@
             //   the isStreamActive() method only informs about the activity of a stream, not
             //   if it's for local playback. Note also that we use the same delay between both tests
             device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/);
+            //user "safe" speaker if available instead of normal speaker to avoid triggering
+            //other acoustic safety mechanisms for notification
+            if (device == AUDIO_DEVICE_OUT_SPEAKER && (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER_SAFE))
+                device = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
         } else if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
             // while media is playing (or has recently played), use the same device
             device = getDeviceForStrategy(STRATEGY_MEDIA, false /*fromCache*/);
         } else {
             // when media is not playing anymore, fall back on the sonification behavior
             device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/);
+            //user "safe" speaker if available instead of normal speaker to avoid triggering
+            //other acoustic safety mechanisms for notification
+            if (device == AUDIO_DEVICE_OUT_SPEAKER && (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER_SAFE))
+                device = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
         }
 
         break;
@@ -4668,6 +4685,10 @@
         }
     }
 
+    /*SPEAKER_SAFE is an alias of SPEAKER for purposes of volume control*/
+    if (device == AUDIO_DEVICE_OUT_SPEAKER_SAFE)
+        device = AUDIO_DEVICE_OUT_SPEAKER;
+
     ALOGW_IF(popcount(device) != 1,
             "getDeviceForVolume() invalid device combination: %08x",
             device);