diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-12-17 18:05:43 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-12-17 18:05:43 -0800 |
commit | 7b5eb023f8d87cca6d830ae6c11c6aadbe02aca8 (patch) | |
tree | d9838a098f868ee2fcffc20627a8c9a33cb23377 /media/libmediaplayerservice | |
parent | 2729ea9262ca60d93047e984739887cfc89e82eb (diff) | |
download | frameworks_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.mk | 3 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.cpp | 136 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.h | 40 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaRecorderClient.cpp | 251 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaRecorderClient.h | 64 | ||||
-rw-r--r-- | media/libmediaplayerservice/MetadataRetrieverClient.cpp | 250 | ||||
-rw-r--r-- | media/libmediaplayerservice/MetadataRetrieverClient.h | 71 | ||||
-rw-r--r-- | media/libmediaplayerservice/MidiFile.cpp | 2 | ||||
-rw-r--r-- | media/libmediaplayerservice/VorbisPlayer.cpp | 2 |
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; } |