Merge "httplive: clear access units before returning from seekTo."
diff --git a/cmds/screenrecord/FrameOutput.h b/cmds/screenrecord/FrameOutput.h
index b8e9e68..bb66e05 100644
--- a/cmds/screenrecord/FrameOutput.h
+++ b/cmds/screenrecord/FrameOutput.h
@@ -34,9 +34,6 @@
         mExtTextureName(0),
         mPixelBuf(NULL)
         {}
-    virtual ~FrameOutput() {
-        delete[] mPixelBuf;
-    }
 
     // Create an "input surface", similar in purpose to a MediaCodec input
     // surface, that the virtual display can send buffers to.  Also configures
@@ -59,6 +56,11 @@
     FrameOutput(const FrameOutput&);
     FrameOutput& operator=(const FrameOutput&);
 
+    // Destruction via RefBase.
+    virtual ~FrameOutput() {
+        delete[] mPixelBuf;
+    }
+
     // (overrides GLConsumer::FrameAvailableListener method)
     virtual void onFrameAvailable();
 
diff --git a/cmds/screenrecord/Overlay.h b/cmds/screenrecord/Overlay.h
index b8473b4..48e48e0 100644
--- a/cmds/screenrecord/Overlay.h
+++ b/cmds/screenrecord/Overlay.h
@@ -47,7 +47,6 @@
         mLastFrameNumber(-1),
         mTotalDroppedFrames(0)
         {}
-    virtual ~Overlay() { assert(mState == UNINITIALIZED || mState == STOPPED); }
 
     // Creates a thread that performs the overlay.  Pass in the surface that
     // output will be sent to.
@@ -71,6 +70,9 @@
     Overlay(const Overlay&);
     Overlay& operator=(const Overlay&);
 
+    // Destruction via RefBase.
+    virtual ~Overlay() { assert(mState == UNINITIALIZED || mState == STOPPED); }
+
     // Draw the initial info screen.
     static void doDrawInfoPage(const EglWindow& window,
             const Program& texRender, TextRenderer& textRenderer);
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 7e9d557..7d23d02 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -746,6 +746,7 @@
 
     bool                    mInUnderrun;            // whether track is currently in underrun state
     String8                 mName;                  // server's name for this IAudioTrack
+    uint32_t                mPausedPosition;
 
 private:
     class DeathNotifier : public IBinder::DeathRecipient {
diff --git a/include/media/nbaio/AudioStreamInSource.h b/include/media/nbaio/AudioStreamInSource.h
index 07d8c89..eaea63c 100644
--- a/include/media/nbaio/AudioStreamInSource.h
+++ b/include/media/nbaio/AudioStreamInSource.h
@@ -43,7 +43,7 @@
 
     // This is an over-estimate, and could dupe the caller into making a blocking read()
     // FIXME Use an audio HAL API to query the buffer filling status when it's available.
-    virtual ssize_t availableToRead() { return mStreamBufferSizeBytes >> mBitShift; }
+    virtual ssize_t availableToRead() { return mStreamBufferSizeBytes / mFrameSize; }
 
     virtual ssize_t read(void *buffer, size_t count);
 
diff --git a/include/media/nbaio/AudioStreamOutSink.h b/include/media/nbaio/AudioStreamOutSink.h
index 7948d40..9949b88 100644
--- a/include/media/nbaio/AudioStreamOutSink.h
+++ b/include/media/nbaio/AudioStreamOutSink.h
@@ -43,7 +43,7 @@
 
     // This is an over-estimate, and could dupe the caller into making a blocking write()
     // FIXME Use an audio HAL API to query the buffer emptying status when it's available.
-    virtual ssize_t availableToWrite() const { return mStreamBufferSizeBytes >> mBitShift; }
+    virtual ssize_t availableToWrite() const { return mStreamBufferSizeBytes / mFrameSize; }
 
     virtual ssize_t write(const void *buffer, size_t count);
 
diff --git a/include/media/nbaio/NBAIO.h b/include/media/nbaio/NBAIO.h
index 56896b9..be0c15b 100644
--- a/include/media/nbaio/NBAIO.h
+++ b/include/media/nbaio/NBAIO.h
@@ -29,6 +29,7 @@
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 #include <media/AudioTimestamp.h>
+#include <system/audio.h>
 
 namespace android {
 
@@ -53,8 +54,12 @@
 // too large, then this decision should be re-visited.
 // Sample rate and channel count are explicit, PCM interleaved 16-bit is assumed.
 struct NBAIO_Format {
+// FIXME make this a class, and change Format_... global methods to class methods
 //private:
-    unsigned    mPacked;
+    unsigned    mSampleRate;
+    unsigned    mChannelCount;
+    audio_format_t  mFormat;
+    size_t      mFrameSize;
 };
 
 extern const NBAIO_Format Format_Invalid;
@@ -62,13 +67,9 @@
 // Return the frame size of an NBAIO_Format in bytes
 size_t Format_frameSize(const NBAIO_Format& format);
 
-// Return the frame size of an NBAIO_Format as a bit shift
-// or -1 if frame size is not a power of 2
-int Format_frameBitShift(const NBAIO_Format& format);
-
 // Convert a sample rate in Hz and channel count to an NBAIO_Format
-// FIXME The sample format is hard-coded to AUDIO_FORMAT_PCM_16_BIT
-NBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount);
+// FIXME rename
+NBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount, audio_format_t format);
 
 // Return the sample rate in Hz of an NBAIO_Format
 unsigned Format_sampleRate(const NBAIO_Format& format);
@@ -126,14 +127,14 @@
 
 protected:
     NBAIO_Port(const NBAIO_Format& format) : mNegotiated(false), mFormat(format),
-                                             mBitShift(Format_frameBitShift(format)) { }
+                                             mFrameSize(Format_frameSize(format)) { }
     virtual ~NBAIO_Port() { }
 
     // Implementations are free to ignore these if they don't need them
 
     bool            mNegotiated;    // mNegotiated implies (mFormat != Format_Invalid)
     NBAIO_Format    mFormat;        // (mFormat != Format_Invalid) does not imply mNegotiated
-    size_t          mBitShift;      // assign in parallel with any assignment to mFormat
+    size_t          mFrameSize;     // assign in parallel with any assignment to mFormat
 };
 
 // Abstract class (interface) representing a non-blocking data sink, for use by a data provider.
diff --git a/include/media/nbaio/SourceAudioBufferProvider.h b/include/media/nbaio/SourceAudioBufferProvider.h
index cdfb6fe..daf6bc3 100644
--- a/include/media/nbaio/SourceAudioBufferProvider.h
+++ b/include/media/nbaio/SourceAudioBufferProvider.h
@@ -41,7 +41,7 @@
 
 private:
     const sp<NBAIO_Source> mSource;     // the wrapped source
-    /*const*/ size_t    mFrameBitShift; // log2(frame size in bytes)
+    /*const*/ size_t    mFrameSize; // frame size in bytes
     void*               mAllocated; // pointer to base of allocated memory
     size_t              mSize;      // size of mAllocated in frames
     size_t              mOffset;    // frame offset within mAllocated of valid data
diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h
index cf5beda..678d642 100644
--- a/include/media/stagefright/MediaDefs.h
+++ b/include/media/stagefright/MediaDefs.h
@@ -38,6 +38,7 @@
 extern const char *MEDIA_MIMETYPE_AUDIO_AAC;
 extern const char *MEDIA_MIMETYPE_AUDIO_QCELP;
 extern const char *MEDIA_MIMETYPE_AUDIO_VORBIS;
+extern const char *MEDIA_MIMETYPE_AUDIO_OPUS;
 extern const char *MEDIA_MIMETYPE_AUDIO_G711_ALAW;
 extern const char *MEDIA_MIMETYPE_AUDIO_G711_MLAW;
 extern const char *MEDIA_MIMETYPE_AUDIO_RAW;
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index db8216b..e862ec3 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -56,6 +56,9 @@
     kKeyD263              = 'd263',  // raw data
     kKeyVorbisInfo        = 'vinf',  // raw data
     kKeyVorbisBooks       = 'vboo',  // raw data
+    kKeyOpusHeader        = 'ohdr',  // raw data
+    kKeyOpusCodecDelay    = 'ocod',  // uint64_t (codec delay in ns)
+    kKeyOpusSeekPreRoll   = 'ospr',  // uint64_t (seek preroll in ns)
     kKeyWantsNALFragments = 'NALf',
     kKeyIsSyncFrame       = 'sync',  // int32_t (bool)
     kKeyIsCodecConfig     = 'conf',  // int32_t (bool)
diff --git a/media/libeffects/downmix/EffectDownmix.c b/media/libeffects/downmix/EffectDownmix.c
index d25dc9b..a39d837 100644
--- a/media/libeffects/downmix/EffectDownmix.c
+++ b/media/libeffects/downmix/EffectDownmix.c
@@ -699,7 +699,7 @@
  *
  *----------------------------------------------------------------------------
  */
-int Downmix_setParameter(downmix_object_t *pDownmixer, int32_t param, size_t size, void *pValue) {
+int Downmix_setParameter(downmix_object_t *pDownmixer, int32_t param, uint32_t size, void *pValue) {
 
     int16_t value16;
     ALOGV("Downmix_setParameter, context %p, param %d, value16 %d, value32 %d",
@@ -709,7 +709,7 @@
 
       case DOWNMIX_PARAM_TYPE:
         if (size != sizeof(downmix_type_t)) {
-            ALOGE("Downmix_setParameter(DOWNMIX_PARAM_TYPE) invalid size %zu, should be %zu",
+            ALOGE("Downmix_setParameter(DOWNMIX_PARAM_TYPE) invalid size %u, should be %zu",
                     size, sizeof(downmix_type_t));
             return -EINVAL;
         }
@@ -755,7 +755,7 @@
  *
  *----------------------------------------------------------------------------
  */
-int Downmix_getParameter(downmix_object_t *pDownmixer, int32_t param, size_t *pSize, void *pValue) {
+int Downmix_getParameter(downmix_object_t *pDownmixer, int32_t param, uint32_t *pSize, void *pValue) {
     int16_t *pValue16;
 
     switch (param) {
diff --git a/media/libeffects/downmix/EffectDownmix.h b/media/libeffects/downmix/EffectDownmix.h
index cb6b957..fcb3c9e 100644
--- a/media/libeffects/downmix/EffectDownmix.h
+++ b/media/libeffects/downmix/EffectDownmix.h
@@ -93,8 +93,8 @@
 int Downmix_Init(downmix_module_t *pDwmModule);
 int Downmix_Configure(downmix_module_t *pDwmModule, effect_config_t *pConfig, bool init);
 int Downmix_Reset(downmix_object_t *pDownmixer, bool init);
-int Downmix_setParameter(downmix_object_t *pDownmixer, int32_t param, size_t size, void *pValue);
-int Downmix_getParameter(downmix_object_t *pDownmixer, int32_t param, size_t *pSize, void *pValue);
+int Downmix_setParameter(downmix_object_t *pDownmixer, int32_t param, uint32_t size, void *pValue);
+int Downmix_getParameter(downmix_object_t *pDownmixer, int32_t param, uint32_t *pSize, void *pValue);
 
 void Downmix_foldFromQuad(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
 void Downmix_foldFromSurround(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c
index 32c4ce0..35e5bc8 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c
@@ -178,7 +178,7 @@
             {
                 return(LVDBE_NULLADDRESS);
             }
-            if (((LVM_UINT32)pMemoryTable->Region[i].pBaseAddress % pMemoryTable->Region[i].Alignment)!=0){
+            if (((uintptr_t)pMemoryTable->Region[i].pBaseAddress % pMemoryTable->Region[i].Alignment)!=0){
                 return(LVDBE_ALIGNMENTERROR);
             }
         }
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c
index 794271b..f5a01f3 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c
@@ -99,7 +99,7 @@
         /*
          * Check the buffer alignment
          */
-        if((((LVM_UINT32)pInData % 4) != 0) || (((LVM_UINT32)pOutData % 4) != 0))
+        if((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0))
         {
             return(LVM_ALIGNMENTERROR);
         }
diff --git a/media/libeffects/lvm/lib/Common/lib/InstAlloc.h b/media/libeffects/lvm/lib/Common/lib/InstAlloc.h
index c6954f2..7f725f4 100644
--- a/media/libeffects/lvm/lib/Common/lib/InstAlloc.h
+++ b/media/libeffects/lvm/lib/Common/lib/InstAlloc.h
@@ -29,7 +29,7 @@
 typedef struct
 {
     LVM_UINT32              TotalSize;      /*  Accumulative total memory size                      */
-    LVM_UINT32              pNextMember;    /*  Pointer to the next instance member to be allocated */
+    uintptr_t               pNextMember;    /*  Pointer to the next instance member to be allocated */
 }   INST_ALLOC;
 
 
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
index 81655dd..0c6fb25 100644
--- a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
@@ -29,6 +29,7 @@
 extern "C" {
 #endif /* __cplusplus */
 
+#include <stdint.h>
 
 /****************************************************************************************/
 /*                                                                                      */
@@ -85,14 +86,14 @@
 
 typedef     char                LVM_CHAR;           /* ASCII character */
 
-typedef     char                LVM_INT8;           /* Signed 8-bit word */
-typedef     unsigned char       LVM_UINT8;          /* Unsigned 8-bit word */
+typedef     int8_t              LVM_INT8;           /* Signed 8-bit word */
+typedef     uint8_t             LVM_UINT8;          /* Unsigned 8-bit word */
 
-typedef     short               LVM_INT16;          /* Signed 16-bit word */
-typedef     unsigned short      LVM_UINT16;         /* Unsigned 16-bit word */
+typedef     int16_t             LVM_INT16;          /* Signed 16-bit word */
+typedef     uint16_t            LVM_UINT16;         /* Unsigned 16-bit word */
 
-typedef     long                LVM_INT32;          /* Signed 32-bit word */
-typedef     unsigned long       LVM_UINT32;         /* Unsigned 32-bit word */
+typedef     int32_t             LVM_INT32;          /* Signed 32-bit word */
+typedef     uint32_t            LVM_UINT32;         /* Unsigned 32-bit word */
 
 
 /****************************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/InstAlloc.c b/media/libeffects/lvm/lib/Common/src/InstAlloc.c
index 481df84..a89a5c3 100644
--- a/media/libeffects/lvm/lib/Common/src/InstAlloc.c
+++ b/media/libeffects/lvm/lib/Common/src/InstAlloc.c
@@ -30,7 +30,7 @@
                         void            *StartAddr )
 {
     pms->TotalSize = 3;
-    pms->pNextMember = (LVM_UINT32)(((LVM_UINT32)StartAddr + 3) & 0xFFFFFFFC);/* This code will fail if the platform address space is more than 32-bits*/
+    pms->pNextMember = (((uintptr_t)StartAddr + 3) & (uintptr_t)~3);
 }
 
 
@@ -51,7 +51,7 @@
     void *NewMemberAddress; /* Variable to temporarily store the return value */
     NewMemberAddress = (void*)pms->pNextMember;
 
-    Size = ((Size + 3) & 0xFFFFFFFC); /* Ceil the size to a multiple of four */
+    Size = ((Size + 3) & (LVM_UINT32)~3); /* Ceil the size to a multiple of four */
 
     pms->TotalSize += Size;
     pms->pNextMember += Size;
@@ -84,30 +84,30 @@
 void    InstAlloc_InitAll( INST_ALLOC                      *pms,
                            LVM_MemoryTable_st             *pMemoryTable)
 {
-    LVM_UINT32 StartAddr;
+    uintptr_t StartAddr;
 
-    StartAddr = (LVM_UINT32)pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress;
+    StartAddr = (uintptr_t)pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress;
 
     pms[0].TotalSize = 3;
-    pms[0].pNextMember = (LVM_UINT32)(((LVM_UINT32)StartAddr + 3) & 0xFFFFFFFC);
+    pms[0].pNextMember = ((StartAddr + 3) & (uintptr_t)~3);
 
 
-    StartAddr = (LVM_UINT32)pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress;
+    StartAddr = (uintptr_t)pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress;
 
     pms[1].TotalSize = 3;
-    pms[1].pNextMember = (LVM_UINT32)(((LVM_UINT32)StartAddr + 3) & 0xFFFFFFFC);
+    pms[1].pNextMember = ((StartAddr + 3) & (uintptr_t)~3);
 
 
-    StartAddr = (LVM_UINT32)pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress;
+    StartAddr = (uintptr_t)pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress;
 
     pms[2].TotalSize = 3;
-    pms[2].pNextMember = (LVM_UINT32)(((LVM_UINT32)StartAddr + 3) & 0xFFFFFFFC);
+    pms[2].pNextMember = ((StartAddr + 3) & (uintptr_t)~3);
 
 
-    StartAddr = (LVM_UINT32)pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress;
+    StartAddr = (uintptr_t)pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress;
 
     pms[3].TotalSize = 3;
-    pms[3].pNextMember = (LVM_UINT32)(((LVM_UINT32)StartAddr + 3) & 0xFFFFFFFC);
+    pms[3].pNextMember = ((StartAddr + 3) & (uintptr_t)~3);
 
 }
 
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c
index ac3c740..58f58ed 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c
@@ -77,7 +77,7 @@
     }
 
     /* Check if the input and output data buffers are 32-bit aligned */
-    if ((((LVM_INT32)pInData % 4) != 0) || (((LVM_INT32)pOutData % 4) != 0))
+    if ((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0))
     {
         return LVEQNB_ALIGNMENTERROR;
     }
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 58d7767..db5c78f 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -2813,9 +2813,9 @@
 
             if(pContext->EffectType == LVM_BASS_BOOST){
                 if (pCmdData == NULL ||
-                        cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+                        cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)) ||
                         pReplyData == NULL ||
-                        *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))){
+                        *replySize < (sizeof(effect_param_t) + sizeof(int32_t))){
                     ALOGV("\tLVM_ERROR : BassBoost_command cmdCode Case: "
                             "EFFECT_CMD_GET_PARAM: ERROR");
                     return -EINVAL;
@@ -2844,9 +2844,9 @@
 
             if(pContext->EffectType == LVM_VIRTUALIZER){
                 if (pCmdData == NULL ||
-                        cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+                        cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)) ||
                         pReplyData == NULL ||
-                        *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))){
+                        *replySize < (sizeof(effect_param_t) + sizeof(int32_t))){
                     ALOGV("\tLVM_ERROR : Virtualizer_command cmdCode Case: "
                             "EFFECT_CMD_GET_PARAM: ERROR");
                     return -EINVAL;
@@ -2876,7 +2876,7 @@
                 //ALOGV("\tEqualizer_command cmdCode Case: "
                 //        "EFFECT_CMD_GET_PARAM start");
                 if (pCmdData == NULL ||
-                    cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+                    cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)) ||
                     pReplyData == NULL ||
                     *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))) {
                     ALOGV("\tLVM_ERROR : Equalizer_command cmdCode Case: "
@@ -2908,7 +2908,7 @@
             if(pContext->EffectType == LVM_VOLUME){
                 //ALOGV("\tVolume_command cmdCode Case: EFFECT_CMD_GET_PARAM start");
                 if (pCmdData == NULL ||
-                        cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+                        cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)) ||
                         pReplyData == NULL ||
                         *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))){
                     ALOGV("\tLVM_ERROR : Volume_command cmdCode Case: "
@@ -2947,7 +2947,7 @@
                 //       *(int16_t *)((char *)pCmdData + sizeof(effect_param_t) + sizeof(int32_t)));
 
                 if (pCmdData   == NULL||
-                    cmdSize    != (int)(sizeof(effect_param_t) + sizeof(int32_t) +sizeof(int16_t))||
+                    cmdSize    != (sizeof(effect_param_t) + sizeof(int32_t) +sizeof(int16_t))||
                     pReplyData == NULL||
                     *replySize != sizeof(int32_t)){
                     ALOGV("\tLVM_ERROR : BassBoost_command cmdCode Case: "
@@ -2980,7 +2980,7 @@
               //        *(int16_t *)((char *)pCmdData + sizeof(effect_param_t) + sizeof(int32_t)));
 
                 if (pCmdData   == NULL||
-                    cmdSize    != (int)(sizeof(effect_param_t) + sizeof(int32_t) +sizeof(int16_t))||
+                    cmdSize    != (sizeof(effect_param_t) + sizeof(int32_t) +sizeof(int16_t))||
                     pReplyData == NULL||
                     *replySize != sizeof(int32_t)){
                     ALOGV("\tLVM_ERROR : Virtualizer_command cmdCode Case: "
@@ -3014,7 +3014,7 @@
                //        *replySize,
                //        *(int16_t *)((char *)pCmdData + sizeof(effect_param_t) + sizeof(int32_t)));
 
-                if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+                if (pCmdData == NULL || cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)) ||
                     pReplyData == NULL || *replySize != sizeof(int32_t)) {
                     ALOGV("\tLVM_ERROR : Equalizer_command cmdCode Case: "
                             "EFFECT_CMD_SET_PARAM: ERROR");
@@ -3034,7 +3034,7 @@
                 //        *(int16_t *)((char *)pCmdData + sizeof(effect_param_t) +sizeof(int32_t)));
 
                 if (    pCmdData   == NULL||
-                        cmdSize    < (int)(sizeof(effect_param_t) + sizeof(int32_t))||
+                        cmdSize    < (sizeof(effect_param_t) + sizeof(int32_t))||
                         pReplyData == NULL||
                         *replySize != sizeof(int32_t)){
                     ALOGV("\tLVM_ERROR : Volume_command cmdCode Case: "
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index 0367302..c6d3759 100644
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -181,7 +181,7 @@
 int  Reverb_setParameter    (ReverbContext *pContext, void *pParam, void *pValue);
 int  Reverb_getParameter    (ReverbContext *pContext,
                              void          *pParam,
-                             size_t        *pValueSize,
+                             uint32_t      *pValueSize,
                              void          *pValue);
 int Reverb_LoadPreset       (ReverbContext   *pContext);
 
@@ -1534,7 +1534,7 @@
 
 int Reverb_getParameter(ReverbContext *pContext,
                         void          *pParam,
-                        size_t        *pValueSize,
+                        uint32_t      *pValueSize,
                         void          *pValue){
     int status = 0;
     int32_t *pParamTemp = (int32_t *)pParam;
@@ -1956,9 +1956,9 @@
             //ALOGV("\tReverb_command cmdCode Case: "
             //        "EFFECT_CMD_GET_PARAM start");
             if (pCmdData == NULL ||
-                    cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+                    cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)) ||
                     pReplyData == NULL ||
-                    *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))){
+                    *replySize < (sizeof(effect_param_t) + sizeof(int32_t))){
                 ALOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
                         "EFFECT_CMD_GET_PARAM: ERROR");
                 return -EINVAL;
@@ -1973,7 +1973,7 @@
 
             p->status = android::Reverb_getParameter(pContext,
                                                          (void *)p->data,
-                                                         (size_t  *)&p->vsize,
+                                                          &p->vsize,
                                                           p->data + voffset);
 
             *replySize = sizeof(effect_param_t) + voffset + p->vsize;
@@ -1994,8 +1994,8 @@
             //        *replySize,
             //        *(int16_t *)((char *)pCmdData + sizeof(effect_param_t) + sizeof(int32_t)));
 
-            if (pCmdData == NULL || (cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)))
-                    || pReplyData == NULL || *replySize != (int)sizeof(int32_t)) {
+            if (pCmdData == NULL || (cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)))
+                    || pReplyData == NULL || *replySize != sizeof(int32_t)) {
                 ALOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
                         "EFFECT_CMD_SET_PARAM: ERROR");
                 return -EINVAL;
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index c56ff72..a96a703 100644
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -77,7 +77,7 @@
     void (* enable)(preproc_effect_t *fx);
     void (* disable)(preproc_effect_t *fx);
     int (* set_parameter)(preproc_effect_t *fx, void *param, void *value);
-    int (* get_parameter)(preproc_effect_t *fx, void *param, size_t *size, void *value);
+    int (* get_parameter)(preproc_effect_t *fx, void *param, uint32_t *size, void *value);
     int (* set_device)(preproc_effect_t *fx, uint32_t device);
 };
 
@@ -291,7 +291,7 @@
 
 int AgcGetParameter(preproc_effect_t *effect,
                     void *pParam,
-                    size_t *pValueSize,
+                    uint32_t *pValueSize,
                     void *pValue)
 {
     int status = 0;
@@ -452,9 +452,9 @@
     return 0;
 }
 
-int AecGetParameter(preproc_effect_t     *effect,
+int AecGetParameter(preproc_effect_t  *effect,
                     void              *pParam,
-                    size_t            *pValueSize,
+                    uint32_t          *pValueSize,
                     void              *pValue)
 {
     int status = 0;
@@ -575,9 +575,9 @@
     return 0;
 }
 
-int NsGetParameter(preproc_effect_t     *effect,
+int NsGetParameter(preproc_effect_t  *effect,
                    void              *pParam,
-                   size_t            *pValueSize,
+                   uint32_t          *pValueSize,
                    void              *pValue)
 {
     int status = 0;
@@ -1453,7 +1453,7 @@
 
             if (effect->ops->get_parameter) {
                 p->status = effect->ops->get_parameter(effect, p->data,
-                                                       (size_t  *)&p->vsize,
+                                                       &p->vsize,
                                                        p->data + voffset);
                 *replySize = sizeof(effect_param_t) + voffset + p->vsize;
             }
diff --git a/media/libeffects/testlibs/EffectEqualizer.cpp b/media/libeffects/testlibs/EffectEqualizer.cpp
index 8d00206..3cb13f2 100644
--- a/media/libeffects/testlibs/EffectEqualizer.cpp
+++ b/media/libeffects/testlibs/EffectEqualizer.cpp
@@ -115,7 +115,7 @@
 
 int Equalizer_init(EqualizerContext *pContext);
 int Equalizer_setConfig(EqualizerContext *pContext, effect_config_t *pConfig);
-int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, size_t *pValueSize, void *pValue);
+int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, uint32_t *pValueSize, void *pValue);
 int Equalizer_setParameter(AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue);
 
 
@@ -360,7 +360,7 @@
 //
 //----------------------------------------------------------------------------
 
-int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, size_t *pValueSize, void *pValue)
+int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, uint32_t *pValueSize, void *pValue)
 {
     int status = 0;
     int32_t param = *pParam++;
@@ -662,8 +662,8 @@
         Equalizer_setConfig(pContext, &pContext->config);
         break;
     case EFFECT_CMD_GET_PARAM: {
-        if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
-            pReplyData == NULL || *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))) {
+        if (pCmdData == NULL || cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)) ||
+            pReplyData == NULL || *replySize < (sizeof(effect_param_t) + sizeof(int32_t))) {
             return -EINVAL;
         }
         effect_param_t *p = (effect_param_t *)pCmdData;
@@ -682,7 +682,7 @@
     case EFFECT_CMD_SET_PARAM: {
         ALOGV("Equalizer_command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, pReplyData %p",
              cmdSize, pCmdData, *replySize, pReplyData);
-        if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+        if (pCmdData == NULL || cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)) ||
             pReplyData == NULL || *replySize != sizeof(int32_t)) {
             return -EINVAL;
         }
diff --git a/media/libeffects/testlibs/EffectReverb.c b/media/libeffects/testlibs/EffectReverb.c
index c37f392..f056d19 100644
--- a/media/libeffects/testlibs/EffectReverb.c
+++ b/media/libeffects/testlibs/EffectReverb.c
@@ -750,7 +750,7 @@
  *
  *----------------------------------------------------------------------------
  */
-int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, size_t *pSize,
+int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, uint32_t *pSize,
         void *pValue) {
     int32_t *pValue32;
     int16_t *pValue16;
@@ -758,7 +758,7 @@
     int32_t i;
     int32_t temp;
     int32_t temp2;
-    size_t size;
+    uint32_t size;
 
     if (pReverb->m_Preset) {
         if (param != REVERB_PARAM_PRESET || *pSize < sizeof(int16_t)) {
@@ -1033,7 +1033,7 @@
  *
  *----------------------------------------------------------------------------
  */
-int Reverb_setParameter(reverb_object_t *pReverb, int32_t param, size_t size,
+int Reverb_setParameter(reverb_object_t *pReverb, int32_t param, uint32_t size,
         void *pValue) {
     int32_t value32;
     int16_t value16;
@@ -1044,7 +1044,7 @@
     reverb_preset_t *pPreset;
     int maxSamples;
     int32_t averageDelay;
-    size_t paramSize;
+    uint32_t paramSize;
 
     ALOGV("Reverb_setParameter, context %p, param %d, value16 %d, value32 %d",
             pReverb, param, *(int16_t *)pValue, *(int32_t *)pValue);
diff --git a/media/libeffects/testlibs/EffectReverb.h b/media/libeffects/testlibs/EffectReverb.h
index e5248fe..756c5ea 100644
--- a/media/libeffects/testlibs/EffectReverb.h
+++ b/media/libeffects/testlibs/EffectReverb.h
@@ -330,8 +330,8 @@
 void Reverb_getConfig(reverb_module_t *pRvbModule, effect_config_t *pConfig);
 void Reverb_Reset(reverb_object_t *pReverb, bool init);
 
-int Reverb_setParameter (reverb_object_t *pReverb, int32_t param, size_t size, void *pValue);
-int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, size_t *pSize, void *pValue);
+int Reverb_setParameter (reverb_object_t *pReverb, int32_t param, uint32_t size, void *pValue);
+int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, uint32_t *pSize, void *pValue);
 
 /*----------------------------------------------------------------------------
  * ReverbUpdateXfade
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index d25c40b..3217171 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -99,7 +99,8 @@
     : mStatus(NO_INIT),
       mIsTimed(false),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
-      mPreviousSchedulingGroup(SP_DEFAULT)
+      mPreviousSchedulingGroup(SP_DEFAULT),
+      mPausedPosition(0)
 {
 }
 
@@ -121,7 +122,8 @@
     : mStatus(NO_INIT),
       mIsTimed(false),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
-      mPreviousSchedulingGroup(SP_DEFAULT)
+      mPreviousSchedulingGroup(SP_DEFAULT),
+      mPausedPosition(0)
 {
     mStatus = set(streamType, sampleRate, format, channelMask,
             frameCount, flags, cbf, user, notificationFrames,
@@ -147,7 +149,8 @@
     : mStatus(NO_INIT),
       mIsTimed(false),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
-      mPreviousSchedulingGroup(SP_DEFAULT)
+      mPreviousSchedulingGroup(SP_DEFAULT),
+      mPausedPosition(0)
 {
     mStatus = set(streamType, sampleRate, format, channelMask,
             0 /*frameCount*/, flags, cbf, user, notificationFrames,
@@ -551,6 +554,16 @@
     }
     mProxy->interrupt();
     mAudioTrack->pause();
+
+    if (isOffloaded()) {
+        if (mOutput != 0) {
+            uint32_t halFrames;
+            // OffloadThread sends HAL pause in its threadLoop.. time saved
+            // here can be slightly off
+            AudioSystem::getRenderPosition(mOutput, &halFrames, &mPausedPosition);
+            ALOGV("AudioTrack::pause for offload, cache current position %u", mPausedPosition);
+        }
+    }
 }
 
 status_t AudioTrack::setVolume(float left, float right)
@@ -770,6 +783,12 @@
     if (isOffloaded_l()) {
         uint32_t dspFrames = 0;
 
+        if ((mState == STATE_PAUSED) || (mState == STATE_PAUSED_STOPPING)) {
+            ALOGV("getPosition called in paused state, return cached position %u", mPausedPosition);
+            *position = mPausedPosition;
+            return NO_ERROR;
+        }
+
         if (mOutput != 0) {
             uint32_t halFrames;
             AudioSystem::getRenderPosition(mOutput, &halFrames, &dspFrames);
@@ -1488,6 +1507,7 @@
     }
     size_t misalignment = mProxy->getMisalignment();
     uint32_t sequence = mSequence;
+    sp<AudioTrackClientProxy> proxy = mProxy;
 
     // These fields don't need to be cached, because they are assigned only by set():
     //     mTransfer, mCbf, mUserData, mFormat, mFrameSize, mFrameSizeAF, mFlags
@@ -1496,35 +1516,32 @@
     mLock.unlock();
 
     if (waitStreamEnd) {
-        AutoMutex lock(mLock);
-
-        sp<AudioTrackClientProxy> proxy = mProxy;
-        sp<IMemory> iMem = mCblkMemory;
-
         struct timespec timeout;
         timeout.tv_sec = WAIT_STREAM_END_TIMEOUT_SEC;
         timeout.tv_nsec = 0;
 
-        mLock.unlock();
-        status_t status = mProxy->waitStreamEndDone(&timeout);
-        mLock.lock();
+        status_t status = proxy->waitStreamEndDone(&timeout);
         switch (status) {
         case NO_ERROR:
         case DEAD_OBJECT:
         case TIMED_OUT:
-            mLock.unlock();
             mCbf(EVENT_STREAM_END, mUserData, NULL);
-            mLock.lock();
-            if (mState == STATE_STOPPING) {
-                mState = STATE_STOPPED;
-                if (status != DEAD_OBJECT) {
-                   return NS_INACTIVE;
+            {
+                AutoMutex lock(mLock);
+                // The previously assigned value of waitStreamEnd is no longer valid,
+                // since the mutex has been unlocked and either the callback handler
+                // or another thread could have re-started the AudioTrack during that time.
+                waitStreamEnd = mState == STATE_STOPPING;
+                if (waitStreamEnd) {
+                    mState = STATE_STOPPED;
                 }
             }
-            return 0;
-        default:
-            return 0;
+            if (waitStreamEnd && status != DEAD_OBJECT) {
+               return NS_INACTIVE;
+            }
+            break;
         }
+        return 0;
     }
 
     // perform callbacks while unlocked
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 4be3c09..1a027a6 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -476,10 +476,11 @@
         case START_OUTPUT: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32());
-            uint32_t stream = data.readInt32();
+            audio_stream_type_t stream =
+                                static_cast <audio_stream_type_t>(data.readInt32());
             int session = data.readInt32();
             reply->writeInt32(static_cast <uint32_t>(startOutput(output,
-                                                                 (audio_stream_type_t)stream,
+                                                                 stream,
                                                                  session)));
             return NO_ERROR;
         } break;
@@ -487,10 +488,11 @@
         case STOP_OUTPUT: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32());
-            uint32_t stream = data.readInt32();
+            audio_stream_type_t stream =
+                                static_cast <audio_stream_type_t>(data.readInt32());
             int session = data.readInt32();
             reply->writeInt32(static_cast <uint32_t>(stopOutput(output,
-                                                                (audio_stream_type_t)stream,
+                                                                stream,
                                                                 session)));
             return NO_ERROR;
         } break;
@@ -633,7 +635,7 @@
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             audio_stream_type_t stream = (audio_stream_type_t) data.readInt32();
             uint32_t inPastMs = (uint32_t)data.readInt32();
-            reply->writeInt32( isStreamActive((audio_stream_type_t) stream, inPastMs) );
+            reply->writeInt32( isStreamActive(stream, inPastMs) );
             return NO_ERROR;
         } break;
 
@@ -641,7 +643,7 @@
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             audio_stream_type_t stream = (audio_stream_type_t) data.readInt32();
             uint32_t inPastMs = (uint32_t)data.readInt32();
-            reply->writeInt32( isStreamActiveRemotely((audio_stream_type_t) stream, inPastMs) );
+            reply->writeInt32( isStreamActiveRemotely(stream, inPastMs) );
             return NO_ERROR;
         } break;
 
diff --git a/media/libnbaio/AudioBufferProviderSource.cpp b/media/libnbaio/AudioBufferProviderSource.cpp
index 4a69104..551f516 100644
--- a/media/libnbaio/AudioBufferProviderSource.cpp
+++ b/media/libnbaio/AudioBufferProviderSource.cpp
@@ -68,7 +68,7 @@
     }
     // count could be zero, either because count was zero on entry or
     // available is zero, but both are unlikely so don't check for that
-    memcpy(buffer, (char *) mBuffer.raw + (mConsumed << mBitShift), count << mBitShift);
+    memcpy(buffer, (char *) mBuffer.raw + (mConsumed * mFrameSize), count * mFrameSize);
     if (CC_UNLIKELY((mConsumed += count) >= mBuffer.frameCount)) {
         mProvider->releaseBuffer(&mBuffer);
         mBuffer.raw = NULL;
@@ -120,7 +120,7 @@
             count = available;
         }
         if (CC_LIKELY(count > 0)) {
-            char* readTgt = (char *) mBuffer.raw + (mConsumed << mBitShift);
+            char* readTgt = (char *) mBuffer.raw + (mConsumed * mFrameSize);
             ssize_t ret = via(user, readTgt, count, readPTS);
             if (CC_UNLIKELY(ret <= 0)) {
                 if (CC_LIKELY(accumulator > 0)) {
diff --git a/media/libnbaio/AudioStreamInSource.cpp b/media/libnbaio/AudioStreamInSource.cpp
index ae8fac8..80bf61a 100644
--- a/media/libnbaio/AudioStreamInSource.cpp
+++ b/media/libnbaio/AudioStreamInSource.cpp
@@ -43,13 +43,11 @@
     if (!Format_isValid(mFormat)) {
         mStreamBufferSizeBytes = mStream->common.get_buffer_size(&mStream->common);
         audio_format_t streamFormat = mStream->common.get_format(&mStream->common);
-        if (streamFormat == AUDIO_FORMAT_PCM_16_BIT) {
-            uint32_t sampleRate = mStream->common.get_sample_rate(&mStream->common);
-            audio_channel_mask_t channelMask =
-                    (audio_channel_mask_t) mStream->common.get_channels(&mStream->common);
-            mFormat = Format_from_SR_C(sampleRate, popcount(channelMask));
-            mBitShift = Format_frameBitShift(mFormat);
-        }
+        uint32_t sampleRate = mStream->common.get_sample_rate(&mStream->common);
+        audio_channel_mask_t channelMask =
+                (audio_channel_mask_t) mStream->common.get_channels(&mStream->common);
+        mFormat = Format_from_SR_C(sampleRate, popcount(channelMask), streamFormat);
+        mFrameSize = Format_frameSize(mFormat);
     }
     return NBAIO_Source::negotiate(offers, numOffers, counterOffers, numCounterOffers);
 }
@@ -70,9 +68,9 @@
     if (CC_UNLIKELY(!Format_isValid(mFormat))) {
         return NEGOTIATE;
     }
-    ssize_t bytesRead = mStream->read(mStream, buffer, count << mBitShift);
+    ssize_t bytesRead = mStream->read(mStream, buffer, count * mFrameSize);
     if (bytesRead > 0) {
-        size_t framesRead = bytesRead >> mBitShift;
+        size_t framesRead = bytesRead / mFrameSize;
         mFramesRead += framesRead;
         return framesRead;
     } else {
diff --git a/media/libnbaio/AudioStreamOutSink.cpp b/media/libnbaio/AudioStreamOutSink.cpp
index aa9810e..c28d34d 100644
--- a/media/libnbaio/AudioStreamOutSink.cpp
+++ b/media/libnbaio/AudioStreamOutSink.cpp
@@ -40,13 +40,11 @@
     if (!Format_isValid(mFormat)) {
         mStreamBufferSizeBytes = mStream->common.get_buffer_size(&mStream->common);
         audio_format_t streamFormat = mStream->common.get_format(&mStream->common);
-        if (streamFormat == AUDIO_FORMAT_PCM_16_BIT) {
-            uint32_t sampleRate = mStream->common.get_sample_rate(&mStream->common);
-            audio_channel_mask_t channelMask =
-                    (audio_channel_mask_t) mStream->common.get_channels(&mStream->common);
-            mFormat = Format_from_SR_C(sampleRate, popcount(channelMask));
-            mBitShift = Format_frameBitShift(mFormat);
-        }
+        uint32_t sampleRate = mStream->common.get_sample_rate(&mStream->common);
+        audio_channel_mask_t channelMask =
+                (audio_channel_mask_t) mStream->common.get_channels(&mStream->common);
+        mFormat = Format_from_SR_C(sampleRate, popcount(channelMask), streamFormat);
+        mFrameSize = Format_frameSize(mFormat);
     }
     return NBAIO_Sink::negotiate(offers, numOffers, counterOffers, numCounterOffers);
 }
@@ -57,9 +55,9 @@
         return NEGOTIATE;
     }
     ALOG_ASSERT(Format_isValid(mFormat));
-    ssize_t ret = mStream->write(mStream, buffer, count << mBitShift);
+    ssize_t ret = mStream->write(mStream, buffer, count * mFrameSize);
     if (ret > 0) {
-        ret >>= mBitShift;
+        ret /= mFrameSize;
         mFramesWritten += ret;
     } else {
         // FIXME verify HAL implementations are returning the correct error codes e.g. WOULD_BLOCK
diff --git a/media/libnbaio/MonoPipe.cpp b/media/libnbaio/MonoPipe.cpp
index b23967b..9c8461c 100644
--- a/media/libnbaio/MonoPipe.cpp
+++ b/media/libnbaio/MonoPipe.cpp
@@ -115,11 +115,11 @@
             part1 = written;
         }
         if (CC_LIKELY(part1 > 0)) {
-            memcpy((char *) mBuffer + (rear << mBitShift), buffer, part1 << mBitShift);
+            memcpy((char *) mBuffer + (rear * mFrameSize), buffer, part1 * mFrameSize);
             if (CC_UNLIKELY(rear + part1 == mMaxFrames)) {
                 size_t part2 = written - part1;
                 if (CC_LIKELY(part2 > 0)) {
-                    memcpy(mBuffer, (char *) buffer + (part1 << mBitShift), part2 << mBitShift);
+                    memcpy(mBuffer, (char *) buffer + (part1 * mFrameSize), part2 * mFrameSize);
                 }
             }
             android_atomic_release_store(written + mRear, &mRear);
@@ -129,7 +129,7 @@
             break;
         }
         count -= written;
-        buffer = (char *) buffer + (written << mBitShift);
+        buffer = (char *) buffer + (written * mFrameSize);
         // Simulate blocking I/O by sleeping at different rates, depending on a throttle.
         // The throttle tries to keep the mean pipe depth near the setpoint, with a slight jitter.
         uint32_t ns;
diff --git a/media/libnbaio/MonoPipeReader.cpp b/media/libnbaio/MonoPipeReader.cpp
index 851341a..de82229 100644
--- a/media/libnbaio/MonoPipeReader.cpp
+++ b/media/libnbaio/MonoPipeReader.cpp
@@ -73,11 +73,11 @@
         part1 = red;
     }
     if (CC_LIKELY(part1 > 0)) {
-        memcpy(buffer, (char *) mPipe->mBuffer + (front << mBitShift), part1 << mBitShift);
+        memcpy(buffer, (char *) mPipe->mBuffer + (front * mFrameSize), part1 * mFrameSize);
         if (CC_UNLIKELY(front + part1 == mPipe->mMaxFrames)) {
             size_t part2 = red - part1;
             if (CC_LIKELY(part2 > 0)) {
-                memcpy((char *) buffer + (part1 << mBitShift), mPipe->mBuffer, part2 << mBitShift);
+                memcpy((char *) buffer + (part1 * mFrameSize), mPipe->mBuffer, part2 * mFrameSize);
             }
         }
         mPipe->updateFrontAndNRPTS(red + mPipe->mFront, nextReadPTS);
diff --git a/media/libnbaio/NBAIO.cpp b/media/libnbaio/NBAIO.cpp
index 51514de..ff3284c 100644
--- a/media/libnbaio/NBAIO.cpp
+++ b/media/libnbaio/NBAIO.cpp
@@ -24,63 +24,17 @@
 
 size_t Format_frameSize(const NBAIO_Format& format)
 {
-    // FIXME The sample format is hard-coded to AUDIO_FORMAT_PCM_16_BIT
-    return Format_channelCount(format) * sizeof(short);
+    return format.mFrameSize;
 }
 
-int Format_frameBitShift(const NBAIO_Format& format)
-{
-    // FIXME The sample format is hard-coded to AUDIO_FORMAT_PCM_16_BIT
-    // sizeof(short) == 2, so frame size == 1 << channels
-    return Format_channelCount(format);
-    // FIXME must return -1 for non-power of 2
-}
-
-const NBAIO_Format Format_Invalid = { 0 };
-
-enum {
-    Format_SR_8000,
-    Format_SR_11025,
-    Format_SR_16000,
-    Format_SR_22050,
-    Format_SR_24000,
-    Format_SR_32000,
-    Format_SR_44100,
-    Format_SR_48000,
-    Format_SR_Mask = 7
-};
-
-enum {
-    Format_C_1 = 0x08,
-    Format_C_2 = 0x10,
-    Format_C_Mask = 0x18
-};
+const NBAIO_Format Format_Invalid = { 0, 0, AUDIO_FORMAT_INVALID, 0 };
 
 unsigned Format_sampleRate(const NBAIO_Format& format)
 {
     if (!Format_isValid(format)) {
         return 0;
     }
-    switch (format.mPacked & Format_SR_Mask) {
-    case Format_SR_8000:
-        return 8000;
-    case Format_SR_11025:
-        return 11025;
-    case Format_SR_16000:
-        return 16000;
-    case Format_SR_22050:
-        return 22050;
-    case Format_SR_24000:
-        return 24000;
-    case Format_SR_32000:
-        return 32000;
-    case Format_SR_44100:
-        return 44100;
-    case Format_SR_48000:
-        return 48000;
-    default:
-        return 0;
-    }
+    return format.mSampleRate;
 }
 
 unsigned Format_channelCount(const NBAIO_Format& format)
@@ -88,59 +42,21 @@
     if (!Format_isValid(format)) {
         return 0;
     }
-    switch (format.mPacked & Format_C_Mask) {
-    case Format_C_1:
-        return 1;
-    case Format_C_2:
-        return 2;
-    default:
-        return 0;
-    }
+    return format.mChannelCount;
 }
 
-NBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount)
+NBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount,
+        audio_format_t format)
 {
-    unsigned format;
-    switch (sampleRate) {
-    case 8000:
-        format = Format_SR_8000;
-        break;
-    case 11025:
-        format = Format_SR_11025;
-        break;
-    case 16000:
-        format = Format_SR_16000;
-        break;
-    case 22050:
-        format = Format_SR_22050;
-        break;
-    case 24000:
-        format = Format_SR_24000;
-        break;
-    case 32000:
-        format = Format_SR_32000;
-        break;
-    case 44100:
-        format = Format_SR_44100;
-        break;
-    case 48000:
-        format = Format_SR_48000;
-        break;
-    default:
-        return Format_Invalid;
-    }
-    switch (channelCount) {
-    case 1:
-        format |= Format_C_1;
-        break;
-    case 2:
-        format |= Format_C_2;
-        break;
-    default:
+    if (sampleRate == 0 || channelCount == 0 || !audio_is_valid_format(format)) {
         return Format_Invalid;
     }
     NBAIO_Format ret;
-    ret.mPacked = format;
+    ret.mSampleRate = sampleRate;
+    ret.mChannelCount = channelCount;
+    ret.mFormat = format;
+    ret.mFrameSize = audio_is_linear_pcm(format) ?
+            channelCount * audio_bytes_per_sample(format) : sizeof(uint8_t);
     return ret;
 }
 
@@ -242,12 +158,15 @@
 
 bool Format_isValid(const NBAIO_Format& format)
 {
-    return format.mPacked != Format_Invalid.mPacked;
+    return format.mSampleRate != 0 && format.mChannelCount != 0 &&
+            format.mFormat != AUDIO_FORMAT_INVALID && format.mFrameSize != 0;
 }
 
 bool Format_isEqual(const NBAIO_Format& format1, const NBAIO_Format& format2)
 {
-    return format1.mPacked == format2.mPacked;
+    return format1.mSampleRate == format2.mSampleRate &&
+            format1.mChannelCount == format2.mChannelCount && format1.mFormat == format2.mFormat &&
+            format1.mFrameSize == format2.mFrameSize;
 }
 
 }   // namespace android
diff --git a/media/libnbaio/Pipe.cpp b/media/libnbaio/Pipe.cpp
index 115f311..28a034c 100644
--- a/media/libnbaio/Pipe.cpp
+++ b/media/libnbaio/Pipe.cpp
@@ -52,13 +52,13 @@
     if (CC_LIKELY(written > count)) {
         written = count;
     }
-    memcpy((char *) mBuffer + (rear << mBitShift), buffer, written << mBitShift);
+    memcpy((char *) mBuffer + (rear * mFrameSize), buffer, written * mFrameSize);
     if (CC_UNLIKELY(rear + written == mMaxFrames)) {
         if (CC_UNLIKELY((count -= written) > rear)) {
             count = rear;
         }
         if (CC_LIKELY(count > 0)) {
-            memcpy(mBuffer, (char *) buffer + (written << mBitShift), count << mBitShift);
+            memcpy(mBuffer, (char *) buffer + (written * mFrameSize), count * mFrameSize);
             written += count;
         }
     }
diff --git a/media/libnbaio/PipeReader.cpp b/media/libnbaio/PipeReader.cpp
index 24da1bd..c8e4953 100644
--- a/media/libnbaio/PipeReader.cpp
+++ b/media/libnbaio/PipeReader.cpp
@@ -76,14 +76,14 @@
         red = count;
     }
     // In particular, an overrun during the memcpy will result in reading corrupt data
-    memcpy(buffer, (char *) mPipe.mBuffer + (front << mBitShift), red << mBitShift);
+    memcpy(buffer, (char *) mPipe.mBuffer + (front * mFrameSize), red * mFrameSize);
     // We could re-read the rear pointer here to detect the corruption, but why bother?
     if (CC_UNLIKELY(front + red == mPipe.mMaxFrames)) {
         if (CC_UNLIKELY((count -= red) > front)) {
             count = front;
         }
         if (CC_LIKELY(count > 0)) {
-            memcpy((char *) buffer + (red << mBitShift), mPipe.mBuffer, count << mBitShift);
+            memcpy((char *) buffer + (red * mFrameSize), mPipe.mBuffer, count * mFrameSize);
             red += count;
         }
     }
diff --git a/media/libnbaio/SourceAudioBufferProvider.cpp b/media/libnbaio/SourceAudioBufferProvider.cpp
index 062fa0f..e21ef48 100644
--- a/media/libnbaio/SourceAudioBufferProvider.cpp
+++ b/media/libnbaio/SourceAudioBufferProvider.cpp
@@ -24,7 +24,7 @@
 
 SourceAudioBufferProvider::SourceAudioBufferProvider(const sp<NBAIO_Source>& source) :
     mSource(source),
-    // mFrameBitShiftFormat below
+    // mFrameSize below
     mAllocated(NULL), mSize(0), mOffset(0), mRemaining(0), mGetCount(0), mFramesReleased(0)
 {
     ALOG_ASSERT(source != 0);
@@ -37,7 +37,7 @@
     numCounterOffers = 0;
     index = source->negotiate(counterOffers, 1, NULL, numCounterOffers);
     ALOG_ASSERT(index == 0);
-    mFrameBitShift = Format_frameBitShift(source->format());
+    mFrameSize = Format_frameSize(source->format());
 }
 
 SourceAudioBufferProvider::~SourceAudioBufferProvider()
@@ -54,14 +54,14 @@
         if (mRemaining < buffer->frameCount) {
             buffer->frameCount = mRemaining;
         }
-        buffer->raw = (char *) mAllocated + (mOffset << mFrameBitShift);
+        buffer->raw = (char *) mAllocated + (mOffset * mFrameSize);
         mGetCount = buffer->frameCount;
         return OK;
     }
     // do we need to reallocate?
     if (buffer->frameCount > mSize) {
         free(mAllocated);
-        mAllocated = malloc(buffer->frameCount << mFrameBitShift);
+        mAllocated = malloc(buffer->frameCount * mFrameSize);
         mSize = buffer->frameCount;
     }
     // read from source
@@ -84,7 +84,7 @@
 void SourceAudioBufferProvider::releaseBuffer(Buffer *buffer)
 {
     ALOG_ASSERT((buffer != NULL) &&
-            (buffer->raw == (char *) mAllocated + (mOffset << mFrameBitShift)) &&
+            (buffer->raw == (char *) mAllocated + (mOffset * mFrameSize)) &&
             (buffer->frameCount <= mGetCount) &&
             (mGetCount <= mRemaining) &&
             (mOffset + mRemaining <= mSize));
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 4450d62..9c48587 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -964,6 +964,8 @@
             "audio_decoder.aac", "audio_encoder.aac" },
         { MEDIA_MIMETYPE_AUDIO_VORBIS,
             "audio_decoder.vorbis", "audio_encoder.vorbis" },
+        { MEDIA_MIMETYPE_AUDIO_OPUS,
+            "audio_decoder.opus", "audio_encoder.opus" },
         { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
             "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
         { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 0636dcc..0fd1e69 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -81,6 +81,7 @@
         libicuuc \
         liblog \
         libmedia \
+        libopus \
         libsonivox \
         libssl \
         libstagefright_omx \
diff --git a/media/libstagefright/MediaDefs.cpp b/media/libstagefright/MediaDefs.cpp
index 340cba7..c670bb4 100644
--- a/media/libstagefright/MediaDefs.cpp
+++ b/media/libstagefright/MediaDefs.cpp
@@ -36,6 +36,7 @@
 const char *MEDIA_MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
 const char *MEDIA_MIMETYPE_AUDIO_QCELP = "audio/qcelp";
 const char *MEDIA_MIMETYPE_AUDIO_VORBIS = "audio/vorbis";
+const char *MEDIA_MIMETYPE_AUDIO_OPUS = "audio/opus";
 const char *MEDIA_MIMETYPE_AUDIO_G711_ALAW = "audio/g711-alaw";
 const char *MEDIA_MIMETYPE_AUDIO_G711_MLAW = "audio/g711-mlaw";
 const char *MEDIA_MIMETYPE_AUDIO_RAW = "audio/raw";
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 625922f..4d3b5bd 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -489,6 +489,13 @@
 
             CHECK(meta->findData(kKeyVorbisBooks, &type, &data, &size));
             addCodecSpecificData(data, size);
+        } else if (meta->findData(kKeyOpusHeader, &type, &data, &size)) {
+            addCodecSpecificData(data, size);
+
+            CHECK(meta->findData(kKeyOpusCodecDelay, &type, &data, &size));
+            addCodecSpecificData(data, size);
+            CHECK(meta->findData(kKeyOpusSeekPreRoll, &type, &data, &size));
+            addCodecSpecificData(data, size);
         }
     }
 
@@ -1387,6 +1394,8 @@
             "audio_decoder.aac", "audio_encoder.aac" },
         { MEDIA_MIMETYPE_AUDIO_VORBIS,
             "audio_decoder.vorbis", "audio_encoder.vorbis" },
+        { MEDIA_MIMETYPE_AUDIO_OPUS,
+            "audio_decoder.opus", "audio_encoder.opus" },
         { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
             "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
         { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
@@ -4125,6 +4134,7 @@
         "OMX_AUDIO_CodingMP3",
         "OMX_AUDIO_CodingSBC",
         "OMX_AUDIO_CodingVORBIS",
+        "OMX_AUDIO_CodingOPUS",
         "OMX_AUDIO_CodingWMA",
         "OMX_AUDIO_CodingRA",
         "OMX_AUDIO_CodingMIDI",
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 451e907..4ff805f 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -251,6 +251,13 @@
         buffer->meta()->setInt32("csd", true);
         buffer->meta()->setInt64("timeUs", 0);
         msg->setBuffer("csd-1", buffer);
+    } else if (meta->findData(kKeyOpusHeader, &type, &data, &size)) {
+        sp<ABuffer> buffer = new ABuffer(size);
+        memcpy(buffer->data(), data, size);
+
+        buffer->meta()->setInt32("csd", true);
+        buffer->meta()->setInt64("timeUs", 0);
+        msg->setBuffer("csd-0", buffer);
     }
 
     *format = msg;
@@ -528,6 +535,7 @@
     { MEDIA_MIMETYPE_AUDIO_AMR_WB,      AUDIO_FORMAT_AMR_WB },
     { MEDIA_MIMETYPE_AUDIO_AAC,         AUDIO_FORMAT_AAC },
     { MEDIA_MIMETYPE_AUDIO_VORBIS,      AUDIO_FORMAT_VORBIS },
+    { MEDIA_MIMETYPE_AUDIO_OPUS,        AUDIO_FORMAT_OPUS},
     { 0, AUDIO_FORMAT_INVALID }
 };
 
diff --git a/media/libstagefright/codecs/common/Config.mk b/media/libstagefright/codecs/common/Config.mk
index a6d4286..a843cef 100644
--- a/media/libstagefright/codecs/common/Config.mk
+++ b/media/libstagefright/codecs/common/Config.mk
@@ -14,8 +14,10 @@
 endif
 
 # Do we also need to check on ARCH_ARM_HAVE_ARMV7A? - probably not
-ifeq ($(ARCH_ARM_HAVE_NEON),true)
-VOTT := v7
+ifeq ($(TARGET_ARCH),arm)
+  ifeq ($(ARCH_ARM_HAVE_NEON),true)
+    VOTT := v7
+  endif
 endif
 
 VOTEST := 0
diff --git a/media/libstagefright/codecs/on2/h264dec/Android.mk b/media/libstagefright/codecs/on2/h264dec/Android.mk
index 655b2ab..bf03ad9 100644
--- a/media/libstagefright/codecs/on2/h264dec/Android.mk
+++ b/media/libstagefright/codecs/on2/h264dec/Android.mk
@@ -84,8 +84,8 @@
 	./omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.S \
 	./omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantChromaDCFromPair_s.S \
 
-
-ifeq ($(ARCH_ARM_HAVE_NEON),true)
+ifeq ($(TARGET_ARCH),arm)
+  ifeq ($(ARCH_ARM_HAVE_NEON),true)
     LOCAL_ARM_NEON   := true
 #    LOCAL_CFLAGS     := -std=c99 -D._NEON -D._OMXDL
     LOCAL_CFLAGS     := -DH264DEC_NEON -DH264DEC_OMXDL
@@ -94,6 +94,7 @@
     LOCAL_C_INCLUDES += $(LOCAL_PATH)/./omxdl/arm_neon/api \
                         $(LOCAL_PATH)/./omxdl/arm_neon/vc/api \
                         $(LOCAL_PATH)/./omxdl/arm_neon/vc/m4p10/api
+  endif
 endif
 
 LOCAL_SHARED_LIBRARIES := \
diff --git a/media/libstagefright/codecs/opus/Android.mk b/media/libstagefright/codecs/opus/Android.mk
new file mode 100644
index 0000000..365b179
--- /dev/null
+++ b/media/libstagefright/codecs/opus/Android.mk
@@ -0,0 +1,4 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/media/libstagefright/codecs/opus/dec/Android.mk b/media/libstagefright/codecs/opus/dec/Android.mk
new file mode 100644
index 0000000..2379c5f
--- /dev/null
+++ b/media/libstagefright/codecs/opus/dec/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+        SoftOpus.cpp
+
+LOCAL_C_INCLUDES := \
+        external/libopus/include \
+        frameworks/av/media/libstagefright/include \
+        frameworks/native/include/media/openmax \
+
+LOCAL_SHARED_LIBRARIES := \
+        libopus libstagefright libstagefright_omx \
+        libstagefright_foundation libutils liblog
+
+LOCAL_MODULE := libstagefright_soft_opusdec
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
\ No newline at end of file
diff --git a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
new file mode 100644
index 0000000..b8084ae
--- /dev/null
+++ b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
@@ -0,0 +1,540 @@
+/*
+ * Copyright (C) 2014 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 "SoftOpus"
+#include <utils/Log.h>
+
+#include "SoftOpus.h"
+#include <OMX_AudioExt.h>
+#include <OMX_IndexExt.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaDefs.h>
+
+extern "C" {
+    #include <opus.h>
+    #include <opus_multistream.h>
+}
+
+namespace android {
+
+static const int kRate = 48000;
+
+template<class T>
+static void InitOMXParams(T *params) {
+    params->nSize = sizeof(T);
+    params->nVersion.s.nVersionMajor = 1;
+    params->nVersion.s.nVersionMinor = 0;
+    params->nVersion.s.nRevision = 0;
+    params->nVersion.s.nStep = 0;
+}
+
+SoftOpus::SoftOpus(
+        const char *name,
+        const OMX_CALLBACKTYPE *callbacks,
+        OMX_PTR appData,
+        OMX_COMPONENTTYPE **component)
+    : SimpleSoftOMXComponent(name, callbacks, appData, component),
+      mInputBufferCount(0),
+      mDecoder(NULL),
+      mHeader(NULL),
+      mCodecDelay(0),
+      mSeekPreRoll(0),
+      mAnchorTimeUs(0),
+      mNumFramesOutput(0),
+      mOutputPortSettingsChange(NONE) {
+    initPorts();
+    CHECK_EQ(initDecoder(), (status_t)OK);
+}
+
+SoftOpus::~SoftOpus() {
+    if (mDecoder != NULL) {
+        opus_multistream_decoder_destroy(mDecoder);
+        mDecoder = NULL;
+    }
+    if (mHeader != NULL) {
+        delete mHeader;
+        mHeader = NULL;
+    }
+}
+
+void SoftOpus::initPorts() {
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    InitOMXParams(&def);
+
+    def.nPortIndex = 0;
+    def.eDir = OMX_DirInput;
+    def.nBufferCountMin = kNumBuffers;
+    def.nBufferCountActual = def.nBufferCountMin;
+    def.nBufferSize = 960 * 6;
+    def.bEnabled = OMX_TRUE;
+    def.bPopulated = OMX_FALSE;
+    def.eDomain = OMX_PortDomainAudio;
+    def.bBuffersContiguous = OMX_FALSE;
+    def.nBufferAlignment = 1;
+
+    def.format.audio.cMIMEType =
+        const_cast<char *>(MEDIA_MIMETYPE_AUDIO_OPUS);
+
+    def.format.audio.pNativeRender = NULL;
+    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
+    def.format.audio.eEncoding =
+        (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS;
+
+    addPort(def);
+
+    def.nPortIndex = 1;
+    def.eDir = OMX_DirOutput;
+    def.nBufferCountMin = kNumBuffers;
+    def.nBufferCountActual = def.nBufferCountMin;
+    def.nBufferSize = kMaxNumSamplesPerBuffer * sizeof(int16_t);
+    def.bEnabled = OMX_TRUE;
+    def.bPopulated = OMX_FALSE;
+    def.eDomain = OMX_PortDomainAudio;
+    def.bBuffersContiguous = OMX_FALSE;
+    def.nBufferAlignment = 2;
+
+    def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
+    def.format.audio.pNativeRender = NULL;
+    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
+    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
+
+    addPort(def);
+}
+
+status_t SoftOpus::initDecoder() {
+    return OK;
+}
+
+OMX_ERRORTYPE SoftOpus::internalGetParameter(
+        OMX_INDEXTYPE index, OMX_PTR params) {
+    switch ((int)index) {
+        case OMX_IndexParamAudioAndroidOpus:
+        {
+            OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *opusParams =
+                (OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *)params;
+
+            if (opusParams->nPortIndex != 0) {
+                return OMX_ErrorUndefined;
+            }
+
+            opusParams->nAudioBandWidth = 0;
+            opusParams->nSampleRate = kRate;
+            opusParams->nBitRate = 0;
+
+            if (!isConfigured()) {
+                opusParams->nChannels = 1;
+            } else {
+                opusParams->nChannels = mHeader->channels;
+            }
+
+            return OMX_ErrorNone;
+        }
+
+        case OMX_IndexParamAudioPcm:
+        {
+            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
+                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+
+            if (pcmParams->nPortIndex != 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            pcmParams->eNumData = OMX_NumericalDataSigned;
+            pcmParams->eEndian = OMX_EndianBig;
+            pcmParams->bInterleaved = OMX_TRUE;
+            pcmParams->nBitPerSample = 16;
+            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
+            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
+            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
+            pcmParams->nSamplingRate = kRate;
+
+            if (!isConfigured()) {
+                pcmParams->nChannels = 1;
+            } else {
+                pcmParams->nChannels = mHeader->channels;
+            }
+
+            return OMX_ErrorNone;
+        }
+
+        default:
+            return SimpleSoftOMXComponent::internalGetParameter(index, params);
+    }
+}
+
+OMX_ERRORTYPE SoftOpus::internalSetParameter(
+        OMX_INDEXTYPE index, const OMX_PTR params) {
+    switch ((int)index) {
+        case OMX_IndexParamStandardComponentRole:
+        {
+            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
+                (const OMX_PARAM_COMPONENTROLETYPE *)params;
+
+            if (strncmp((const char *)roleParams->cRole,
+                        "audio_decoder.opus",
+                        OMX_MAX_STRINGNAME_SIZE - 1)) {
+                return OMX_ErrorUndefined;
+            }
+
+            return OMX_ErrorNone;
+        }
+
+        case OMX_IndexParamAudioAndroidOpus:
+        {
+            const OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *opusParams =
+                (const OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *)params;
+
+            if (opusParams->nPortIndex != 0) {
+                return OMX_ErrorUndefined;
+            }
+
+            return OMX_ErrorNone;
+        }
+
+        default:
+            return SimpleSoftOMXComponent::internalSetParameter(index, params);
+    }
+}
+
+bool SoftOpus::isConfigured() const {
+    return mInputBufferCount >= 1;
+}
+
+static uint16_t ReadLE16(const uint8_t *data, size_t data_size,
+                         uint32_t read_offset) {
+    if (read_offset + 1 > data_size)
+        return 0;
+    uint16_t val;
+    val = data[read_offset];
+    val |= data[read_offset + 1] << 8;
+    return val;
+}
+
+// Opus uses Vorbis channel mapping, and Vorbis channel mapping specifies
+// mappings for up to 8 channels. This information is part of the Vorbis I
+// Specification:
+// http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html
+static const int kMaxChannels = 8;
+
+// Maximum packet size used in Xiph's opusdec.
+static const int kMaxOpusOutputPacketSizeSamples = 960 * 6;
+
+// Default audio output channel layout. Used to initialize |stream_map| in
+// OpusHeader, and passed to opus_multistream_decoder_create() when the header
+// does not contain mapping information. The values are valid only for mono and
+// stereo output: Opus streams with more than 2 channels require a stream map.
+static const int kMaxChannelsWithDefaultLayout = 2;
+static const uint8_t kDefaultOpusChannelLayout[kMaxChannelsWithDefaultLayout] = { 0, 1 };
+
+// Parses Opus Header. Header spec: http://wiki.xiph.org/OggOpus#ID_Header
+static bool ParseOpusHeader(const uint8_t *data, size_t data_size,
+                            OpusHeader* header) {
+    // Size of the Opus header excluding optional mapping information.
+    const size_t kOpusHeaderSize = 19;
+
+    // Offset to the channel count byte in the Opus header.
+    const size_t kOpusHeaderChannelsOffset = 9;
+
+    // Offset to the pre-skip value in the Opus header.
+    const size_t kOpusHeaderSkipSamplesOffset = 10;
+
+    // Offset to the gain value in the Opus header.
+    const size_t kOpusHeaderGainOffset = 16;
+
+    // Offset to the channel mapping byte in the Opus header.
+    const size_t kOpusHeaderChannelMappingOffset = 18;
+
+    // Opus Header contains a stream map. The mapping values are in the header
+    // beyond the always present |kOpusHeaderSize| bytes of data. The mapping
+    // data contains stream count, coupling information, and per channel mapping
+    // values:
+    //   - Byte 0: Number of streams.
+    //   - Byte 1: Number coupled.
+    //   - Byte 2: Starting at byte 2 are |header->channels| uint8 mapping
+    //             values.
+    const size_t kOpusHeaderNumStreamsOffset = kOpusHeaderSize;
+    const size_t kOpusHeaderNumCoupledOffset = kOpusHeaderNumStreamsOffset + 1;
+    const size_t kOpusHeaderStreamMapOffset = kOpusHeaderNumStreamsOffset + 2;
+
+    if (data_size < kOpusHeaderSize) {
+        ALOGV("Header size is too small.");
+        return false;
+    }
+    header->channels = *(data + kOpusHeaderChannelsOffset);
+
+    if (header->channels <= 0 || header->channels > kMaxChannels) {
+        ALOGV("Invalid Header, wrong channel count: %d", header->channels);
+        return false;
+    }
+    header->skip_samples = ReadLE16(data, data_size,
+                                        kOpusHeaderSkipSamplesOffset);
+    header->gain_db = static_cast<int16_t>(
+                              ReadLE16(data, data_size,
+                                       kOpusHeaderGainOffset));
+    header->channel_mapping = *(data + kOpusHeaderChannelMappingOffset);
+    if (!header->channel_mapping) {
+        if (header->channels > kMaxChannelsWithDefaultLayout) {
+            ALOGV("Invalid Header, missing stream map.");
+            return false;
+        }
+        header->num_streams = 1;
+        header->num_coupled = header->channels > 1;
+        header->stream_map[0] = 0;
+        header->stream_map[1] = 1;
+        return true;
+    }
+    if (data_size < kOpusHeaderStreamMapOffset + header->channels) {
+        ALOGV("Invalid stream map; insufficient data for current channel "
+              "count: %d", header->channels);
+        return false;
+    }
+    header->num_streams = *(data + kOpusHeaderNumStreamsOffset);
+    header->num_coupled = *(data + kOpusHeaderNumCoupledOffset);
+    if (header->num_streams + header->num_coupled != header->channels) {
+        ALOGV("Inconsistent channel mapping.");
+        return false;
+    }
+    for (int i = 0; i < header->channels; ++i)
+      header->stream_map[i] = *(data + kOpusHeaderStreamMapOffset + i);
+    return true;
+}
+
+// Convert nanoseconds to number of samples.
+static uint64_t ns_to_samples(uint64_t ns, int kRate) {
+    return static_cast<double>(ns) * kRate / 1000000000;
+}
+
+void SoftOpus::onQueueFilled(OMX_U32 portIndex) {
+    List<BufferInfo *> &inQueue = getPortQueue(0);
+    List<BufferInfo *> &outQueue = getPortQueue(1);
+
+    if (mOutputPortSettingsChange != NONE) {
+        return;
+    }
+
+    if (portIndex == 0 && mInputBufferCount < 3) {
+        BufferInfo *info = *inQueue.begin();
+        OMX_BUFFERHEADERTYPE *header = info->mHeader;
+
+        const uint8_t *data = header->pBuffer + header->nOffset;
+        size_t size = header->nFilledLen;
+
+        if (mInputBufferCount == 0) {
+            CHECK(mHeader == NULL);
+            mHeader = new OpusHeader();
+            memset(mHeader, 0, sizeof(*mHeader));
+            if (!ParseOpusHeader(data, size, mHeader)) {
+                ALOGV("Parsing Opus Header failed.");
+                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+                return;
+            }
+
+            uint8_t channel_mapping[kMaxChannels] = {0};
+            memcpy(&channel_mapping,
+                   kDefaultOpusChannelLayout,
+                   kMaxChannelsWithDefaultLayout);
+
+            int status = OPUS_INVALID_STATE;
+            mDecoder = opus_multistream_decoder_create(kRate,
+                                                       mHeader->channels,
+                                                       mHeader->num_streams,
+                                                       mHeader->num_coupled,
+                                                       channel_mapping,
+                                                       &status);
+            if (!mDecoder || status != OPUS_OK) {
+                ALOGV("opus_multistream_decoder_create failed status=%s",
+                      opus_strerror(status));
+                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+                return;
+            }
+            status =
+                opus_multistream_decoder_ctl(mDecoder,
+                                             OPUS_SET_GAIN(mHeader->gain_db));
+            if (status != OPUS_OK) {
+                ALOGV("Failed to set OPUS header gain; status=%s",
+                      opus_strerror(status));
+                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+                return;
+            }
+        } else if (mInputBufferCount == 1) {
+            mCodecDelay = ns_to_samples(
+                              *(reinterpret_cast<int64_t*>(header->pBuffer +
+                                                           header->nOffset)),
+                              kRate);
+            mSamplesToDiscard = mCodecDelay;
+        } else {
+            mSeekPreRoll = ns_to_samples(
+                               *(reinterpret_cast<int64_t*>(header->pBuffer +
+                                                            header->nOffset)),
+                               kRate);
+            notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
+            mOutputPortSettingsChange = AWAITING_DISABLED;
+        }
+
+        inQueue.erase(inQueue.begin());
+        info->mOwnedByUs = false;
+        notifyEmptyBufferDone(header);
+        ++mInputBufferCount;
+        return;
+    }
+
+    while (!inQueue.empty() && !outQueue.empty()) {
+        BufferInfo *inInfo = *inQueue.begin();
+        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
+
+        BufferInfo *outInfo = *outQueue.begin();
+        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+
+        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+            inQueue.erase(inQueue.begin());
+            inInfo->mOwnedByUs = false;
+            notifyEmptyBufferDone(inHeader);
+
+            outHeader->nFilledLen = 0;
+            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+
+            outQueue.erase(outQueue.begin());
+            outInfo->mOwnedByUs = false;
+            notifyFillBufferDone(outHeader);
+            return;
+        }
+
+        if (inHeader->nOffset == 0) {
+            mAnchorTimeUs = inHeader->nTimeStamp;
+            mNumFramesOutput = 0;
+        }
+
+        // When seeking to zero, |mCodecDelay| samples has to be discarded
+        // instead of |mSeekPreRoll| samples (as we would when seeking to any
+        // other timestamp).
+        if (inHeader->nTimeStamp == 0) {
+            mSamplesToDiscard = mCodecDelay;
+        }
+
+        const uint8_t *data = inHeader->pBuffer + inHeader->nOffset;
+        const uint32_t size = inHeader->nFilledLen;
+
+        int numFrames = opus_multistream_decode(mDecoder,
+                                                data,
+                                                size,
+                                                (int16_t *)outHeader->pBuffer,
+                                                kMaxOpusOutputPacketSizeSamples,
+                                                0);
+        if (numFrames < 0) {
+            ALOGE("opus_multistream_decode returned %d", numFrames);
+            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+            return;
+        }
+
+        outHeader->nOffset = 0;
+        if (mSamplesToDiscard > 0) {
+            if (mSamplesToDiscard > numFrames) {
+                mSamplesToDiscard -= numFrames;
+                numFrames = 0;
+            } else {
+                numFrames -= mSamplesToDiscard;
+                outHeader->nOffset = mSamplesToDiscard * sizeof(int16_t) *
+                                     mHeader->channels;
+                mSamplesToDiscard = 0;
+            }
+        }
+
+        outHeader->nFilledLen = numFrames * sizeof(int16_t) * mHeader->channels;
+        outHeader->nFlags = 0;
+
+        outHeader->nTimeStamp = mAnchorTimeUs +
+                                (mNumFramesOutput * 1000000ll) /
+                                kRate;
+
+        mNumFramesOutput += numFrames;
+
+        inInfo->mOwnedByUs = false;
+        inQueue.erase(inQueue.begin());
+        inInfo = NULL;
+        notifyEmptyBufferDone(inHeader);
+        inHeader = NULL;
+
+        outInfo->mOwnedByUs = false;
+        outQueue.erase(outQueue.begin());
+        outInfo = NULL;
+        notifyFillBufferDone(outHeader);
+        outHeader = NULL;
+
+        ++mInputBufferCount;
+    }
+}
+
+void SoftOpus::onPortFlushCompleted(OMX_U32 portIndex) {
+    if (portIndex == 0 && mDecoder != NULL) {
+        // Make sure that the next buffer output does not still
+        // depend on fragments from the last one decoded.
+        mNumFramesOutput = 0;
+        opus_multistream_decoder_ctl(mDecoder, OPUS_RESET_STATE);
+        mAnchorTimeUs = 0;
+        mSamplesToDiscard = mSeekPreRoll;
+    }
+}
+
+void SoftOpus::onReset() {
+    mInputBufferCount = 0;
+    mNumFramesOutput = 0;
+    if (mDecoder != NULL) {
+        opus_multistream_decoder_destroy(mDecoder);
+        mDecoder = NULL;
+    }
+    if (mHeader != NULL) {
+        delete mHeader;
+        mHeader = NULL;
+    }
+
+    mOutputPortSettingsChange = NONE;
+}
+
+void SoftOpus::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
+    if (portIndex != 1) {
+        return;
+    }
+
+    switch (mOutputPortSettingsChange) {
+        case NONE:
+            break;
+
+        case AWAITING_DISABLED:
+        {
+            CHECK(!enabled);
+            mOutputPortSettingsChange = AWAITING_ENABLED;
+            break;
+        }
+
+        default:
+        {
+            CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
+            CHECK(enabled);
+            mOutputPortSettingsChange = NONE;
+            break;
+        }
+    }
+}
+
+}  // namespace android
+
+android::SoftOMXComponent *createSoftOMXComponent(
+        const char *name, const OMX_CALLBACKTYPE *callbacks,
+        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
+    return new android::SoftOpus(name, callbacks, appData, component);
+}
diff --git a/media/libstagefright/codecs/opus/dec/SoftOpus.h b/media/libstagefright/codecs/opus/dec/SoftOpus.h
new file mode 100644
index 0000000..97f6561
--- /dev/null
+++ b/media/libstagefright/codecs/opus/dec/SoftOpus.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+/*
+ * The Opus specification is part of IETF RFC 6716:
+ * http://tools.ietf.org/html/rfc6716
+ */
+
+#ifndef SOFT_OPUS_H_
+
+#define SOFT_OPUS_H_
+
+#include "SimpleSoftOMXComponent.h"
+
+struct OpusMSDecoder;
+
+namespace android {
+
+struct OpusHeader {
+  int channels;
+  int skip_samples;
+  int channel_mapping;
+  int num_streams;
+  int num_coupled;
+  int16_t gain_db;
+  uint8_t stream_map[8];
+};
+
+struct SoftOpus : public SimpleSoftOMXComponent {
+    SoftOpus(const char *name,
+             const OMX_CALLBACKTYPE *callbacks,
+             OMX_PTR appData,
+             OMX_COMPONENTTYPE **component);
+
+protected:
+    virtual ~SoftOpus();
+
+    virtual OMX_ERRORTYPE internalGetParameter(
+            OMX_INDEXTYPE index, OMX_PTR params);
+
+    virtual OMX_ERRORTYPE internalSetParameter(
+            OMX_INDEXTYPE index, const OMX_PTR params);
+
+    virtual void onQueueFilled(OMX_U32 portIndex);
+    virtual void onPortFlushCompleted(OMX_U32 portIndex);
+    virtual void onPortEnableCompleted(OMX_U32 portIndex, bool enabled);
+    virtual void onReset();
+
+private:
+    enum {
+        kNumBuffers = 4,
+        kMaxNumSamplesPerBuffer = 960 * 6
+    };
+
+    size_t mInputBufferCount;
+
+    OpusMSDecoder *mDecoder;
+    OpusHeader *mHeader;
+
+    int64_t mCodecDelay;
+    int64_t mSeekPreRoll;
+    int64_t mSamplesToDiscard;
+    int64_t mAnchorTimeUs;
+    int64_t mNumFramesOutput;
+
+    enum {
+        NONE,
+        AWAITING_DISABLED,
+        AWAITING_ENABLED
+    } mOutputPortSettingsChange;
+
+    void initPorts();
+    status_t initDecoder();
+    bool isConfigured() const;
+
+    DISALLOW_EVIL_CONSTRUCTORS(SoftOpus);
+};
+
+}  // namespace android
+
+#endif  // SOFT_OPUS_H_
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index b221c0c..9d7cb99 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -1233,6 +1233,18 @@
             | (adtsHeader[4] << 3)
             | (adtsHeader[5] >> 5);
 
+        if (aac_frame_length == 0) {
+            const uint8_t *id3Header = adtsHeader;
+            if (!memcmp(id3Header, "ID3", 3)) {
+                ID3 id3(id3Header, buffer->size() - offset, true);
+                if (id3.isValid()) {
+                    offset += id3.rawSize();
+                    continue;
+                };
+            }
+            return ERROR_MALFORMED;
+        }
+
         CHECK_LE(offset + aac_frame_length, buffer->size());
 
         sp<ABuffer> unit = new ABuffer(aac_frame_length);
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp
index 6f69d0b..6ec9263 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.cpp
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -313,7 +313,7 @@
 
     *actualFrameTimeUs = -1ll;
 
-    const int64_t seekTimeNs = seekTimeUs * 1000ll;
+    const int64_t seekTimeNs = seekTimeUs * 1000ll - mExtractor->mSeekPreRollNs;
 
     mkvparser::Segment* const pSegment = mExtractor->mSegment;
 
@@ -628,7 +628,8 @@
       mReader(new DataSourceReader(mDataSource)),
       mSegment(NULL),
       mExtractedThumbnails(false),
-      mIsWebm(false) {
+      mIsWebm(false),
+      mSeekPreRollNs(0) {
     off64_t size;
     mIsLiveStreaming =
         (mDataSource->flags()
@@ -919,6 +920,12 @@
 
                     err = addVorbisCodecInfo(
                             meta, codecPrivate, codecPrivateSize);
+                } else if (!strcmp("A_OPUS", codecID)) {
+                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS);
+                    meta->setData(kKeyOpusHeader, 0, codecPrivate, codecPrivateSize);
+                    meta->setInt64(kKeyOpusCodecDelay, track->GetCodecDelay());
+                    meta->setInt64(kKeyOpusSeekPreRoll, track->GetSeekPreRoll());
+                    mSeekPreRollNs = track->GetSeekPreRoll();
                 } else if (!strcmp("A_MPEG/L3", codecID)) {
                     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
                 } else {
diff --git a/media/libstagefright/matroska/MatroskaExtractor.h b/media/libstagefright/matroska/MatroskaExtractor.h
index 1294b4f..cf200f3 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.h
+++ b/media/libstagefright/matroska/MatroskaExtractor.h
@@ -69,6 +69,7 @@
     bool mExtractedThumbnails;
     bool mIsLiveStreaming;
     bool mIsWebm;
+    int64_t mSeekPreRollNs;
 
     void addTracks();
     void findThumbnails();
diff --git a/media/libstagefright/omx/SoftOMXPlugin.cpp b/media/libstagefright/omx/SoftOMXPlugin.cpp
index d49e50b..65f5404 100644
--- a/media/libstagefright/omx/SoftOMXPlugin.cpp
+++ b/media/libstagefright/omx/SoftOMXPlugin.cpp
@@ -50,6 +50,7 @@
     { "OMX.google.mpeg4.encoder", "mpeg4enc", "video_encoder.mpeg4" },
     { "OMX.google.mp3.decoder", "mp3dec", "audio_decoder.mp3" },
     { "OMX.google.vorbis.decoder", "vorbisdec", "audio_decoder.vorbis" },
+    { "OMX.google.opus.decoder", "opusdec", "audio_decoder.opus" },
     { "OMX.google.vp8.decoder", "vpxdec", "video_decoder.vp8" },
     { "OMX.google.vp9.decoder", "vpxdec", "video_decoder.vp9" },
     { "OMX.google.vp8.encoder", "vpxenc", "video_encoder.vp8" },
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 03725df..f4dfd6b 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -463,6 +463,7 @@
         { "audio_decoder.aac", "audio/mp4a-latm" },
         { "audio_decoder.mp3", "audio/mpeg" },
         { "audio_decoder.vorbis", "audio/vorbis" },
+        { "audio_decoder.opus", "audio/opus" },
         { "audio_decoder.g711alaw", MEDIA_MIMETYPE_AUDIO_G711_ALAW },
         { "audio_decoder.g711mlaw", MEDIA_MIMETYPE_AUDIO_G711_MLAW },
     };
@@ -495,6 +496,7 @@
         { "audio/mpeg",
           "file:///sdcard/media_api/music/MP3_48KHz_128kbps_s_1_17_CBR.mp3" },
         { "audio/vorbis", NULL },
+        { "audio/opus", NULL },
         { "video/x-vnd.on2.vp8",
           "file:///sdcard/media_api/video/big-buck-bunny_trailer.webm" },
         { MEDIA_MIMETYPE_AUDIO_G711_ALAW, "file:///sdcard/M1F1-Alaw-AFsp.wav" },
diff --git a/media/libstagefright/tests/SurfaceMediaSource_test.cpp b/media/libstagefright/tests/SurfaceMediaSource_test.cpp
index aeecdbc..a3093d0 100644
--- a/media/libstagefright/tests/SurfaceMediaSource_test.cpp
+++ b/media/libstagefright/tests/SurfaceMediaSource_test.cpp
@@ -35,7 +35,6 @@
 #include <gui/SurfaceComposerClient.h>
 
 #include <binder/ProcessState.h>
-#include <ui/FramebufferNativeWindow.h>
 
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/MediaBufferGroup.h>
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 357ea22..8fdb50d 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2567,7 +2567,7 @@
     // create an NBAIO sink for the HAL output stream, and negotiate
     mOutputSink = new AudioStreamOutSink(output->stream);
     size_t numCounterOffers = 0;
-    const NBAIO_Format offers[1] = {Format_from_SR_C(mSampleRate, mChannelCount)};
+    const NBAIO_Format offers[1] = {Format_from_SR_C(mSampleRate, mChannelCount, mFormat)};
     ssize_t index = mOutputSink->negotiate(offers, 1, NULL, numCounterOffers);
     ALOG_ASSERT(index == 0);
 
@@ -5555,12 +5555,12 @@
     mBufferSize = mInput->stream->common.get_buffer_size(&mInput->stream->common);
     mFrameCount = mBufferSize / mFrameSize;
     // This is the formula for calculating the temporary buffer size.
-    // With 3 HAL buffers, we can guarantee ability to down-sample the input by ratio of 2:1 to
+    // With 7 HAL buffers, we can guarantee ability to down-sample the input by ratio of 6:1 to
     // 1 full output buffer, regardless of the alignment of the available input.
-    // The "3" is somewhat arbitrary, and could probably be larger.
+    // The value is somewhat arbitrary, and could probably be even larger.
     // A larger value should allow more old data to be read after a track calls start(),
     // without increasing latency.
-    mRsmpInFrames = mFrameCount * 3;
+    mRsmpInFrames = mFrameCount * 7;
     mRsmpInFramesP2 = roundup(mRsmpInFrames);
     delete[] mRsmpInBuffer;
     // Over-allocate beyond mRsmpInFramesP2 to permit a HAL read past end of buffer