summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmds/screenrecord/FrameOutput.h8
-rw-r--r--cmds/screenrecord/Overlay.h4
-rw-r--r--include/media/AudioTrack.h1
-rw-r--r--include/media/nbaio/AudioStreamInSource.h2
-rw-r--r--include/media/nbaio/AudioStreamOutSink.h2
-rw-r--r--include/media/nbaio/NBAIO.h19
-rw-r--r--include/media/nbaio/SourceAudioBufferProvider.h2
-rw-r--r--include/media/stagefright/MediaDefs.h1
-rw-r--r--include/media/stagefright/MetaData.h3
-rw-r--r--media/libeffects/downmix/EffectDownmix.c6
-rw-r--r--media/libeffects/downmix/EffectDownmix.h4
-rw-r--r--media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c2
-rw-r--r--media/libeffects/lvm/lib/Bundle/src/LVM_Process.c2
-rw-r--r--media/libeffects/lvm/lib/Common/lib/InstAlloc.h2
-rw-r--r--media/libeffects/lvm/lib/Common/lib/LVM_Types.h13
-rw-r--r--media/libeffects/lvm/lib/Common/src/InstAlloc.c22
-rw-r--r--media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c2
-rw-r--r--media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp20
-rw-r--r--media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp14
-rw-r--r--media/libeffects/preprocessing/PreProcessing.cpp14
-rw-r--r--media/libeffects/testlibs/EffectEqualizer.cpp10
-rw-r--r--media/libeffects/testlibs/EffectReverb.c8
-rw-r--r--media/libeffects/testlibs/EffectReverb.h4
-rw-r--r--media/libmedia/AudioTrack.cpp57
-rw-r--r--media/libmedia/IAudioPolicyService.cpp14
-rw-r--r--media/libnbaio/AudioBufferProviderSource.cpp4
-rw-r--r--media/libnbaio/AudioStreamInSource.cpp16
-rw-r--r--media/libnbaio/AudioStreamOutSink.cpp16
-rw-r--r--media/libnbaio/MonoPipe.cpp6
-rw-r--r--media/libnbaio/MonoPipeReader.cpp4
-rw-r--r--media/libnbaio/NBAIO.cpp115
-rw-r--r--media/libnbaio/Pipe.cpp4
-rw-r--r--media/libnbaio/PipeReader.cpp4
-rw-r--r--media/libnbaio/SourceAudioBufferProvider.cpp10
-rw-r--r--media/libstagefright/ACodec.cpp2
-rw-r--r--media/libstagefright/Android.mk1
-rw-r--r--media/libstagefright/MediaDefs.cpp1
-rw-r--r--media/libstagefright/OMXCodec.cpp10
-rw-r--r--media/libstagefright/Utils.cpp8
-rw-r--r--media/libstagefright/codecs/common/Config.mk6
-rw-r--r--media/libstagefright/codecs/on2/h264dec/Android.mk5
-rw-r--r--media/libstagefright/codecs/opus/Android.mk4
-rw-r--r--media/libstagefright/codecs/opus/dec/Android.mk19
-rw-r--r--media/libstagefright/codecs/opus/dec/SoftOpus.cpp540
-rw-r--r--media/libstagefright/codecs/opus/dec/SoftOpus.h94
-rw-r--r--media/libstagefright/httplive/PlaylistFetcher.cpp12
-rw-r--r--media/libstagefright/matroska/MatroskaExtractor.cpp11
-rw-r--r--media/libstagefright/matroska/MatroskaExtractor.h1
-rw-r--r--media/libstagefright/omx/SoftOMXPlugin.cpp1
-rw-r--r--media/libstagefright/omx/tests/OMXHarness.cpp2
-rw-r--r--media/libstagefright/tests/SurfaceMediaSource_test.cpp1
-rw-r--r--services/audioflinger/Threads.cpp8
52 files changed, 895 insertions, 246 deletions
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 @@ public:
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 @@ private:
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 @@ public:
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 @@ private:
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 @@ protected:
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 @@ public:
// 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 @@ public:
// 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 @@ enum {
// 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 @@ extern const NBAIO_Format Format_Invalid;
// 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 @@ public:
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 @@ public:
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_MPEG_LAYER_II;
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 @@ enum {
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_Reset(downmix_object_t *pDownmixer, bool init) {
*
*----------------------------------------------------------------------------
*/
-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 @@ int Downmix_setParameter(downmix_object_t *pDownmixer, int32_t param, size_t siz
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_setParameter(downmix_object_t *pDownmixer, int32_t param, size_t siz
*
*----------------------------------------------------------------------------
*/
-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 @@ static int Downmix_GetDescriptor(effect_handle_t self,
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 @@ LVDBE_ReturnStatus_en LVDBE_Init(LVDBE_Handle_t *phInstance,
{
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 @@ LVM_ReturnStatus_en LVM_Process(LVM_Handle_t hInstance,
/*
* 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 @@ extern "C" {
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 @@ extern "C" {
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 InstAlloc_Init( INST_ALLOC *pms,
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* InstAlloc_AddMember( INST_ALLOC *pms,
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 @@ LVM_UINT32 InstAlloc_GetTotal( INST_ALLOC *pms)
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 @@ LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t hInstance,
}
/* 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 @@ int Effect_command(effect_handle_t self,
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 @@ int Effect_command(effect_handle_t self,
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 @@ int Effect_command(effect_handle_t self,
//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 @@ int Effect_command(effect_handle_t self,
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 @@ int Effect_command(effect_handle_t self,
// *(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 @@ int Effect_command(effect_handle_t self,
// *(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 @@ int Effect_command(effect_handle_t self,
// *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 @@ int Effect_command(effect_handle_t self,
// *(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 @@ void Reverb_getConfig (ReverbContext *pContext, effect_config_t *pConfig);
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_LoadPreset(ReverbContext *pContext)
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 @@ int Reverb_command(effect_handle_t self,
//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 @@ int Reverb_command(effect_handle_t self,
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 @@ int Reverb_command(effect_handle_t self,
// *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 @@ struct preproc_ops_s {
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 AgcCreate(preproc_effect_t *effect)
int AgcGetParameter(preproc_effect_t *effect,
void *pParam,
- size_t *pValueSize,
+ uint32_t *pValueSize,
void *pValue)
{
int status = 0;
@@ -452,9 +452,9 @@ int AecCreate(preproc_effect_t *effect)
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 @@ int NsCreate(preproc_effect_t *effect)
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 @@ int PreProcessingFx_Command(effect_handle_t self,
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 @@ struct EqualizerContext {
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_init(EqualizerContext *pContext)
//
//----------------------------------------------------------------------------
-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 @@ extern "C" int Equalizer_command(effect_handle_t self, uint32_t cmdCode, uint32_
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 @@ extern "C" int Equalizer_command(effect_handle_t self, uint32_t cmdCode, uint32_
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 @@ void Reverb_Reset(reverb_object_t *pReverb, bool init) {
*
*----------------------------------------------------------------------------
*/
-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 @@ int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, size_t *pSize,
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_getParameter(reverb_object_t *pReverb, int32_t param, size_t *pSize,
*
*----------------------------------------------------------------------------
*/
-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 @@ int Reverb_setParameter(reverb_object_t *pReverb, int32_t param, size_t size,
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 @@ int Reverb_setConfig(reverb_module_t *pRvbModule, effect_config_t *pConfig, bool
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 @@ AudioTrack::AudioTrack()
: mStatus(NO_INIT),
mIsTimed(false),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
- mPreviousSchedulingGroup(SP_DEFAULT)
+ mPreviousSchedulingGroup(SP_DEFAULT),
+ mPausedPosition(0)
{
}
@@ -121,7 +122,8 @@ AudioTrack::AudioTrack(
: 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 @@ AudioTrack::AudioTrack(
: 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 @@ void AudioTrack::pause()
}
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 @@ status_t AudioTrack::getPosition(uint32_t *position) const
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 @@ nsecs_t AudioTrack::processAudioBuffer()
}
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 @@ nsecs_t AudioTrack::processAudioBuffer()
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 @@ status_t BnAudioPolicyService::onTransact(
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 @@ status_t BnAudioPolicyService::onTransact(
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 @@ status_t BnAudioPolicyService::onTransact(
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 @@ status_t BnAudioPolicyService::onTransact(
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 @@ ssize_t AudioBufferProviderSource::read(void *buffer,
}
// 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 @@ ssize_t AudioBufferProviderSource::readVia(readVia_t via, size_t total, void *us
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 @@ ssize_t AudioStreamInSource::negotiate(const NBAIO_Format offers[], size_t numOf
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 @@ ssize_t AudioStreamInSource::read(void *buffer, size_t count)
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 @@ ssize_t AudioStreamOutSink::negotiate(const NBAIO_Format offers[], size_t numOff
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 @@ ssize_t AudioStreamOutSink::write(const void *buffer, size_t count)
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 @@ ssize_t MonoPipe::write(const void *buffer, size_t count)
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 @@ ssize_t MonoPipe::write(const void *buffer, size_t count)
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 @@ ssize_t MonoPipeReader::read(void *buffer, size_t count, int64_t readPTS)
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 @@ namespace android {
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 @@ unsigned Format_channelCount(const NBAIO_Format& format)
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 @@ ssize_t NBAIO_Port::negotiate(const NBAIO_Format offers[], size_t numOffers,
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 @@ ssize_t Pipe::write(const void *buffer, size_t count)
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 @@ ssize_t PipeReader::read(void *buffer, size_t count, int64_t readPTS __unused)
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 @@ namespace android {
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 @@ SourceAudioBufferProvider::SourceAudioBufferProvider(const sp<NBAIO_Source>& sou
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 @@ status_t SourceAudioBufferProvider::getNextBuffer(Buffer *buffer, int64_t pts)
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 @@ status_t SourceAudioBufferProvider::getNextBuffer(Buffer *buffer, int64_t pts)
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 @@ status_t ACodec::setComponentRole(
"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 @@ LOCAL_SHARED_LIBRARIES := \
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_MPEG_LAYER_II = "audio/mpeg-L2";
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 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
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 @@ void OMXCodec::setComponentRole(
"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 @@ static const char *audioCodingTypeString(OMX_AUDIO_CODINGTYPE type) {
"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 @@ status_t convertMetaDataToMessage(
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 @@ static const struct mime_conv_t mimeLookup[] = {
{ 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 @@ VOTT := pc
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 @@ MY_OMXDL_ASM_SRC := \
./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 @@ ifeq ($(ARCH_ARM_HAVE_NEON),true)
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 @@ status_t PlaylistFetcher::extractAndQueueAccessUnits(
| (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 @@ void BlockIterator::seek(
*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 @@ MatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source)
mReader(new DataSourceReader(mDataSource)),
mSegment(NULL),
mExtractedThumbnails(false),
- mIsWebm(false) {
+ mIsWebm(false),
+ mSeekPreRollNs(0) {
off64_t size;
mIsLiveStreaming =
(mDataSource->flags()
@@ -919,6 +920,12 @@ void MatroskaExtractor::addTracks() {
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 @@ private:
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 @@ static const struct {
{ "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 @@ static const char *GetMimeFromComponentRole(const char *componentRole) {
{ "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 @@ static const char *GetURLForMime(const char *mime) {
{ "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 @@ AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, Aud
// 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 @@ void AudioFlinger::RecordThread::readInputParameters_l()
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