summaryrefslogtreecommitdiffstats
path: root/media/libmediaplayerservice
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:43 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:43 -0800
commit7b5eb023f8d87cca6d830ae6c11c6aadbe02aca8 (patch)
treed9838a098f868ee2fcffc20627a8c9a33cb23377 /media/libmediaplayerservice
parent2729ea9262ca60d93047e984739887cfc89e82eb (diff)
downloadframeworks_av-7b5eb023f8d87cca6d830ae6c11c6aadbe02aca8.zip
frameworks_av-7b5eb023f8d87cca6d830ae6c11c6aadbe02aca8.tar.gz
frameworks_av-7b5eb023f8d87cca6d830ae6c11c6aadbe02aca8.tar.bz2
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'media/libmediaplayerservice')
-rw-r--r--media/libmediaplayerservice/Android.mk3
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp136
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.h40
-rw-r--r--media/libmediaplayerservice/MediaRecorderClient.cpp251
-rw-r--r--media/libmediaplayerservice/MediaRecorderClient.h64
-rw-r--r--media/libmediaplayerservice/MetadataRetrieverClient.cpp250
-rw-r--r--media/libmediaplayerservice/MetadataRetrieverClient.h71
-rw-r--r--media/libmediaplayerservice/MidiFile.cpp2
-rw-r--r--media/libmediaplayerservice/VorbisPlayer.cpp2
9 files changed, 764 insertions, 55 deletions
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index b3a5747..f710921 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -7,7 +7,9 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
+ MediaRecorderClient.cpp \
MediaPlayerService.cpp \
+ MetadataRetrieverClient.cpp \
VorbisPlayer.cpp \
MidiFile.cpp
@@ -21,6 +23,7 @@ LOCAL_SHARED_LIBRARIES := \
libvorbisidec \
libsonivox \
libopencoreplayer \
+ libopencoreauthor \
libmedia \
libandroid_runtime
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index fd5f0ed..5383171 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -34,11 +34,17 @@
#include <utils/IServiceManager.h>
#include <utils/MemoryHeapBase.h>
#include <utils/MemoryBase.h>
+#include <cutils/properties.h>
#include <media/MediaPlayerInterface.h>
+#include <media/mediarecorder.h>
+#include <media/MediaMetadataRetrieverInterface.h>
#include <media/AudioTrack.h>
+#include "MediaRecorderClient.h"
#include "MediaPlayerService.h"
+#include "MetadataRetrieverClient.h"
+
#include "MidiFile.h"
#include "VorbisPlayer.h"
#include <media/PVPlayer.h>
@@ -72,7 +78,7 @@ pid_t gettid() { return syscall(__NR_gettid);}
restart continuously.
*/
#define USE_SIGBUS_HANDLER 0
-
+
// TODO: Temp hack until we can register players
static const char* MIDI_FILE_EXTS[] =
{
@@ -87,8 +93,10 @@ static const char* MIDI_FILE_EXTS[] =
namespace android {
-// TODO: should come from audio driver
-/* static */ const uint32_t MediaPlayerService::AudioOutput::kDriverLatencyInMsecs = 150;
+// TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
+/* static */ const uint32_t MediaPlayerService::AudioOutput::kAudioVideoDelayMs = 96;
+/* static */ int MediaPlayerService::AudioOutput::mMinBufferCount = 4;
+/* static */ bool MediaPlayerService::AudioOutput::mIsOnEmulator = false;
static struct sigaction oldact;
static pthread_key_t sigbuskey;
@@ -172,7 +180,7 @@ MediaPlayerService::MediaPlayerService()
pthread_key_create(&sigbuskey, NULL);
-
+
#if USE_SIGBUS_HANDLER
struct sigaction act;
memset(&act,0, sizeof act);
@@ -191,6 +199,20 @@ MediaPlayerService::~MediaPlayerService()
LOGV("MediaPlayerService destroyed");
}
+sp<IMediaRecorder> MediaPlayerService::createMediaRecorder(pid_t pid)
+{
+ sp<MediaRecorderClient> recorder = new MediaRecorderClient(pid);
+ LOGV("Create new media recorder client from pid %d", pid);
+ return recorder;
+}
+
+sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever(pid_t pid)
+{
+ sp<MetadataRetrieverClient> retriever = new MetadataRetrieverClient(pid);
+ LOGV("Create new media retriever from pid %d", pid);
+ return retriever;
+}
+
sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url)
{
int32_t connId = android_atomic_inc(&mNextConnId);
@@ -237,8 +259,8 @@ status_t MediaPlayerService::AudioCache::dump(int fd, const Vector<String16>& ar
mHeap->getBase(), mHeap->getSize(), mHeap->getFlags(), mHeap->getDevice());
result.append(buffer);
}
- snprintf(buffer, 255, " msec per frame(%f), channel count(%ld), frame count(%ld)\n",
- mMsecsPerFrame, mChannelCount, mFrameCount);
+ snprintf(buffer, 255, " msec per frame(%f), channel count(%d), format(%d), frame count(%ld)\n",
+ mMsecsPerFrame, mChannelCount, mFormat, mFrameCount);
result.append(buffer);
snprintf(buffer, 255, " sample rate(%d), size(%d), error(%d), command complete(%s)\n",
mSampleRate, mSize, mError, mCommandComplete?"true":"false");
@@ -257,8 +279,8 @@ status_t MediaPlayerService::AudioOutput::dump(int fd, const Vector<String16>& a
snprintf(buffer, 255, " stream type(%d), left - right volume(%f, %f)\n",
mStreamType, mLeftVolume, mRightVolume);
result.append(buffer);
- snprintf(buffer, 255, " msec per frame(%f), latency (%d), driver latency(%d)\n",
- mMsecsPerFrame, mLatency, kDriverLatencyInMsecs);
+ snprintf(buffer, 255, " msec per frame(%f), latency (%d)\n",
+ mMsecsPerFrame, mLatency);
result.append(buffer);
::write(fd, result.string(), result.size());
if (mTrack != 0) {
@@ -315,7 +337,7 @@ status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
if (f) {
while (!feof(f)) {
fgets(buffer, SIZE, f);
- if (strstr(buffer, " /sdcard/") ||
+ if (strstr(buffer, " /sdcard/") ||
strstr(buffer, " /system/sounds/") ||
strstr(buffer, " /system/media/")) {
result.append(" ");
@@ -334,7 +356,7 @@ status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
if (d) {
struct dirent *ent;
while((ent = readdir(d)) != NULL) {
- if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
+ if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
snprintf(buffer, SIZE, "/proc/%d/fd/%s", myTid(), ent->d_name);
struct stat s;
if (lstat(buffer, &s) == 0) {
@@ -350,7 +372,7 @@ status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
} else {
linkto[len] = 0;
}
- if (strstr(linkto, "/sdcard/") == linkto ||
+ if (strstr(linkto, "/sdcard/") == linkto ||
strstr(linkto, "/system/sounds/") == linkto ||
strstr(linkto, "/system/media/") == linkto) {
result.append(" ");
@@ -683,20 +705,6 @@ status_t MediaPlayerService::Client::isPlaying(bool* state)
return NO_ERROR;
}
-status_t MediaPlayerService::Client::getVideoSize(int *w, int *h)
-{
- sp<MediaPlayerBase> p = getPlayer();
- if (p == 0) return UNKNOWN_ERROR;
- status_t ret = p->getVideoWidth(w);
- if (ret == NO_ERROR) ret = p->getVideoHeight(h);
- if (ret == NO_ERROR) {
- LOGV("[%d] getVideoWidth = (%d, %d)", mConnId, *w, *h);
- } else {
- LOGE("getVideoSize returned %d", ret);
- }
- return ret;
-}
-
status_t MediaPlayerService::Client::getCurrentPosition(int *msec)
{
LOGV("getCurrentPosition");
@@ -812,7 +820,7 @@ int Antagonizer::callbackThread(void* user)
static size_t kDefaultHeapSize = 1024 * 1024; // 1MB
-sp<IMemory> MediaPlayerService::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels)
+sp<IMemory> MediaPlayerService::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
{
LOGV("decode(%s)", url);
sp<MemoryBase> mem;
@@ -856,14 +864,15 @@ sp<IMemory> MediaPlayerService::decode(const char* url, uint32_t *pSampleRate, i
mem = new MemoryBase(cache->getHeap(), 0, cache->size());
*pSampleRate = cache->sampleRate();
*pNumChannels = cache->channelCount();
- LOGV("return memory @ %p, sampleRate=%u, channelCount = %d", mem->pointer(), *pSampleRate, *pNumChannels);
+ *pFormat = cache->format();
+ LOGV("return memory @ %p, sampleRate=%u, channelCount = %d, format = %d", mem->pointer(), *pSampleRate, *pNumChannels, *pFormat);
Exit:
if (player != 0) player->reset();
return mem;
}
-sp<IMemory> MediaPlayerService::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels)
+sp<IMemory> MediaPlayerService::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
{
LOGV("decode(%d, %lld, %lld)", fd, offset, length);
sp<MemoryBase> mem;
@@ -898,7 +907,8 @@ sp<IMemory> MediaPlayerService::decode(int fd, int64_t offset, int64_t length, u
mem = new MemoryBase(cache->getHeap(), 0, cache->size());
*pSampleRate = cache->sampleRate();
*pNumChannels = cache->channelCount();
- LOGV("return memory @ %p, sampleRate=%u, channelCount = %d", mem->pointer(), *pSampleRate, *pNumChannels);
+ *pFormat = cache->format();
+ LOGV("return memory @ %p, sampleRate=%u, channelCount = %d, format = %d", mem->pointer(), *pSampleRate, *pNumChannels, *pFormat);
Exit:
if (player != 0) player->reset();
@@ -916,6 +926,7 @@ MediaPlayerService::AudioOutput::AudioOutput()
mRightVolume = 1.0;
mLatency = 0;
mMsecsPerFrame = 0;
+ setMinBufferCount();
}
MediaPlayerService::AudioOutput::~AudioOutput()
@@ -923,10 +934,31 @@ MediaPlayerService::AudioOutput::~AudioOutput()
close();
}
+void MediaPlayerService::AudioOutput::setMinBufferCount()
+{
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("ro.kernel.qemu", value, 0)) {
+ mIsOnEmulator = true;
+ mMinBufferCount = 12; // to prevent systematic buffer underrun for emulator
+ }
+}
+
+bool MediaPlayerService::AudioOutput::isOnEmulator()
+{
+ setMinBufferCount();
+ return mIsOnEmulator;
+}
+
+int MediaPlayerService::AudioOutput::getMinBufferCount()
+{
+ setMinBufferCount();
+ return mMinBufferCount;
+}
+
ssize_t MediaPlayerService::AudioOutput::bufferSize() const
{
if (mTrack == 0) return NO_INIT;
- return mTrack->frameCount() * mTrack->channelCount() * sizeof(int16_t);
+ return mTrack->frameCount() * frameSize();
}
ssize_t MediaPlayerService::AudioOutput::frameCount() const
@@ -944,7 +976,7 @@ ssize_t MediaPlayerService::AudioOutput::channelCount() const
ssize_t MediaPlayerService::AudioOutput::frameSize() const
{
if (mTrack == 0) return NO_INIT;
- return mTrack->channelCount() * sizeof(int16_t);
+ return mTrack->frameSize();
}
uint32_t MediaPlayerService::AudioOutput::latency () const
@@ -957,12 +989,29 @@ float MediaPlayerService::AudioOutput::msecsPerFrame() const
return mMsecsPerFrame;
}
-status_t MediaPlayerService::AudioOutput::open(uint32_t sampleRate, int channelCount, int bufferCount)
+status_t MediaPlayerService::AudioOutput::open(uint32_t sampleRate, int channelCount, int format, int bufferCount)
{
- LOGV("open(%u, %d, %d)", sampleRate, channelCount, bufferCount);
+ // Check argument "bufferCount" against the mininum buffer count
+ if (bufferCount < mMinBufferCount) {
+ LOGD("bufferCount (%d) is too small and increased to %d", bufferCount, mMinBufferCount);
+ bufferCount = mMinBufferCount;
+
+ }
+ LOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount);
if (mTrack) close();
+ int afSampleRate;
+ int afFrameCount;
+ int frameCount;
- AudioTrack *t = new AudioTrack(mStreamType, sampleRate, AudioSystem::PCM_16_BIT, channelCount, bufferCount);
+ if (AudioSystem::getOutputFrameCount(&afFrameCount) != NO_ERROR) {
+ return NO_INIT;
+ }
+ if (AudioSystem::getOutputSamplingRate(&afSampleRate) != NO_ERROR) {
+ return NO_INIT;
+ }
+
+ frameCount = (sampleRate*afFrameCount)/afSampleRate;
+ AudioTrack *t = new AudioTrack(mStreamType, sampleRate, format, channelCount, frameCount*bufferCount);
if ((t == 0) || (t->initCheck() != NO_ERROR)) {
LOGE("Unable to create audio track");
delete t;
@@ -972,7 +1021,7 @@ status_t MediaPlayerService::AudioOutput::open(uint32_t sampleRate, int channelC
LOGV("setVolume");
t->setVolume(mLeftVolume, mRightVolume);
mMsecsPerFrame = 1.e3 / (float) sampleRate;
- mLatency = (mMsecsPerFrame * bufferCount * t->frameCount()) + kDriverLatencyInMsecs;
+ mLatency = t->latency() + kAudioVideoDelayMs;
mTrack = t;
return NO_ERROR;
}
@@ -1031,7 +1080,7 @@ void MediaPlayerService::AudioOutput::setVolume(float left, float right)
#undef LOG_TAG
#define LOG_TAG "AudioCache"
MediaPlayerService::AudioCache::AudioCache(const char* name) :
- mChannelCount(0), mFrameCount(0), mSampleRate(0), mSize(0),
+ mChannelCount(0), mFrameCount(1024), mSampleRate(0), mSize(0),
mError(NO_ERROR), mCommandComplete(false)
{
// create ashmem heap
@@ -1048,12 +1097,13 @@ float MediaPlayerService::AudioCache::msecsPerFrame() const
return mMsecsPerFrame;
}
-status_t MediaPlayerService::AudioCache::open(uint32_t sampleRate, int channelCount, int bufferCount)
+status_t MediaPlayerService::AudioCache::open(uint32_t sampleRate, int channelCount, int format, int bufferCount)
{
- LOGV("open(%u, %d, %d)", sampleRate, channelCount, bufferCount);
- if (mHeap->getHeapID() < 0) return NO_INIT;
- mSampleRate = sampleRate;
- mChannelCount = channelCount;
+ LOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount);
+ if (mHeap->getHeapID() < 0) return NO_INIT;
+ mSampleRate = sampleRate;
+ mChannelCount = (uint16_t)channelCount;
+ mFormat = (uint16_t)format;
mMsecsPerFrame = 1.e3 / (float) sampleRate;
return NO_ERROR;
}
@@ -1067,6 +1117,10 @@ ssize_t MediaPlayerService::AudioCache::write(const void* buffer, size_t size)
if (p == NULL) return NO_INIT;
p += mSize;
LOGV("memcpy(%p, %p, %u)", p, buffer, size);
+ if (mSize + size > mHeap->getSize()) {
+ LOGE("Heap size overflow! req size: %d, max size: %d", (mSize + size), mHeap->getSize());
+ size = mHeap->getSize() - mSize;
+ }
memcpy(p, buffer, size);
mSize += size;
return size;
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index c2007cb..f138886 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -25,10 +25,11 @@
#include <media/IMediaPlayerService.h>
#include <media/MediaPlayerInterface.h>
-class SkBitmap;
-
namespace android {
+class IMediaRecorder;
+class IMediaMetadataRetriever;
+
#define CALLBACK_ANTAGONIZER 0
#if CALLBACK_ANTAGONIZER
class Antagonizer {
@@ -68,7 +69,7 @@ class MediaPlayerService : public BnMediaPlayerService
virtual ssize_t frameSize() const;
virtual uint32_t latency() const;
virtual float msecsPerFrame() const;
- virtual status_t open(uint32_t sampleRate, int channelCount, int bufferCount=4);
+ virtual status_t open(uint32_t sampleRate, int channelCount, int format, int bufferCount=4);
virtual void start();
virtual ssize_t write(const void* buffer, size_t size);
virtual void stop();
@@ -78,14 +79,24 @@ class MediaPlayerService : public BnMediaPlayerService
void setAudioStreamType(int streamType) { mStreamType = streamType; }
void setVolume(float left, float right);
virtual status_t dump(int fd, const Vector<String16>& args) const;
+
+ static bool isOnEmulator();
+ static int getMinBufferCount();
private:
+ static void setMinBufferCount();
+
AudioTrack* mTrack;
int mStreamType;
float mLeftVolume;
float mRightVolume;
float mMsecsPerFrame;
uint32_t mLatency;
- static const uint32_t kDriverLatencyInMsecs;
+
+ // TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
+ static const uint32_t kAudioVideoDelayMs;
+ static bool mIsOnEmulator;
+ static int mMinBufferCount; // 12 for emulator; otherwise 4
+
};
class AudioCache : public MediaPlayerBase::AudioSink
@@ -96,13 +107,13 @@ class MediaPlayerService : public BnMediaPlayerService
virtual bool ready() const { return (mChannelCount > 0) && (mHeap->getHeapID() > 0); }
virtual bool realtime() const { return false; }
- virtual ssize_t bufferSize() const { return 4096; }
+ virtual ssize_t bufferSize() const { return frameSize() * mFrameCount; }
virtual ssize_t frameCount() const { return mFrameCount; }
- virtual ssize_t channelCount() const { return mChannelCount; }
- virtual ssize_t frameSize() const { return ssize_t(mChannelCount * sizeof(int16_t)); }
+ virtual ssize_t channelCount() const { return (ssize_t)mChannelCount; }
+ virtual ssize_t frameSize() const { return ssize_t(mChannelCount * ((mFormat == AudioSystem::PCM_16_BIT)?sizeof(int16_t):sizeof(u_int8_t))); }
virtual uint32_t latency() const;
virtual float msecsPerFrame() const;
- virtual status_t open(uint32_t sampleRate, int channelCount, int bufferCount=1);
+ virtual status_t open(uint32_t sampleRate, int channelCount, int format, int bufferCount=1);
virtual void start() {}
virtual ssize_t write(const void* buffer, size_t size);
virtual void stop() {}
@@ -112,6 +123,7 @@ class MediaPlayerService : public BnMediaPlayerService
void setAudioStreamType(int streamType) {}
void setVolume(float left, float right) {}
uint32_t sampleRate() const { return mSampleRate; }
+ uint32_t format() const { return (uint32_t)mFormat; }
size_t size() const { return mSize; }
status_t wait();
@@ -127,7 +139,8 @@ class MediaPlayerService : public BnMediaPlayerService
Condition mSignal;
sp<MemoryHeapBase> mHeap;
float mMsecsPerFrame;
- ssize_t mChannelCount;
+ uint16_t mChannelCount;
+ uint16_t mFormat;
ssize_t mFrameCount;
uint32_t mSampleRate;
uint32_t mSize;
@@ -139,10 +152,14 @@ public:
static void instantiate();
// IMediaPlayerService interface
+ virtual sp<IMediaRecorder> createMediaRecorder(pid_t pid);
+ virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid);
+
+ // House keeping for media player clients
virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url);
virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length);
- virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels);
- virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels);
+ virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
+ virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
virtual status_t dump(int fd, const Vector<String16>& args);
@@ -160,7 +177,6 @@ private:
virtual status_t stop();
virtual status_t pause();
virtual status_t isPlaying(bool* state);
- virtual status_t getVideoSize(int* w, int* h);
virtual status_t seekTo(int msec);
virtual status_t getCurrentPosition(int* msec);
virtual status_t getDuration(int* msec);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
new file mode 100644
index 0000000..f326a0e
--- /dev/null
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -0,0 +1,251 @@
+/*
+ ** Copyright 2008, HTC Inc.
+ **
+ ** 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 "MediaRecorderService"
+#include <utils/Log.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <string.h>
+#include <cutils/atomic.h>
+#include <android_runtime/ActivityManager.h>
+#include <utils/IPCThreadState.h>
+#include <utils/IServiceManager.h>
+#include <utils/MemoryHeapBase.h>
+#include <utils/MemoryBase.h>
+#include <media/PVMediaRecorder.h>
+
+#include "MediaRecorderClient.h"
+
+namespace android {
+
+status_t MediaRecorderClient::setCamera(const sp<ICamera>& camera)
+{
+ LOGV("setCamera");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ LOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setCamera(camera);
+}
+
+status_t MediaRecorderClient::setPreviewSurface(const sp<ISurface>& surface)
+{
+ LOGV("setPreviewSurface");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ LOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setPreviewSurface(surface);
+}
+
+status_t MediaRecorderClient::setVideoSource(int vs)
+{
+ LOGV("setVideoSource(%d)", vs);
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ LOGE("recorder is not initialized");
+ }
+ return mRecorder->setVideoSource((video_source)vs);
+}
+
+status_t MediaRecorderClient::setAudioSource(int as)
+{
+ LOGV("setAudioSource(%d)", as);
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ LOGE("recorder is not initialized");
+ }
+ return mRecorder->setAudioSource((audio_source)as);
+}
+
+status_t MediaRecorderClient::setOutputFormat(int of)
+{
+ LOGV("setOutputFormat(%d)", of);
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ LOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setOutputFormat((output_format)of);
+}
+
+status_t MediaRecorderClient::setVideoEncoder(int ve)
+{
+ LOGV("setVideoEncoder(%d)", ve);
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ LOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setVideoEncoder((video_encoder)ve);
+}
+
+status_t MediaRecorderClient::setAudioEncoder(int ae)
+{
+ LOGV("setAudioEncoder(%d)", ae);
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ LOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setAudioEncoder((audio_encoder)ae);
+}
+
+status_t MediaRecorderClient::setOutputFile(const char* path)
+{
+ LOGV("setOutputFile(%s)", path);
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ LOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setOutputFile(path);
+}
+
+status_t MediaRecorderClient::setVideoSize(int width, int height)
+{
+ LOGV("setVideoSize(%dx%d)", width, height);
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ LOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setVideoSize(width, height);
+}
+
+status_t MediaRecorderClient::setVideoFrameRate(int frames_per_second)
+{
+ LOGV("setVideoFrameRate(%d)", frames_per_second);
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ LOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setVideoFrameRate(frames_per_second);
+}
+
+status_t MediaRecorderClient::prepare()
+{
+ LOGV("prepare");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ LOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->prepare();
+}
+
+
+status_t MediaRecorderClient::getMaxAmplitude(int* max)
+{
+ LOGV("getMaxAmplitude");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ LOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->getMaxAmplitude(max);
+}
+
+status_t MediaRecorderClient::start()
+{
+ LOGV("start");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ LOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->start();
+
+}
+
+status_t MediaRecorderClient::stop()
+{
+ LOGV("stop");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ LOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->stop();
+}
+
+status_t MediaRecorderClient::init()
+{
+ LOGV("init");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ LOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->init();
+}
+
+status_t MediaRecorderClient::close()
+{
+ LOGV("close");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ LOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->close();
+}
+
+
+status_t MediaRecorderClient::reset()
+{
+ LOGV("reset");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ LOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->reset();
+}
+
+status_t MediaRecorderClient::release()
+{
+ LOGV("release");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder != NULL) {
+ delete mRecorder;
+ mRecorder = NULL;
+ }
+ return NO_ERROR;
+}
+
+MediaRecorderClient::MediaRecorderClient(pid_t pid)
+{
+ LOGV("Client constructor");
+ mPid = pid;
+ mRecorder = new PVMediaRecorder();
+}
+
+MediaRecorderClient::~MediaRecorderClient()
+{
+ LOGV("Client destructor");
+ release();
+}
+
+}; // namespace android
+
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
new file mode 100644
index 0000000..3158017
--- /dev/null
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -0,0 +1,64 @@
+/*
+ **
+ ** Copyright 2008, HTC Inc.
+ **
+ ** 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.
+ */
+
+#ifndef ANDROID_MEDIARECORDERCLIENT_H
+#define ANDROID_MEDIARECORDERCLIENT_H
+
+#include <media/IMediaRecorder.h>
+
+namespace android {
+
+class PVMediaRecorder;
+class ISurface;
+
+class MediaRecorderClient : public BnMediaRecorder
+{
+public:
+ virtual status_t setCamera(const sp<ICamera>& camera);
+ virtual status_t setPreviewSurface(const sp<ISurface>& surface);
+ virtual status_t setVideoSource(int vs);
+ virtual status_t setAudioSource(int as);
+ virtual status_t setOutputFormat(int of);
+ virtual status_t setVideoEncoder(int ve);
+ virtual status_t setAudioEncoder(int ae);
+ virtual status_t setOutputFile(const char* path);
+ virtual status_t setVideoSize(int width, int height);
+ virtual status_t setVideoFrameRate(int frames_per_second);
+ virtual status_t prepare();
+ virtual status_t getMaxAmplitude(int* max);
+ virtual status_t start();
+ virtual status_t stop();
+ virtual status_t reset();
+ virtual status_t init();
+ virtual status_t close();
+ virtual status_t release();
+
+private:
+ friend class MediaPlayerService; // for accessing private constructor
+
+ MediaRecorderClient(pid_t pid);
+ virtual ~MediaRecorderClient();
+
+ pid_t mPid;
+ Mutex mLock;
+ PVMediaRecorder *mRecorder;
+};
+
+}; // namespace android
+
+#endif // ANDROID_MEDIARECORDERCLIENT_H
+
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
new file mode 100644
index 0000000..a320bd5
--- /dev/null
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -0,0 +1,250 @@
+/*
+**
+** Copyright (C) 2008 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 "MetadataRetrieverClient"
+#include <utils/Log.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#include <string.h>
+#include <cutils/atomic.h>
+#include <utils/MemoryDealer.h>
+#include <android_runtime/ActivityManager.h>
+#include <utils/IPCThreadState.h>
+#include <utils/IServiceManager.h>
+#include <media/MediaMetadataRetrieverInterface.h>
+#include <media/MediaPlayerInterface.h>
+#include <media/PVMetadataRetriever.h>
+#include <private/media/VideoFrame.h>
+
+#include "MetadataRetrieverClient.h"
+
+
+namespace android {
+
+MetadataRetrieverClient::MetadataRetrieverClient(pid_t pid)
+{
+ LOGV("MetadataRetrieverClient constructor pid(%d)", pid);
+ mPid = pid;
+ mThumbnailDealer = NULL;
+ mAlbumArtDealer = NULL;
+ mThumbnail = NULL;
+ mAlbumArt = NULL;
+
+ mRetriever = new PVMetadataRetriever();
+ if (mRetriever == NULL) {
+ LOGE("failed to initialize the retriever");
+ }
+}
+
+MetadataRetrieverClient::~MetadataRetrieverClient()
+{
+ LOGV("MetadataRetrieverClient destructor");
+ disconnect();
+}
+
+status_t MetadataRetrieverClient::dump(int fd, const Vector<String16>& args) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ result.append(" MetadataRetrieverClient\n");
+ snprintf(buffer, 255, " pid(%d)\n", mPid);
+ result.append(buffer);
+ write(fd, result.string(), result.size());
+ write(fd, "\n", 1);
+ return NO_ERROR;
+}
+
+void MetadataRetrieverClient::disconnect()
+{
+ LOGV("disconnect from pid %d", mPid);
+ Mutex::Autolock lock(mLock);
+ mRetriever.clear();
+ mThumbnailDealer.clear();
+ mAlbumArtDealer.clear();
+ mThumbnail.clear();
+ mAlbumArt.clear();
+ IPCThreadState::self()->flushCommands();
+}
+
+status_t MetadataRetrieverClient::setDataSource(const char *url)
+{
+ LOGV("setDataSource(%s)", url);
+ Mutex::Autolock lock(mLock);
+ if (url == NULL) {
+ return UNKNOWN_ERROR;
+ }
+ if (mRetriever == NULL) {
+ LOGE("retriever is not initialized");
+ return NO_INIT;
+ }
+ return mRetriever->setDataSource(url);
+}
+
+status_t MetadataRetrieverClient::setDataSource(int fd, int64_t offset, int64_t length)
+{
+ LOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length);
+ Mutex::Autolock lock(mLock);
+ if (mRetriever == NULL) {
+ LOGE("retriever is not initialized");
+ ::close(fd);
+ return NO_INIT;
+ }
+
+ struct stat sb;
+ int ret = fstat(fd, &sb);
+ if (ret != 0) {
+ LOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
+ return UNKNOWN_ERROR;
+ }
+ LOGV("st_dev = %llu", sb.st_dev);
+ LOGV("st_mode = %u", sb.st_mode);
+ LOGV("st_uid = %lu", sb.st_uid);
+ LOGV("st_gid = %lu", sb.st_gid);
+ LOGV("st_size = %llu", sb.st_size);
+
+ if (offset >= sb.st_size) {
+ LOGE("offset (%lld) bigger than file size (%llu)", offset, sb.st_size);
+ ::close(fd);
+ return UNKNOWN_ERROR;
+ }
+ if (offset + length > sb.st_size) {
+ length = sb.st_size - offset;
+ LOGE("calculated length = %lld", length);
+ }
+ status_t status = mRetriever->setDataSource(fd, offset, length);
+ ::close(fd);
+ return status;
+}
+
+status_t MetadataRetrieverClient::setMode(int mode)
+{
+ LOGV("setMode");
+ Mutex::Autolock lock(mLock);
+ if (mRetriever == NULL) {
+ LOGE("retriever is not initialized");
+ return NO_INIT;
+ }
+ return mRetriever->setMode(mode);
+}
+
+status_t MetadataRetrieverClient::getMode(int* mode) const
+{
+ LOGV("getMode");
+ Mutex::Autolock lock(mLock);
+ if (mRetriever == NULL) {
+ LOGE("retriever is not initialized");
+ return NO_INIT;
+ }
+ return mRetriever->getMode(mode);
+}
+
+sp<IMemory> MetadataRetrieverClient::captureFrame()
+{
+ LOGV("captureFrame");
+ Mutex::Autolock lock(mLock);
+ mThumbnail.clear();
+ mThumbnailDealer.clear();
+ if (mRetriever == NULL) {
+ LOGE("retriever is not initialized");
+ return NULL;
+ }
+ VideoFrame *frame = mRetriever->captureFrame();
+ if (frame == NULL) {
+ LOGE("failed to capture a video frame");
+ return NULL;
+ }
+ size_t size = sizeof(VideoFrame) + frame->mSize;
+ mThumbnailDealer = new MemoryDealer(size);
+ if (mThumbnailDealer == NULL) {
+ LOGE("failed to create MemoryDealer");
+ delete frame;
+ return NULL;
+ }
+ mThumbnail = mThumbnailDealer->allocate(size);
+ if (mThumbnail == NULL) {
+ LOGE("not enough memory for VideoFrame size=%u", size);
+ mThumbnailDealer.clear();
+ delete frame;
+ return NULL;
+ }
+ VideoFrame *frameCopy = static_cast<VideoFrame *>(mThumbnail->pointer());
+ frameCopy->mWidth = frame->mWidth;
+ frameCopy->mHeight = frame->mHeight;
+ frameCopy->mDisplayWidth = frame->mDisplayWidth;
+ frameCopy->mDisplayHeight = frame->mDisplayHeight;
+ frameCopy->mSize = frame->mSize;
+ frameCopy->mData = (uint8_t *)frameCopy + sizeof(VideoFrame);
+ memcpy(frameCopy->mData, frame->mData, frame->mSize);
+ delete frame; // Fix memory leakage
+ return mThumbnail;
+}
+
+sp<IMemory> MetadataRetrieverClient::extractAlbumArt()
+{
+ LOGV("extractAlbumArt");
+ Mutex::Autolock lock(mLock);
+ mAlbumArt.clear();
+ mAlbumArtDealer.clear();
+ if (mRetriever == NULL) {
+ LOGE("retriever is not initialized");
+ return NULL;
+ }
+ MediaAlbumArt *albumArt = mRetriever->extractAlbumArt();
+ if (albumArt == NULL) {
+ LOGE("failed to extract an album art");
+ return NULL;
+ }
+ size_t size = sizeof(MediaAlbumArt) + albumArt->mSize;
+ mAlbumArtDealer = new MemoryDealer(size);
+ if (mAlbumArtDealer == NULL) {
+ LOGE("failed to create MemoryDealer object");
+ delete albumArt;
+ return NULL;
+ }
+ mAlbumArt = mAlbumArtDealer->allocate(size);
+ if (mAlbumArt == NULL) {
+ LOGE("not enough memory for MediaAlbumArt size=%u", size);
+ mAlbumArtDealer.clear();
+ delete albumArt;
+ return NULL;
+ }
+ MediaAlbumArt *albumArtCopy = static_cast<MediaAlbumArt *>(mAlbumArt->pointer());
+ albumArtCopy->mSize = albumArt->mSize;
+ albumArtCopy->mData = (uint8_t *)albumArtCopy + sizeof(MediaAlbumArt);
+ memcpy(albumArtCopy->mData, albumArt->mData, albumArt->mSize);
+ delete albumArt; // Fix memory leakage
+ return mAlbumArt;
+}
+
+const char* MetadataRetrieverClient::extractMetadata(int keyCode)
+{
+ LOGV("extractMetadata");
+ Mutex::Autolock lock(mLock);
+ if (mRetriever == NULL) {
+ LOGE("retriever is not initialized");
+ return NULL;
+ }
+ return mRetriever->extractMetadata(keyCode);
+}
+
+}; // namespace android
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.h b/media/libmediaplayerservice/MetadataRetrieverClient.h
new file mode 100644
index 0000000..ce29c98
--- /dev/null
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.h
@@ -0,0 +1,71 @@
+/*
+**
+** Copyright (C) 2008 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.
+*/
+
+#ifndef ANDROID_MEDIAMETADATARETRIEVERSERVICE_H
+#define ANDROID_MEDIAMETADATARETRIEVERSERVICE_H
+
+#include <utils.h>
+#include <utils/KeyedVector.h>
+#include <utils/IMemory.h>
+
+#include <media/MediaMetadataRetrieverInterface.h>
+
+
+namespace android {
+
+class IMediaPlayerService;
+class MemoryDealer;
+
+class MetadataRetrieverClient : public BnMediaMetadataRetriever
+{
+public:
+ MetadataRetrieverClient(const sp<IMediaPlayerService>& service, pid_t pid, int32_t connId);
+
+ // Implements IMediaMetadataRetriever interface
+ // These methods are called in IMediaMetadataRetriever.cpp?
+ virtual void disconnect();
+ virtual status_t setDataSource(const char *url);
+ virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
+ virtual status_t setMode(int mode);
+ virtual status_t getMode(int* mode) const;
+ virtual sp<IMemory> captureFrame();
+ virtual sp<IMemory> extractAlbumArt();
+ virtual const char* extractMetadata(int keyCode);
+
+ virtual status_t dump(int fd, const Vector<String16>& args) const;
+
+private:
+ friend class MediaPlayerService;
+
+ explicit MetadataRetrieverClient(pid_t pid);
+ virtual ~MetadataRetrieverClient();
+
+ mutable Mutex mLock;
+ sp<MediaMetadataRetrieverBase> mRetriever;
+ pid_t mPid;
+
+ // Keep the shared memory copy of album art and capture frame (for thumbnail)
+ sp<MemoryDealer> mAlbumArtDealer;
+ sp<MemoryDealer> mThumbnailDealer;
+ sp<IMemory> mAlbumArt;
+ sp<IMemory> mThumbnail;
+};
+
+}; // namespace android
+
+#endif // ANDROID_MEDIAMETADATARETRIEVERSERVICE_H
+
diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp
index 538f7d4..cfad66c 100644
--- a/media/libmediaplayerservice/MidiFile.cpp
+++ b/media/libmediaplayerservice/MidiFile.cpp
@@ -431,7 +431,7 @@ status_t MidiFile::setLooping(int loop)
}
status_t MidiFile::createOutputTrack() {
- if (mAudioSink->open(pLibConfig->sampleRate,pLibConfig->numChannels, 2) != NO_ERROR) {
+ if (mAudioSink->open(pLibConfig->sampleRate, pLibConfig->numChannels, AudioSystem::PCM_16_BIT, 2) != NO_ERROR) {
LOGE("mAudioSink open failed");
return ERROR_OPEN_FAILED;
}
diff --git a/media/libmediaplayerservice/VorbisPlayer.cpp b/media/libmediaplayerservice/VorbisPlayer.cpp
index a0e0f39..9a64403 100644
--- a/media/libmediaplayerservice/VorbisPlayer.cpp
+++ b/media/libmediaplayerservice/VorbisPlayer.cpp
@@ -385,7 +385,7 @@ status_t VorbisPlayer::createOutputTrack() {
LOGV("Create AudioTrack object: rate=%ld, channels=%d\n",
vi->rate, vi->channels);
- if (mAudioSink->open(vi->rate, vi->channels, DEFAULT_AUDIOSINK_BUFFERCOUNT) != NO_ERROR) {
+ if (mAudioSink->open(vi->rate, vi->channels, AudioSystem::PCM_16_BIT, DEFAULT_AUDIOSINK_BUFFERCOUNT) != NO_ERROR) {
LOGE("mAudioSink open failed");
return ERROR_OPEN_FAILED;
}