summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/AudioSystem.h1
-rw-r--r--include/media/IAudioFlinger.h6
-rw-r--r--media/libmedia/AudioSystem.cpp7
-rw-r--r--media/libmedia/IAudioFlinger.cpp18
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp35
-rw-r--r--media/libstagefright/include/OMXNodeInstance.h10
-rw-r--r--media/libstagefright/omx/OMX.cpp2
-rw-r--r--media/libstagefright/omx/OMXNodeInstance.cpp89
8 files changed, 163 insertions, 5 deletions
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 57f8102..a7c8a0a 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -220,6 +220,7 @@ public:
static status_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount,
size_t* buffSize);
+ static status_t setVoiceVolume(float volume);
//
// AudioPolicyService interface
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index 8018568..a46c727 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -102,10 +102,10 @@ public:
virtual status_t setParameters(int ioHandle, const String8& keyValuePairs) = 0;
virtual String8 getParameters(int ioHandle, const String8& keys) = 0;
-
+
// register a current process for audio output change notifications
virtual void registerClient(const sp<IAudioFlingerClient>& client) = 0;
-
+
// retrieve the audio recording buffer size
virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount) = 0;
@@ -128,6 +128,8 @@ public:
virtual status_t closeInput(int input) = 0;
virtual status_t setStreamOutput(uint32_t stream, int output) = 0;
+
+ virtual status_t setVoiceVolume(float volume) = 0;
};
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index bd1b2d7..5352234 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -335,6 +335,13 @@ status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, int format, int ch
return NO_ERROR;
}
+status_t AudioSystem::setVoiceVolume(float value)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ return af->setVoiceVolume(value);
+}
+
// ---------------------------------------------------------------------------
void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) {
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 5089157..0eff205 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -59,7 +59,8 @@ enum {
RESTORE_OUTPUT,
OPEN_INPUT,
CLOSE_INPUT,
- SET_STREAM_OUTPUT
+ SET_STREAM_OUTPUT,
+ SET_VOICE_VOLUME
};
class BpAudioFlinger : public BpInterface<IAudioFlinger>
@@ -455,6 +456,15 @@ public:
remote()->transact(SET_STREAM_OUTPUT, data, &reply);
return reply.readInt32();
}
+
+ virtual status_t setVoiceVolume(float volume)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeFloat(volume);
+ remote()->transact(SET_VOICE_VOLUME, data, &reply);
+ return reply.readInt32();
+ }
};
IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
@@ -700,6 +710,12 @@ status_t BnAudioFlinger::onTransact(
reply->writeInt32(setStreamOutput(stream, output));
return NO_ERROR;
} break;
+ case SET_VOICE_VOLUME: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ float volume = data.readFloat();
+ reply->writeInt32( setVoiceVolume(volume) );
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index ab759df..64267de 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -356,11 +356,44 @@ extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
extern "C" void free_malloc_leak_info(uint8_t* info);
+// Use the String-class below instead of String8 to allocate all memory
+// beforehand and not reenter the heap while we are examining it...
+struct MyString8 {
+ static const size_t MAX_SIZE = 256 * 1024;
+
+ MyString8()
+ : mPtr((char *)malloc(MAX_SIZE)) {
+ *mPtr = '\0';
+ }
+
+ ~MyString8() {
+ free(mPtr);
+ }
+
+ void append(const char *s) {
+ strcat(mPtr, s);
+ }
+
+ const char *string() const {
+ return mPtr;
+ }
+
+ size_t size() const {
+ return strlen(mPtr);
+ }
+
+private:
+ char *mPtr;
+
+ MyString8(const MyString8 &);
+ MyString8 &operator=(const MyString8 &);
+};
+
void memStatus(int fd, const Vector<String16>& args)
{
const size_t SIZE = 256;
char buffer[SIZE];
- String8 result;
+ MyString8 result;
typedef struct {
size_t size;
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index 181742e..09a8816 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -85,8 +85,18 @@ private:
OMX_HANDLETYPE mHandle;
sp<IOMXObserver> mObserver;
+ struct ActiveBuffer {
+ OMX_U32 mPortIndex;
+ OMX::buffer_id mID;
+ };
+ Vector<ActiveBuffer> mActiveBuffers;
+
~OMXNodeInstance();
+ void addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id);
+ void removeActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id);
+ void freeActiveBuffers();
+
static OMX_ERRORTYPE OnEvent(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_PTR pAppData,
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 3800a26..e361018 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -98,7 +98,7 @@ void OMX::CallbackDispatcher::post(const omx_message &msg) {
void OMX::CallbackDispatcher::dispatch(const omx_message &msg) {
OMXNodeInstance *instance = mOwner->findInstance(msg.node);
if (instance == NULL) {
- LOGW("Would have dispatched a message to a node that's already gone.");
+ LOGV("Would have dispatched a message to a node that's already gone.");
return;
}
instance->onMessage(msg);
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index d5d45d7..ab8be53 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -107,6 +107,55 @@ static status_t StatusFromOMXError(OMX_ERRORTYPE err) {
}
status_t OMXNodeInstance::freeNode() {
+ // Transition the node from its current state all the way down
+ // to "Loaded".
+ // This ensures that all active buffers are properly freed even
+ // for components that don't do this themselves on a call to
+ // "FreeHandle".
+
+ OMX_STATETYPE state;
+ CHECK_EQ(OMX_GetState(mHandle, &state), OMX_ErrorNone);
+ switch (state) {
+ case OMX_StateExecuting:
+ {
+ LOGV("forcing Executing->Idle");
+ sendCommand(OMX_CommandStateSet, OMX_StateIdle);
+ OMX_ERRORTYPE err;
+ while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
+ && state != OMX_StateIdle) {
+ usleep(100000);
+ }
+ CHECK_EQ(err, OMX_ErrorNone);
+
+ // fall through
+ }
+
+ case OMX_StateIdle:
+ {
+ LOGV("forcing Idle->Loaded");
+ sendCommand(OMX_CommandStateSet, OMX_StateLoaded);
+
+ freeActiveBuffers();
+
+ OMX_ERRORTYPE err;
+ while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
+ && state != OMX_StateLoaded) {
+ LOGV("waiting for Loaded state...");
+ usleep(100000);
+ }
+ CHECK_EQ(err, OMX_ErrorNone);
+
+ // fall through
+ }
+
+ case OMX_StateLoaded:
+ break;
+
+ default:
+ CHECK(!"should not be here, unknown state.");
+ break;
+ }
+
OMX_ERRORTYPE err = OMX_MasterFreeHandle(mHandle);
mHandle = NULL;
@@ -193,6 +242,8 @@ status_t OMXNodeInstance::useBuffer(
*buffer = header;
+ addActiveBuffer(portIndex, *buffer);
+
return OK;
}
@@ -220,6 +271,8 @@ status_t OMXNodeInstance::allocateBuffer(
*buffer = header;
+ addActiveBuffer(portIndex, *buffer);
+
return OK;
}
@@ -248,6 +301,8 @@ status_t OMXNodeInstance::allocateBufferWithBackup(
*buffer = header;
+ addActiveBuffer(portIndex, *buffer);
+
return OK;
}
@@ -255,6 +310,8 @@ status_t OMXNodeInstance::freeBuffer(
OMX_U32 portIndex, OMX::buffer_id buffer) {
Mutex::Autolock autoLock(mLock);
+ removeActiveBuffer(portIndex, buffer);
+
OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
@@ -367,5 +424,37 @@ OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone(
return instance->owner()->OnFillBufferDone(instance->nodeID(), pBuffer);
}
+void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) {
+ ActiveBuffer active;
+ active.mPortIndex = portIndex;
+ active.mID = id;
+ mActiveBuffers.push(active);
+}
+
+void OMXNodeInstance::removeActiveBuffer(
+ OMX_U32 portIndex, OMX::buffer_id id) {
+ bool found = false;
+ for (size_t i = 0; i < mActiveBuffers.size(); ++i) {
+ if (mActiveBuffers[i].mPortIndex == portIndex
+ && mActiveBuffers[i].mID == id) {
+ found = true;
+ mActiveBuffers.removeItemsAt(i);
+ break;
+ }
+ }
+
+ if (!found) {
+ LOGW("Attempt to remove an active buffer we know nothing about...");
+ }
+}
+
+void OMXNodeInstance::freeActiveBuffers() {
+ // Make sure to count down here, as freeBuffer will in turn remove
+ // the active buffer from the vector...
+ for (size_t i = mActiveBuffers.size(); i--;) {
+ freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID);
+ }
+}
+
} // namespace android