summaryrefslogtreecommitdiffstats
path: root/media/libmedia
diff options
context:
space:
mode:
authorMarco Nelissen <marcone@google.com>2009-09-20 10:42:13 -0700
committerMarco Nelissen <marcone@google.com>2009-10-06 08:51:16 -0700
commit10dbb8e97e7a81ca4867663b5517f048820b3094 (patch)
tree8a85a3f2c3547afc82a7ab1f92bed562ab980102 /media/libmedia
parentdefd1bd08aaf7edc1918108419cf3f9d185c22f9 (diff)
downloadframeworks_av-10dbb8e97e7a81ca4867663b5517f048820b3094.zip
frameworks_av-10dbb8e97e7a81ca4867663b5517f048820b3094.tar.gz
frameworks_av-10dbb8e97e7a81ca4867663b5517f048820b3094.tar.bz2
Music visualizer support hack.
This currently assumes 44k stereo (won't crash on other formats, but won't give the correct results either), and links statically with libspeex to get FFT data, increasing the size of libmedia by about 45kb.
Diffstat (limited to 'media/libmedia')
-rw-r--r--media/libmedia/Android.mk10
-rw-r--r--media/libmedia/IMediaPlayerService.cpp15
-rw-r--r--media/libmedia/mediaplayer.cpp57
3 files changed, 79 insertions, 3 deletions
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 7c01687..3c0ee1c 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -37,8 +37,12 @@ LOCAL_SHARED_LIBRARIES += libdl
endif
LOCAL_C_INCLUDES := \
- $(JNI_H_INCLUDE) \
- $(call include-path-for, graphics corecg) \
- $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
+ $(JNI_H_INCLUDE) \
+ $(call include-path-for, graphics corecg) \
+ $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
+ external/speex/include \
+ external/speex/libspeex
+
+LOCAL_STATIC_LIBRARIES := libspeex
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index 8d2c360..98f7ef1 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -36,6 +36,7 @@ enum {
CREATE_MEDIA_RECORDER,
CREATE_METADATA_RETRIEVER,
CREATE_OMX,
+ SNOOP
};
class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
@@ -114,6 +115,14 @@ public:
return interface_cast<IMemory>(reply.readStrongBinder());
}
+ virtual sp<IMemory> snoop()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+ remote()->transact(SNOOP, data, &reply);
+ return interface_cast<IMemory>(reply.readStrongBinder());
+ }
+
virtual sp<IOMX> createOMX() {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
@@ -178,6 +187,12 @@ status_t BnMediaPlayerService::onTransact(
reply->writeStrongBinder(player->asBinder());
return NO_ERROR;
} break;
+ case SNOOP: {
+ CHECK_INTERFACE(IMediaPlayerService, data, reply);
+ sp<IMemory> snooped_audio = snoop();
+ reply->writeStrongBinder(snooped_audio->asBinder());
+ return NO_ERROR;
+ } break;
case CREATE_MEDIA_RECORDER: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
pid_t pid = data.readInt32();
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index aeb43c5..040366b 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -690,4 +690,61 @@ MediaPlayer::DeathNotifier::~DeathNotifier()
}
+extern "C" {
+#define FLOATING_POINT 1
+#include "fftwrap.h"
+}
+
+static void *ffttable = NULL;
+
+// peeks at the audio data and fills 'data' with the requested kind
+// (currently kind=0 returns mono 16 bit PCM data, and kind=1 returns
+// 256 point FFT data). Return value is number of samples returned,
+// which may be 0.
+/*static*/ int MediaPlayer::snoop(short* data, int len, int kind) {
+
+ sp<IMemory> p;
+ const sp<IMediaPlayerService>& service = getMediaPlayerService();
+ if (service != 0) {
+ // Take a peek at the waveform. The returned data consists of 16 bit mono PCM data.
+ p = service->snoop();
+
+ if (p == NULL) {
+ return 0;
+ }
+
+ if (kind == 0) { // return waveform data
+ int plen = p->size();
+ len *= 2; // number of shorts -> number of bytes
+ short *src = (short*) p->pointer();
+ if (plen > len) {
+ plen = len;
+ }
+ memcpy(data, src, plen);
+ return plen / sizeof(short); // return number of samples
+ } else if (kind == 1) {
+ // TODO: use a more efficient FFT
+ // Right now this uses the speex library, which is compiled to do a float FFT
+ if (!ffttable) ffttable = spx_fft_init(512);
+ short *usrc = (short*) p->pointer();
+ float fsrc[512];
+ for (int i=0;i<512;i++)
+ fsrc[i] = usrc[i];
+ float fdst[512];
+ spx_fft_float(ffttable, fsrc, fdst);
+ if (len > 512) {
+ len = 512;
+ }
+ len /= 2; // only half the output data is valid
+ for (int i=0; i < len; i++)
+ data[i] = fdst[i];
+ return len;
+ }
+
+ } else {
+ LOGE("Unable to locate media service");
+ }
+ return 0;
+}
+
}; // namespace android