From 5e07b5774c8b376776caa4f5b0a193767697e97e Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Tue, 10 Feb 2009 15:44:00 -0800 Subject: auto import from //branches/cupcake/...@130745 --- include/media/AudioSystem.h | 23 +++- include/media/AudioTrack.h | 1 + include/media/IAudioFlinger.h | 10 ++ include/media/IAudioFlingerClient.h | 55 ++++++++ include/media/JetPlayer.h | 16 ++- include/media/MediaPlayerInterface.h | 32 ----- include/media/PVPlayer.h | 14 +- include/media/ToneGenerator.h | 3 - include/private/opengles/gl_context.h | 1 + media/libmedia/Android.mk | 1 + media/libmedia/AudioRecord.cpp | 18 ++- media/libmedia/AudioSystem.cpp | 55 +++++++- media/libmedia/AudioTrack.cpp | 14 +- media/libmedia/IAudioFlinger.cpp | 50 +++++++ media/libmedia/IAudioFlingerClient.cpp | 81 ++++++++++++ media/libmedia/JetPlayer.cpp | 70 +++++++++- media/libmedia/ToneGenerator.cpp | 8 +- media/libmedia/mediaplayer.cpp | 10 +- media/libmediaplayerservice/MediaPlayerService.cpp | 147 +++------------------ media/libmediaplayerservice/MidiFile.cpp | 20 +-- media/libmediaplayerservice/MidiFile.h | 2 - media/libmediaplayerservice/VorbisPlayer.cpp | 4 +- 22 files changed, 409 insertions(+), 226 deletions(-) create mode 100644 include/media/IAudioFlingerClient.h create mode 100644 media/libmedia/IAudioFlingerClient.cpp diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index 77676bf..6bd54ba 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -99,23 +99,31 @@ public: static status_t getOutputSamplingRate(int* samplingRate); static status_t getOutputFrameCount(int* frameCount); static status_t getOutputLatency(uint32_t* latency); + + static status_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount, + size_t* buffSize); // ---------------------------------------------------------------------------- private: - class DeathNotifier: public IBinder::DeathRecipient + class AudioFlingerClient: public IBinder::DeathRecipient, public BnAudioFlingerClient { public: - DeathNotifier() { + AudioFlingerClient() { } + // DeathRecipient virtual void binderDied(const wp& who); + + // IAudioFlingerClient + virtual void audioOutputChanged(uint32_t frameCount, uint32_t samplingRate, uint32_t latency); + }; - static sp gDeathNotifier; + static sp gAudioFlingerClient; - friend class DeathNotifier; + friend class AudioFlingerClient; static Mutex gLock; static sp gAudioFlinger; @@ -123,6 +131,13 @@ private: static int gOutSamplingRate; static int gOutFrameCount; static uint32_t gOutLatency; + + static size_t gInBuffSize; + // previous parameters for recording buffer size queries + static uint32_t gPrevInSamplingRate; + static int gPrevInFormat; + static int gPrevInChannelCount; + }; }; // namespace android diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h index fd62daa..5b2bab9 100644 --- a/include/media/AudioTrack.h +++ b/include/media/AudioTrack.h @@ -51,6 +51,7 @@ public: MUSIC = 3, ALARM = 4, NOTIFICATION = 5, + BLUETOOTH_SCO = 6, NUM_STREAM_TYPES }; diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h index 69703b2..df601d7 100644 --- a/include/media/IAudioFlinger.h +++ b/include/media/IAudioFlinger.h @@ -26,6 +26,7 @@ #include #include #include +#include namespace android { @@ -107,6 +108,15 @@ public: // Temporary interface, do not use // TODO: Replace with a more generic key:value get/set mechanism virtual status_t setParameter(const char* key, const char* value) = 0; + + // register a current process for audio output change notifications + virtual void registerClient(const sp& client) = 0; + + // retrieve the audio recording buffer size + virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount) = 0; + + // force AudioFlinger thread out of standby + virtual void wakeUp() = 0; }; diff --git a/include/media/IAudioFlingerClient.h b/include/media/IAudioFlingerClient.h new file mode 100644 index 0000000..10c3e0f --- /dev/null +++ b/include/media/IAudioFlingerClient.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2009 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_IAUDIOFLINGERCLIENT_H +#define ANDROID_IAUDIOFLINGERCLIENT_H + + +#include +#include + + +namespace android { + +// ---------------------------------------------------------------------------- + +class IAudioFlingerClient : public IInterface +{ +public: + DECLARE_META_INTERFACE(AudioFlingerClient); + + // Notifies a change of audio output from/to hardware to/from A2DP. + virtual void audioOutputChanged(uint32_t frameCount, uint32_t samplingRate, uint32_t latency) = 0; + +}; + + +// ---------------------------------------------------------------------------- + +class BnAudioFlingerClient : public BnInterface +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +// ---------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_IAUDIOFLINGERCLIENT_H diff --git a/include/media/JetPlayer.h b/include/media/JetPlayer.h index 4268170..16764a9 100644 --- a/include/media/JetPlayer.h +++ b/include/media/JetPlayer.h @@ -33,9 +33,12 @@ class JetPlayer { public: - static const int JET_USERID_UPDATE = 1; - static const int JET_NUMQUEUEDSEGMENT_UPDATE = 2; - static const int JET_PAUSE_UPDATE = 3; + // to keep in sync with the JetPlayer class constants + // defined in frameworks/base/media/java/android/media/JetPlayer.java + static const int JET_EVENT = 1; + static const int JET_USERID_UPDATE = 2; + static const int JET_NUMQUEUEDSEGMENT_UPDATE = 3; + static const int JET_PAUSE_UPDATE = 4; JetPlayer(jobject javaJetPlayer, int maxTracks = 32, @@ -44,7 +47,8 @@ public: int init(); int release(); - int openFile(const char* url); + int loadFromFile(const char* url); + int loadFromFD(const int fd, const long long offset, const long long length); int closeFile(); int play(); int pause(); @@ -53,6 +57,7 @@ public: int setMuteFlags(EAS_U32 muteFlags, bool sync); int setMuteFlag(int trackNum, bool muteFlag, bool sync); int triggerClip(int clipId); + int clearQueue(); void setEventCallback(jetevent_callback callback); @@ -62,7 +67,8 @@ public: private: static int renderThread(void*); int render(); - void fireEventOnStatusChange(); + void fireUpdateOnStatusChange(); + void fireEventsFromJetQueue(); JetPlayer() {} // no default constructor void dump(); diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h index 30e4578..7f0e7b3 100644 --- a/include/media/MediaPlayerInterface.h +++ b/include/media/MediaPlayerInterface.h @@ -17,9 +17,6 @@ #ifndef ANDROID_MEDIAPLAYERINTERFACE_H #define ANDROID_MEDIAPLAYERINTERFACE_H -#include -#include - #ifdef __cplusplus #include @@ -74,7 +71,6 @@ public: virtual ~MediaPlayerBase() {} virtual status_t initCheck() = 0; virtual bool hardwareOutput() = 0; - virtual status_t setSigBusHandlerStructTLSKey(pthread_key_t key) { return 0; } virtual status_t setDataSource(const char *url) = 0; virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; virtual status_t setVideoSurface(const sp& surface) = 0; @@ -125,34 +121,6 @@ public: #endif // __cplusplus -// A thread can set the thread local variable identified by the pthread_key_t -// that was passed to the player using the setSigBusHandlerStructTLSKey() -// method to the address of the following structure. -// If 'handlesigbus' is non-NULL, the function it points to will be called, -// and if it returns 0, the signal will be assumed to have been handled, -// and no other action will be taken. If it returns non-zero, the old SIGBUS -// handler will be called. -// If 'handlesigbus is NULL, then sigbusvar must be non NULL. The system's -// SIGBUS handler will map an accessible page filled with zeroes at the -// location that caused the original fault, set the variable pointed to by -// sigbusvar to a non-zero value, and exit (which causes the operation to -// be retried, which should now succeed). -// If base and len are non zero, which is strongly recommended, they will -// be used as additional constraints on the signal handler. That is, when -// specified, the fault address must be in the range specified by base and -// len in order for handlesigbus() to be called or sigbusvar to be set. -// If the fault address is outside of the range, the old SIGBUS handler -// will be called. -struct mediasigbushandler { - int (*handlesigbus)(siginfo_t *, struct mediasigbushandler *); - int *sigbusvar; - char *base; - int len; - // these next two are free for application use - struct mediasigbushandler *next; - void *data; -}; - #endif // ANDROID_MEDIAPLAYERINTERFACE_H diff --git a/include/media/PVPlayer.h b/include/media/PVPlayer.h index 5f302ed..6d98852 100644 --- a/include/media/PVPlayer.h +++ b/include/media/PVPlayer.h @@ -20,6 +20,12 @@ #include #include +#define MAX_OPENCORE_INSTANCES 25 + +#ifdef MAX_OPENCORE_INSTANCES +#include +#endif + class PlayerDriver; namespace android { @@ -31,7 +37,6 @@ public: virtual ~PVPlayer(); virtual status_t initCheck(); - virtual status_t setSigBusHandlerStructTLSKey(pthread_key_t key); virtual status_t setDataSource(const char *url); virtual status_t setDataSource(int fd, int64_t offset, int64_t length); virtual status_t setVideoSurface(const sp& surface); @@ -62,10 +67,13 @@ private: char * mDataSourcePath; bool mIsDataSourceSet; sp mSurface; - void * mMemBase; - off_t mMemSize; + int mSharedFd; status_t mInit; int mDuration; + +#ifdef MAX_OPENCORE_INSTANCES + static volatile int32_t sNumInstances; +#endif }; }; // namespace android diff --git a/include/media/ToneGenerator.h b/include/media/ToneGenerator.h index 0cfdeec..ec64e4d 100644 --- a/include/media/ToneGenerator.h +++ b/include/media/ToneGenerator.h @@ -85,8 +85,6 @@ private: TONE_RESTARTING // }; - static const unsigned int NUM_PCM_BUFFERS = 2; // Number of AudioTrack pcm buffers - static const unsigned int TONEGEN_MAX_WAVES = 3; static const unsigned int TONEGEN_MAX_SEGMENTS = 4; // Maximun number of elenemts in static const unsigned int TONEGEN_INF = 0xFFFFFFFF; // Represents infinite time duration @@ -127,7 +125,6 @@ private: const ToneDescriptor *mpNewToneDesc; // pointer to next active tone descriptor int mSamplingRate; // AudioFlinger Sampling rate - int mBufferSize; // PCM buffer size in frames AudioTrack *mpAudioTrack; // Pointer to audio track used for playback Mutex mLock; // Mutex to control concurent access to ToneGenerator object from audio callback and application API Mutex mCbkCondLock; // Mutex associated to mWaitCbkCond diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h index 3056139..0c7ad46 100644 --- a/include/private/opengles/gl_context.h +++ b/include/private/opengles/gl_context.h @@ -28,6 +28,7 @@ #include #include +#include namespace android { diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index 2a697b9..8020da2 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -4,6 +4,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ AudioTrack.cpp \ IAudioFlinger.cpp \ + IAudioFlingerClient.cpp \ IAudioTrack.cpp \ IAudioRecord.cpp \ AudioRecord.cpp \ diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 3d39181..a987b92 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -128,8 +128,22 @@ status_t AudioRecord::set( return BAD_VALUE; } - // TODO: Get input frame count from hardware. - int minFrameCount = 1024*2; + size_t inputBuffSizeInBytes = -1; + if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &inputBuffSizeInBytes) + != NO_ERROR) { + LOGE("AudioSystem could not query the input buffer size."); + return NO_INIT; + } + if (inputBuffSizeInBytes == 0) { + LOGE("Recording parameters are not supported: sampleRate %d, channelCount %d, format %d", + sampleRate, channelCount, format); + return BAD_VALUE; + } + int frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? 2 : 1); + + // We use 2* size of input buffer for ping pong use of record buffer. + int minFrameCount = 2 * inputBuffSizeInBytes / frameSizeInBytes; + LOGV("AudioRecord::set() minFrameCount = %d", minFrameCount); if (frameCount == 0) { frameCount = minFrameCount; diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index a375b55..cf91105 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -15,6 +15,8 @@ */ #define LOG_TAG "AudioSystem" +//#define LOG_NDEBUG 0 + #include #include #include @@ -26,12 +28,17 @@ namespace android { // client singleton for AudioFlinger binder interface Mutex AudioSystem::gLock; sp AudioSystem::gAudioFlinger; -sp AudioSystem::gDeathNotifier; +sp AudioSystem::gAudioFlingerClient; audio_error_callback AudioSystem::gAudioErrorCallback = NULL; // Cached values int AudioSystem::gOutSamplingRate = 0; int AudioSystem::gOutFrameCount = 0; uint32_t AudioSystem::gOutLatency = 0; +// Cached values for recording queries +uint32_t AudioSystem::gPrevInSamplingRate = 16000; +int AudioSystem::gPrevInFormat = AudioSystem::PCM_16_BIT; +int AudioSystem::gPrevInChannelCount = 1; +size_t AudioSystem::gInBuffSize = 0; // establish binder interface to AudioFlinger service @@ -48,15 +55,16 @@ const sp& AudioSystem::get_audio_flinger() LOGW("AudioFlinger not published, waiting..."); usleep(500000); // 0.5 s } while(true); - if (gDeathNotifier == NULL) { - gDeathNotifier = new DeathNotifier(); + if (gAudioFlingerClient == NULL) { + gAudioFlingerClient = new AudioFlingerClient(); } else { if (gAudioErrorCallback) { gAudioErrorCallback(NO_ERROR); } } - binder->linkToDeath(gDeathNotifier); + binder->linkToDeath(gAudioFlingerClient); gAudioFlinger = interface_cast(binder); + gAudioFlinger->registerClient(gAudioFlingerClient); // Cache frequently accessed parameters gOutFrameCount = (int)gAudioFlinger->frameCount(); gOutSamplingRate = (int)gAudioFlinger->sampleRate(); @@ -250,7 +258,7 @@ status_t AudioSystem::getOutputSamplingRate(int* samplingRate) const sp& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; // gOutSamplingRate is updated by get_audio_flinger() - } + } *samplingRate = gOutSamplingRate; return NO_ERROR; @@ -261,7 +269,7 @@ status_t AudioSystem::getOutputFrameCount(int* frameCount) if (gOutFrameCount == 0) { const sp& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; - // gOutSamplingRate is updated by get_audio_flinger() + // gOutFrameCount is updated by get_audio_flinger() } *frameCount = gOutFrameCount; return NO_ERROR; @@ -279,14 +287,38 @@ status_t AudioSystem::getOutputLatency(uint32_t* latency) return NO_ERROR; } +status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, int format, int channelCount, + size_t* buffSize) +{ + // Do we have a stale gInBufferSize or are we requesting the input buffer size for new values + if ((gInBuffSize == 0) || (sampleRate != gPrevInSamplingRate) || (format != gPrevInFormat) + || (channelCount != gPrevInChannelCount)) { + // save the request params + gPrevInSamplingRate = sampleRate; + gPrevInFormat = format; + gPrevInChannelCount = channelCount; + + gInBuffSize = 0; + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) { + return PERMISSION_DENIED; + } + gInBuffSize = af->getInputBufferSize(sampleRate, format, channelCount); + } + *buffSize = gInBuffSize; + + return NO_ERROR; +} + // --------------------------------------------------------------------------- -void AudioSystem::DeathNotifier::binderDied(const wp& who) { +void AudioSystem::AudioFlingerClient::binderDied(const wp& who) { Mutex::Autolock _l(AudioSystem::gLock); AudioSystem::gAudioFlinger.clear(); AudioSystem::gOutSamplingRate = 0; AudioSystem::gOutFrameCount = 0; AudioSystem::gOutLatency = 0; + AudioSystem::gInBuffSize = 0; if (gAudioErrorCallback) { gAudioErrorCallback(DEAD_OBJECT); @@ -294,6 +326,15 @@ void AudioSystem::DeathNotifier::binderDied(const wp& who) { LOGW("AudioFlinger server died!"); } +void AudioSystem::AudioFlingerClient::audioOutputChanged(uint32_t frameCount, uint32_t samplingRate, uint32_t latency) { + + AudioSystem::gOutFrameCount = frameCount; + AudioSystem::gOutSamplingRate = samplingRate; + AudioSystem::gOutLatency = latency; + + LOGV("AudioFlinger output changed!"); +} + void AudioSystem::setErrorCallback(audio_error_callback cb) { Mutex::Autolock _l(AudioSystem::gLock); gAudioErrorCallback = cb; diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index f9f8568..63b2012 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -603,13 +603,17 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) if (__builtin_expect(result!=NO_ERROR, false)) { cblk->waitTimeMs += WAIT_PERIOD_MS; if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) { - LOGW( "obtainBuffer timed out (is the CPU pegged?) " - "user=%08x, server=%08x", cblk->user, cblk->server); - mAudioTrack->start(); // FIXME: Wake up audioflinger - timeout = 1; + // timing out when a loop has been set and we have already written upto loop end + // is a normal condition: no need to wake AudioFlinger up. + if (cblk->user < cblk->loopEnd) { + LOGW( "obtainBuffer timed out (is the CPU pegged?) " + "user=%08x, server=%08x", cblk->user, cblk->server); + mAudioFlinger->wakeUp(); + timeout = 1; + } cblk->waitTimeMs = 0; } - ; + if (--waitCount == 0) { return TIMED_OUT; } diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 018ea6c..4215820 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -51,6 +51,9 @@ enum { GET_MIC_MUTE, IS_MUSIC_ACTIVE, SET_PARAMETER, + REGISTER_CLIENT, + GET_INPUTBUFFERSIZE, + WAKE_UP }; class BpAudioFlinger : public BpInterface @@ -303,6 +306,33 @@ public: remote()->transact(SET_PARAMETER, data, &reply); return reply.readInt32(); } + + virtual void registerClient(const sp& client) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeStrongBinder(client->asBinder()); + remote()->transact(REGISTER_CLIENT, data, &reply); + } + + virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(sampleRate); + data.writeInt32(format); + data.writeInt32(channelCount); + remote()->transact(GET_INPUTBUFFERSIZE, data, &reply); + return reply.readInt32(); + } + + virtual void wakeUp() + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + remote()->transact(WAKE_UP, data, &reply); + return; + } }; IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger"); @@ -470,6 +500,26 @@ status_t BnAudioFlinger::onTransact( reply->writeInt32( setParameter(key, value) ); return NO_ERROR; } break; + case REGISTER_CLIENT: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + sp client = interface_cast(data.readStrongBinder()); + registerClient(client); + return NO_ERROR; + } break; + case GET_INPUTBUFFERSIZE: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + uint32_t sampleRate = data.readInt32(); + int format = data.readInt32(); + int channelCount = data.readInt32(); + reply->writeInt32( getInputBufferSize(sampleRate, format, channelCount) ); + return NO_ERROR; + } break; + case WAKE_UP: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + wakeUp(); + return NO_ERROR; + } break; + default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp new file mode 100644 index 0000000..d956266 --- /dev/null +++ b/media/libmedia/IAudioFlingerClient.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2009 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_TAG "IAudioFlingerClient" +#include + +#include +#include + +#include + +#include + +namespace android { + +enum { + AUDIO_OUTPUT_CHANGED = IBinder::FIRST_CALL_TRANSACTION +}; + +class BpAudioFlingerClient : public BpInterface +{ +public: + BpAudioFlingerClient(const sp& impl) + : BpInterface(impl) + { + } + + void audioOutputChanged(uint32_t frameCount, uint32_t samplingRate, uint32_t latency) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor()); + data.writeInt32(frameCount); + data.writeInt32(samplingRate); + data.writeInt32(latency); + remote()->transact(AUDIO_OUTPUT_CHANGED, data, &reply); + } +}; + +IMPLEMENT_META_INTERFACE(AudioFlingerClient, "android.media.IAudioFlingerClient"); + +// ---------------------------------------------------------------------- + +#define CHECK_INTERFACE(interface, data, reply) \ + do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ + LOGW("Call incorrectly routed to " #interface); \ + return PERMISSION_DENIED; \ + } } while (0) + +status_t BnAudioFlingerClient::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch(code) { + case AUDIO_OUTPUT_CHANGED: { + CHECK_INTERFACE(IAudioFlingerClient, data, reply); + uint32_t frameCount = data.readInt32(); + uint32_t samplingRate = data.readInt32(); + uint32_t latency = data.readInt32(); + audioOutputChanged(frameCount, samplingRate, latency); + return NO_ERROR; + } break; + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +// ---------------------------------------------------------------------------- + +}; // namespace android diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp index f0edf88..ead24d4 100644 --- a/media/libmedia/JetPlayer.cpp +++ b/media/libmedia/JetPlayer.cpp @@ -214,12 +214,15 @@ int JetPlayer::render() { } p += count * pLibConfig->numChannels; num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM); + + // send events that were generated (if any) to the event callback + fireEventsFromJetQueue(); } // update playback state //LOGV("JetPlayer::render(): updating state"); JET_Status(mEasData, &mJetStatus); - fireEventOnStatusChange(); + fireUpdateOnStatusChange(); mPaused = mJetStatus.paused; mMutex.unlock(); // UNLOCK ]]]]]]]] ----------------------------------- @@ -261,9 +264,9 @@ threadExit: //------------------------------------------------------------------------------------------------- -// fire up an event if any of the status fields has changed +// fire up an update if any of the status fields has changed // precondition: mMutex locked -void JetPlayer::fireEventOnStatusChange() +void JetPlayer::fireUpdateOnStatusChange() { if( (mJetStatus.currentUserID != mPreviousJetStatus.currentUserID) ||(mJetStatus.segmentRepeatCount != mPreviousJetStatus.segmentRepeatCount) ) { @@ -303,9 +306,31 @@ void JetPlayer::fireEventOnStatusChange() //------------------------------------------------------------------------------------------------- -int JetPlayer::openFile(const char* path) +// fire up all the JET events in the JET engine queue (until the queue is empty) +// precondition: mMutex locked +void JetPlayer::fireEventsFromJetQueue() +{ + if(!mEventCallback) { + // no callback, just empty the event queue + while (JET_GetEvent(mEasData, NULL, NULL)) { } + return; + } + + EAS_U32 rawEvent; + while (JET_GetEvent(mEasData, &rawEvent, NULL)) { + mEventCallback( + JetPlayer::JET_EVENT, + rawEvent, + -1, + mJavaJetPlayerRef); + } +} + + +//------------------------------------------------------------------------------------------------- +int JetPlayer::loadFromFile(const char* path) { - LOGV("JetPlayer::openFile(): path=%s", path); + LOGV("JetPlayer::loadFromFile(): path=%s", path); Mutex::Autolock lock(mMutex); @@ -326,6 +351,29 @@ int JetPlayer::openFile(const char* path) return( result ); } + +//------------------------------------------------------------------------------------------------- +int JetPlayer::loadFromFD(const int fd, const long long offset, const long long length) +{ + LOGV("JetPlayer::loadFromFD(): fd=%d offset=%lld length=%lld", fd, offset, length); + + Mutex::Autolock lock(mMutex); + + mEasJetFileLoc = (EAS_FILE_LOCATOR) malloc(sizeof(EAS_FILE)); + mEasJetFileLoc->fd = fd; + mEasJetFileLoc->offset = offset; + mEasJetFileLoc->length = length; + mEasJetFileLoc->path = NULL; + + EAS_RESULT result = JET_OpenFile(mEasData, mEasJetFileLoc); + if(result != EAS_SUCCESS) + mState = EAS_STATE_ERROR; + else + mState = EAS_STATE_OPEN; + return( result ); +} + + //------------------------------------------------------------------------------------------------- int JetPlayer::closeFile() { @@ -348,7 +396,7 @@ int JetPlayer::play() JET_Status(mEasData, &mJetStatus); this->dumpJetStatus(&mJetStatus); - fireEventOnStatusChange(); + fireUpdateOnStatusChange(); // wake up render thread LOGV("JetPlayer::play(): wakeup render thread"); @@ -368,7 +416,7 @@ int JetPlayer::pause() JET_Status(mEasData, &mJetStatus); this->dumpJetStatus(&mJetStatus); - fireEventOnStatusChange(); + fireUpdateOnStatusChange(); return result; @@ -408,6 +456,14 @@ int JetPlayer::triggerClip(int clipId) } //------------------------------------------------------------------------------------------------- +int JetPlayer::clearQueue() +{ + LOGV("JetPlayer::clearQueue"); + Mutex::Autolock lock(mMutex); + return JET_Clear_Queue(mEasData); +} + +//------------------------------------------------------------------------------------------------- void JetPlayer::dump() { LOGE("JetPlayer dump: JET file=%s", mEasJetFileLoc->path); diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp index 584d135..fa36460 100644 --- a/media/libmedia/ToneGenerator.cpp +++ b/media/libmedia/ToneGenerator.cpp @@ -97,10 +97,6 @@ ToneGenerator::ToneGenerator(int streamType, float volume) { LOGE("Unable to marshal AudioFlinger"); return; } - if (AudioSystem::getOutputFrameCount(&mBufferSize) != NO_ERROR) { - LOGE("Unable to marshal AudioFlinger"); - return; - } mStreamType = streamType; mVolume = volume; mpAudioTrack = 0; @@ -275,9 +271,9 @@ bool ToneGenerator::initAudioTrack() { mpAudioTrack = 0; } - // Open audio track in mono, PCM 16bit, default sampling rate, 2 buffers of + // Open audio track in mono, PCM 16bit, default sampling rate, default buffer size mpAudioTrack - = new AudioTrack(mStreamType, 0, AudioSystem::PCM_16_BIT, 1, NUM_PCM_BUFFERS*mBufferSize, 0, audioCallback, this, mBufferSize); + = new AudioTrack(mStreamType, 0, AudioSystem::PCM_16_BIT, 1, 0, 0, audioCallback, this, 0); if (mpAudioTrack == 0) { LOGE("AudioTrack allocation failed"); diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index ebdbda8..31ff507 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -172,7 +172,7 @@ status_t MediaPlayer::setDataSource(const sp& player) status_t MediaPlayer::setDataSource(const char *url) { LOGV("setDataSource(%s)", url); - status_t err = UNKNOWN_ERROR; + status_t err = BAD_VALUE; if (url != NULL) { const sp& service(getMediaPlayerService()); if (service != 0) { @@ -199,7 +199,7 @@ status_t MediaPlayer::setVideoSurface(const sp& surface) { LOGV("setVideoSurface"); Mutex::Autolock _l(mLock); - if (mPlayer == 0) return UNKNOWN_ERROR; + if (mPlayer == 0) return NO_INIT; return mPlayer->setVideoSurface(surface->getISurface()); } @@ -219,7 +219,7 @@ status_t MediaPlayer::prepare() { LOGV("prepare"); Mutex::Autolock _l(mLock); - if (mPrepareSync) return UNKNOWN_ERROR; + if (mPrepareSync) return -EALREADY; mPrepareSync = true; status_t ret = prepareAsync_l(); if (ret != NO_ERROR) return ret; @@ -253,7 +253,6 @@ status_t MediaPlayer::start() status_t ret = mPlayer->start(); if (ret != NO_ERROR) { mCurrentState = MEDIA_PLAYER_STATE_ERROR; - ret = UNKNOWN_ERROR; } else { if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) { LOGV("playback completed immediately following start()"); @@ -275,7 +274,6 @@ status_t MediaPlayer::stop() status_t ret = mPlayer->stop(); if (ret != NO_ERROR) { mCurrentState = MEDIA_PLAYER_STATE_ERROR; - ret = UNKNOWN_ERROR; } else { mCurrentState = MEDIA_PLAYER_STOPPED; } @@ -295,7 +293,6 @@ status_t MediaPlayer::pause() status_t ret = mPlayer->pause(); if (ret != NO_ERROR) { mCurrentState = MEDIA_PLAYER_STATE_ERROR; - ret = UNKNOWN_ERROR; } else { mCurrentState = MEDIA_PLAYER_PAUSED; } @@ -422,7 +419,6 @@ status_t MediaPlayer::reset() if (ret != NO_ERROR) { LOGE("reset() failed with return code (%d)", ret); mCurrentState = MEDIA_PLAYER_STATE_ERROR; - ret = UNKNOWN_ERROR; } else { mCurrentState = MEDIA_PLAYER_IDLE; } diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 5383171..9e366e2 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -61,113 +61,32 @@ pid_t gettid() { return syscall(__NR_gettid);} #undef __KERNEL__ #endif -/* - When USE_SIGBUS_HANDLER is set to 1, a handler for SIGBUS will be - installed, which allows us to recover when there is a read error - when accessing an mmap'ed file. However, since the kernel folks - don't seem to like it when non kernel folks install signal handlers - in their own process, this is currently disabled. - Without the handler, the process hosting this service will die and - then be restarted. This is mostly OK right now because the process is - not being shared with any other services, and clients of the service - will be notified of its death in their MediaPlayer.onErrorListener - callback, assuming they have installed one, and can then attempt to - do their own recovery. - It does open us up to a DOS attack against the media server, where - a malicious application can trivially force the media server to - restart continuously. -*/ -#define USE_SIGBUS_HANDLER 0 + +namespace android { // TODO: Temp hack until we can register players -static const char* MIDI_FILE_EXTS[] = -{ - ".mid", - ".smf", - ".xmf", - ".imy", - ".rtttl", - ".rtx", - ".ota" +typedef struct { + const char *extension; + const player_type playertype; +} extmap; +extmap FILE_EXTS [] = { + {".mid", SONIVOX_PLAYER}, + {".midi", SONIVOX_PLAYER}, + {".smf", SONIVOX_PLAYER}, + {".xmf", SONIVOX_PLAYER}, + {".imy", SONIVOX_PLAYER}, + {".rtttl", SONIVOX_PLAYER}, + {".rtx", SONIVOX_PLAYER}, + {".ota", SONIVOX_PLAYER}, + {".ogg", VORBIS_PLAYER}, + {".oga", VORBIS_PLAYER}, }; -namespace android { - // 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; - -static void sigbushandler(int signal, siginfo_t *info, void *context) -{ - char *faultaddr = (char*) info->si_addr; - LOGE("SIGBUS at %p\n", faultaddr); - - struct mediasigbushandler* h = (struct mediasigbushandler*) pthread_getspecific(sigbuskey); - - if (h) { - if (h->len) { - if (faultaddr < h->base || faultaddr >= h->base + h->len) { - // outside specified range, call old handler - if (oldact.sa_flags & SA_SIGINFO) { - oldact.sa_sigaction(signal, info, context); - } else { - oldact.sa_handler(signal); - } - return; - } - } - - // no range specified or address was in range - - if (h->handlesigbus) { - if (h->handlesigbus(info, h)) { - // thread's handler didn't handle the signal - if (oldact.sa_flags & SA_SIGINFO) { - oldact.sa_sigaction(signal, info, context); - } else { - oldact.sa_handler(signal); - } - } - return; - } - - if (h->sigbusvar) { - // map in a zeroed out page so the operation can succeed - long pagesize = sysconf(_SC_PAGE_SIZE); - long pagemask = ~(pagesize - 1); - void * pageaddr = (void*) (((long)(faultaddr)) & pagemask); - - void * bar = mmap( pageaddr, pagesize, PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED, -1, 0); - if (bar == MAP_FAILED) { - LOGE("couldn't map zero page at %p: %s", pageaddr, strerror(errno)); - if (oldact.sa_flags & SA_SIGINFO) { - oldact.sa_sigaction(signal, info, context); - } else { - oldact.sa_handler(signal); - } - return; - } - - LOGE("setting sigbusvar at %p", h->sigbusvar); - *(h->sigbusvar) = 1; - return; - } - } - - LOGE("SIGBUS: no handler, or improperly configured handler (%p)", h); - - if (oldact.sa_flags & SA_SIGINFO) { - oldact.sa_sigaction(signal, info, context); - } else { - oldact.sa_handler(signal); - } - return; -} - void MediaPlayerService::instantiate() { defaultServiceManager()->addService( String16("media.player"), new MediaPlayerService()); @@ -177,25 +96,10 @@ MediaPlayerService::MediaPlayerService() { LOGV("MediaPlayerService created"); mNextConnId = 1; - - pthread_key_create(&sigbuskey, NULL); - - -#if USE_SIGBUS_HANDLER - struct sigaction act; - memset(&act,0, sizeof act); - act.sa_sigaction = sigbushandler; - act.sa_flags = SA_SIGINFO; - sigaction(SIGBUS, &act, &oldact); -#endif } MediaPlayerService::~MediaPlayerService() { -#if USE_SIGBUS_HANDLER - sigaction(SIGBUS, &oldact, NULL); -#endif - pthread_key_delete(sigbuskey); LOGV("MediaPlayerService destroyed"); } @@ -481,7 +385,7 @@ static player_type getPlayerType(int fd, int64_t offset, int64_t length) locator.offset = offset; locator.length = length; EAS_HANDLE eashandle; - if (EAS_OpenFile(easdata, &locator, &eashandle, NULL) == EAS_SUCCESS) { + if (EAS_OpenFile(easdata, &locator, &eashandle) == EAS_SUCCESS) { EAS_CloseFile(easdata, eashandle); EAS_Shutdown(easdata); return SONIVOX_PLAYER; @@ -498,22 +402,16 @@ static player_type getPlayerType(const char* url) // use MidiFile for MIDI extensions int lenURL = strlen(url); - for (int i = 0; i < NELEM(MIDI_FILE_EXTS); ++i) { - int len = strlen(MIDI_FILE_EXTS[i]); + for (int i = 0; i < NELEM(FILE_EXTS); ++i) { + int len = strlen(FILE_EXTS[i].extension); int start = lenURL - len; if (start > 0) { - if (!strncmp(url + start, MIDI_FILE_EXTS[i], len)) { - LOGV("Type is MIDI"); - return SONIVOX_PLAYER; + if (!strncmp(url + start, FILE_EXTS[i].extension, len)) { + return FILE_EXTS[i].playertype; } } } - if (strcmp(url + strlen(url) - 4, ".ogg") == 0) { - LOGV("Type is Vorbis"); - return VORBIS_PLAYER; - } - // Fall through to PV return PV_PLAYER; } @@ -539,7 +437,6 @@ static sp createPlayer(player_type playerType, void* cookie, if (p != NULL) { if (p->initCheck() == NO_ERROR) { p->setNotifyCallback(cookie, notifyFunc); - p->setSigBusHandlerStructTLSKey(sigbuskey); } else { p.clear(); } diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp index cfad66c..7ce2fab 100644 --- a/media/libmediaplayerservice/MidiFile.cpp +++ b/media/libmediaplayerservice/MidiFile.cpp @@ -40,8 +40,6 @@ static pid_t myTid() { return getpid(); } // ---------------------------------------------------------------------------- -extern pthread_key_t EAS_sigbuskey; - namespace android { // ---------------------------------------------------------------------------- @@ -132,7 +130,7 @@ status_t MidiFile::setDataSource(const char* path) mFileLocator.fd = -1; mFileLocator.offset = 0; mFileLocator.length = 0; - EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle, &mMemFailedVar); + EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle); if (result == EAS_SUCCESS) { updateState(); } @@ -148,12 +146,6 @@ status_t MidiFile::setDataSource(const char* path) return NO_ERROR; } -status_t MidiFile::setSigBusHandlerStructTLSKey(pthread_key_t key) -{ - EAS_sigbuskey = key; - return 0; -} - status_t MidiFile::setDataSource(int fd, int64_t offset, int64_t length) { LOGV("MidiFile::setDataSource fd=%d", fd); @@ -168,7 +160,7 @@ status_t MidiFile::setDataSource(int fd, int64_t offset, int64_t length) mFileLocator.fd = dup(fd); mFileLocator.offset = offset; mFileLocator.length = length; - EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle, &mMemFailedVar); + EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle); updateState(); if (result != EAS_SUCCESS) { @@ -332,7 +324,7 @@ status_t MidiFile::getDuration(int* duration) EAS_HANDLE easHandle = NULL; EAS_RESULT result = EAS_Init(&easData); if (result == EAS_SUCCESS) { - result = EAS_OpenFile(easData, &mFileLocator, &easHandle, NULL); + result = EAS_OpenFile(easData, &mFileLocator, &easHandle); } if (result == EAS_SUCCESS) { result = EAS_Prepare(easData, easHandle); @@ -451,8 +443,6 @@ int MidiFile::render() { LOGV("MidiFile::render"); - struct mediasigbushandler sigbushandler; - // allocate render buffer mAudioBuffer = new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * NUM_BUFFERS]; if (!mAudioBuffer) { @@ -468,10 +458,6 @@ int MidiFile::render() { mCondition.signal(); } - sigbushandler.handlesigbus = NULL; - sigbushandler.sigbusvar = mMemFailedVar; - pthread_setspecific(EAS_sigbuskey, &sigbushandler); - while (1) { mMutex.lock(); diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h index 9d2dfdd..302f1cf 100644 --- a/media/libmediaplayerservice/MidiFile.h +++ b/media/libmediaplayerservice/MidiFile.h @@ -30,7 +30,6 @@ public: ~MidiFile(); virtual status_t initCheck(); - virtual status_t setSigBusHandlerStructTLSKey(pthread_key_t key); virtual status_t setDataSource(const char* path); virtual status_t setDataSource(int fd, int64_t offset, int64_t length); virtual status_t setVideoSurface(const sp& surface) { return UNKNOWN_ERROR; } @@ -57,7 +56,6 @@ private: Mutex mMutex; Condition mCondition; - int* mMemFailedVar; EAS_DATA_HANDLE mEasData; EAS_HANDLE mEasHandle; EAS_PCM* mAudioBuffer; diff --git a/media/libmediaplayerservice/VorbisPlayer.cpp b/media/libmediaplayerservice/VorbisPlayer.cpp index 9a64403..009d628 100644 --- a/media/libmediaplayerservice/VorbisPlayer.cpp +++ b/media/libmediaplayerservice/VorbisPlayer.cpp @@ -455,13 +455,15 @@ int VorbisPlayer::render() { current_section = 0; numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, ¤t_section); } else { - sendEvent(MEDIA_PLAYBACK_COMPLETE); mAudioSink->stop(); audioStarted = false; mRender = false; mPaused = true; int endpos = ov_time_tell(&mVorbisFile); + LOGV("send MEDIA_PLAYBACK_COMPLETE"); + sendEvent(MEDIA_PLAYBACK_COMPLETE); + // wait until we're started again LOGV("playback complete - wait for signal"); mCondition.wait(mMutex); -- cgit v1.1 From 7a2146d5807030b2629f347736be5301b61e8811 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Fri, 13 Feb 2009 12:57:50 -0800 Subject: auto import from //branches/cupcake/...@131421 --- include/media/AudioSystem.h | 39 ++++++-- include/media/AudioTrack.h | 15 +-- include/media/IAudioFlinger.h | 13 ++- include/media/IAudioFlingerClient.h | 2 +- include/media/IMediaRecorder.h | 1 + include/media/PVMediaRecorder.h | 1 + include/media/mediarecorder.h | 1 + media/libmedia/AudioRecord.cpp | 18 +--- media/libmedia/AudioSystem.cpp | 103 ++++++++++++++------- media/libmedia/AudioTrack.cpp | 15 ++- media/libmedia/IAudioFlinger.cpp | 47 +++++++--- media/libmedia/IAudioFlingerClient.cpp | 12 +-- media/libmedia/IMediaRecorder.cpp | 29 +++++- media/libmedia/JetPlayer.cpp | 2 +- media/libmedia/ToneGenerator.cpp | 8 +- media/libmedia/mediaplayer.cpp | 2 +- media/libmedia/mediarecorder.cpp | 32 ++++++- media/libmediaplayerservice/MediaPlayerService.cpp | 10 +- .../libmediaplayerservice/MediaRecorderClient.cpp | 11 +++ media/libmediaplayerservice/MediaRecorderClient.h | 1 + media/libmediaplayerservice/MidiFile.cpp | 2 +- media/libmediaplayerservice/VorbisPlayer.cpp | 2 +- 22 files changed, 242 insertions(+), 124 deletions(-) diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index 6bd54ba..7437f65 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -29,8 +29,27 @@ class AudioSystem { public: + enum stream_type { + DEFAULT =-1, + VOICE_CALL = 0, + SYSTEM = 1, + RING = 2, + MUSIC = 3, + ALARM = 4, + NOTIFICATION = 5, + BLUETOOTH_SCO = 6, + NUM_STREAM_TYPES + }; + + enum audio_output_type { + AUDIO_OUTPUT_DEFAULT =-1, + AUDIO_OUTPUT_HARDWARE = 0, + AUDIO_OUTPUT_A2DP = 1, + NUM_AUDIO_OUTPUT_TYPES + }; + enum audio_format { - DEFAULT = 0, + FORMAT_DEFAULT = 0, PCM_16_BIT, PCM_8_BIT, INVALID_FORMAT @@ -96,9 +115,11 @@ public: static float linearToLog(int volume); static int logToLinear(float volume); - static status_t getOutputSamplingRate(int* samplingRate); - static status_t getOutputFrameCount(int* frameCount); - static status_t getOutputLatency(uint32_t* latency); + static status_t getOutputSamplingRate(int* samplingRate, int stream = DEFAULT); + static status_t getOutputFrameCount(int* frameCount, int stream = DEFAULT); + static status_t getOutputLatency(uint32_t* latency, int stream = DEFAULT); + + static bool routedToA2dpOutput(int streamType); static status_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount, size_t* buffSize); @@ -117,9 +138,10 @@ private: virtual void binderDied(const wp& who); // IAudioFlingerClient - virtual void audioOutputChanged(uint32_t frameCount, uint32_t samplingRate, uint32_t latency); + virtual void a2dpEnabledChanged(bool enabled); }; + static int getOutput(int streamType); static sp gAudioFlingerClient; @@ -128,9 +150,10 @@ private: static Mutex gLock; static sp gAudioFlinger; static audio_error_callback gAudioErrorCallback; - static int gOutSamplingRate; - static int gOutFrameCount; - static uint32_t gOutLatency; + static int gOutSamplingRate[NUM_AUDIO_OUTPUT_TYPES]; + static int gOutFrameCount[NUM_AUDIO_OUTPUT_TYPES]; + static uint32_t gOutLatency[NUM_AUDIO_OUTPUT_TYPES]; + static bool gA2dpEnabled; static size_t gInBuffSize; // previous parameters for recording buffer size queries diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h index 5b2bab9..659f5f8 100644 --- a/include/media/AudioTrack.h +++ b/include/media/AudioTrack.h @@ -42,19 +42,6 @@ class audio_track_cblk_t; class AudioTrack { public: - - enum stream_type { - DEFAULT =-1, - VOICE_CALL = 0, - SYSTEM = 1, - RING = 2, - MUSIC = 3, - ALARM = 4, - NOTIFICATION = 5, - BLUETOOTH_SCO = 6, - NUM_STREAM_TYPES - }; - enum channel_index { MONO = 0, LEFT = 0, @@ -128,7 +115,7 @@ public: * Parameters: * * streamType: Select the type of audio stream this track is attached to - * (e.g. AudioTrack::MUSIC). + * (e.g. AudioSystem::MUSIC). * sampleRate: Track sampling rate in Hz. * format: PCM sample format (e.g AudioSystem::PCM_16_BIT for signed * 16 bits per sample). diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h index df601d7..6f13fe0 100644 --- a/include/media/IAudioFlinger.h +++ b/include/media/IAudioFlinger.h @@ -65,11 +65,11 @@ public: /* query the audio hardware state. This state never changes, * and therefore can be cached. */ - virtual uint32_t sampleRate() const = 0; - virtual int channelCount() const = 0; - virtual int format() const = 0; - virtual size_t frameCount() const = 0; - virtual uint32_t latency() const = 0; + virtual uint32_t sampleRate(int output) const = 0; + virtual int channelCount(int output) const = 0; + virtual int format(int output) const = 0; + virtual size_t frameCount(int output) const = 0; + virtual uint32_t latency(int output) const = 0; /* set/get the audio hardware state. This will probably be used by * the preference panel, mostly. @@ -117,6 +117,9 @@ public: // force AudioFlinger thread out of standby virtual void wakeUp() = 0; + + // is A2DP output enabled + virtual bool isA2dpEnabled() const = 0; }; diff --git a/include/media/IAudioFlingerClient.h b/include/media/IAudioFlingerClient.h index 10c3e0f..c3deb0b 100644 --- a/include/media/IAudioFlingerClient.h +++ b/include/media/IAudioFlingerClient.h @@ -32,7 +32,7 @@ public: DECLARE_META_INTERFACE(AudioFlingerClient); // Notifies a change of audio output from/to hardware to/from A2DP. - virtual void audioOutputChanged(uint32_t frameCount, uint32_t samplingRate, uint32_t latency) = 0; + virtual void a2dpEnabledChanged(bool enabled) = 0; }; diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h index 49e45d1..0dff84e 100644 --- a/include/media/IMediaRecorder.h +++ b/include/media/IMediaRecorder.h @@ -38,6 +38,7 @@ public: virtual status_t setVideoEncoder(int ve) = 0; virtual status_t setAudioEncoder(int ae) = 0; virtual status_t setOutputFile(const char* path) = 0; + virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0; virtual status_t setVideoSize(int width, int height) = 0; virtual status_t setVideoFrameRate(int frames_per_second) = 0; virtual status_t prepare() = 0; diff --git a/include/media/PVMediaRecorder.h b/include/media/PVMediaRecorder.h index 5fee0d6..f795d04 100644 --- a/include/media/PVMediaRecorder.h +++ b/include/media/PVMediaRecorder.h @@ -43,6 +43,7 @@ public: status_t setCamera(const sp& camera); status_t setPreviewSurface(const sp& surface); status_t setOutputFile(const char *path); + status_t setOutputFile(int fd, int64_t offset, int64_t length); status_t prepare(); status_t start(); status_t stop(); diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h index a901d32..436e8f1 100644 --- a/include/media/mediarecorder.h +++ b/include/media/mediarecorder.h @@ -102,6 +102,7 @@ public: status_t setVideoEncoder(int ve); status_t setAudioEncoder(int ae); status_t setOutputFile(const char* path); + status_t setOutputFile(int fd, int64_t offset, int64_t length); status_t setVideoSize(int width, int height); status_t setVideoFrameRate(int frames_per_second); status_t prepare(); diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index a987b92..3d39181 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -128,22 +128,8 @@ status_t AudioRecord::set( return BAD_VALUE; } - size_t inputBuffSizeInBytes = -1; - if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &inputBuffSizeInBytes) - != NO_ERROR) { - LOGE("AudioSystem could not query the input buffer size."); - return NO_INIT; - } - if (inputBuffSizeInBytes == 0) { - LOGE("Recording parameters are not supported: sampleRate %d, channelCount %d, format %d", - sampleRate, channelCount, format); - return BAD_VALUE; - } - int frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? 2 : 1); - - // We use 2* size of input buffer for ping pong use of record buffer. - int minFrameCount = 2 * inputBuffSizeInBytes / frameSizeInBytes; - LOGV("AudioRecord::set() minFrameCount = %d", minFrameCount); + // TODO: Get input frame count from hardware. + int minFrameCount = 1024*2; if (frameCount == 0) { frameCount = minFrameCount; diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index cf91105..63dfc3b 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include namespace android { @@ -31,9 +30,10 @@ sp AudioSystem::gAudioFlinger; sp AudioSystem::gAudioFlingerClient; audio_error_callback AudioSystem::gAudioErrorCallback = NULL; // Cached values -int AudioSystem::gOutSamplingRate = 0; -int AudioSystem::gOutFrameCount = 0; -uint32_t AudioSystem::gOutLatency = 0; +int AudioSystem::gOutSamplingRate[NUM_AUDIO_OUTPUT_TYPES]; +int AudioSystem::gOutFrameCount[NUM_AUDIO_OUTPUT_TYPES]; +uint32_t AudioSystem::gOutLatency[NUM_AUDIO_OUTPUT_TYPES]; +bool AudioSystem::gA2dpEnabled; // Cached values for recording queries uint32_t AudioSystem::gPrevInSamplingRate = 16000; int AudioSystem::gPrevInFormat = AudioSystem::PCM_16_BIT; @@ -66,9 +66,12 @@ const sp& AudioSystem::get_audio_flinger() gAudioFlinger = interface_cast(binder); gAudioFlinger->registerClient(gAudioFlingerClient); // Cache frequently accessed parameters - gOutFrameCount = (int)gAudioFlinger->frameCount(); - gOutSamplingRate = (int)gAudioFlinger->sampleRate(); - gOutLatency = gAudioFlinger->latency(); + for (int output = 0; output < NUM_AUDIO_OUTPUT_TYPES; output++) { + gOutFrameCount[output] = (int)gAudioFlinger->frameCount(output); + gOutSamplingRate[output] = (int)gAudioFlinger->sampleRate(output); + gOutLatency[output] = gAudioFlinger->latency(output); + } + gA2dpEnabled = gAudioFlinger->isA2dpEnabled(); } LOGE_IF(gAudioFlinger==0, "no AudioFlinger!?"); return gAudioFlinger; @@ -147,7 +150,7 @@ status_t AudioSystem::getMasterMute(bool* mute) status_t AudioSystem::setStreamVolume(int stream, float value) { - if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) return BAD_VALUE; + if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE; const sp& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; af->setStreamVolume(stream, value); @@ -156,7 +159,7 @@ status_t AudioSystem::setStreamVolume(int stream, float value) status_t AudioSystem::setStreamMute(int stream, bool mute) { - if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) return BAD_VALUE; + if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE; const sp& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; af->setStreamMute(stream, mute); @@ -165,7 +168,7 @@ status_t AudioSystem::setStreamMute(int stream, bool mute) status_t AudioSystem::getStreamVolume(int stream, float* volume) { - if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) return BAD_VALUE; + if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE; const sp& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; *volume = af->streamVolume(stream); @@ -174,7 +177,7 @@ status_t AudioSystem::getStreamVolume(int stream, float* volume) status_t AudioSystem::getStreamMute(int stream, bool* mute) { - if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) return BAD_VALUE; + if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE; const sp& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; *mute = af->streamMute(stream); @@ -252,37 +255,48 @@ int AudioSystem::logToLinear(float volume) return volume ? 100 - int(dBConvertInverse * log(volume) + 0.5) : 0; } -status_t AudioSystem::getOutputSamplingRate(int* samplingRate) +status_t AudioSystem::getOutputSamplingRate(int* samplingRate, int streamType) { - if (gOutSamplingRate == 0) { + int output = getOutput(streamType); + + if (gOutSamplingRate[output] == 0) { const sp& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; // gOutSamplingRate is updated by get_audio_flinger() } - *samplingRate = gOutSamplingRate; + LOGV("getOutputSamplingRate() streamType %d, output %d, sampling rate %d", streamType, output, gOutSamplingRate[output]); + *samplingRate = gOutSamplingRate[output]; return NO_ERROR; } -status_t AudioSystem::getOutputFrameCount(int* frameCount) +status_t AudioSystem::getOutputFrameCount(int* frameCount, int streamType) { - if (gOutFrameCount == 0) { + int output = getOutput(streamType); + + if (gOutFrameCount[output] == 0) { const sp& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; // gOutFrameCount is updated by get_audio_flinger() } - *frameCount = gOutFrameCount; + LOGV("getOutputFrameCount() streamType %d, output %d, frame count %d", streamType, output, gOutFrameCount[output]); + + *frameCount = gOutFrameCount[output]; return NO_ERROR; } -status_t AudioSystem::getOutputLatency(uint32_t* latency) +status_t AudioSystem::getOutputLatency(uint32_t* latency, int streamType) { - if (gOutLatency == 0) { + int output = getOutput(streamType); + + if (gOutLatency[output] == 0) { const sp& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; // gOutLatency is updated by get_audio_flinger() - } - *latency = gOutLatency; + } + LOGV("getOutputLatency() streamType %d, output %d, latency %d", streamType, output, gOutLatency[output]); + + *latency = gOutLatency[output]; return NO_ERROR; } @@ -315,24 +329,23 @@ status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, int format, int ch void AudioSystem::AudioFlingerClient::binderDied(const wp& who) { Mutex::Autolock _l(AudioSystem::gLock); AudioSystem::gAudioFlinger.clear(); - AudioSystem::gOutSamplingRate = 0; - AudioSystem::gOutFrameCount = 0; - AudioSystem::gOutLatency = 0; + + for (int output = 0; output < NUM_AUDIO_OUTPUT_TYPES; output++) { + gOutFrameCount[output] = 0; + gOutSamplingRate[output] = 0; + gOutLatency[output] = 0; + } AudioSystem::gInBuffSize = 0; - + if (gAudioErrorCallback) { gAudioErrorCallback(DEAD_OBJECT); } LOGW("AudioFlinger server died!"); } -void AudioSystem::AudioFlingerClient::audioOutputChanged(uint32_t frameCount, uint32_t samplingRate, uint32_t latency) { - - AudioSystem::gOutFrameCount = frameCount; - AudioSystem::gOutSamplingRate = samplingRate; - AudioSystem::gOutLatency = latency; - - LOGV("AudioFlinger output changed!"); +void AudioSystem::AudioFlingerClient::a2dpEnabledChanged(bool enabled) { + gA2dpEnabled = enabled; + LOGV("AudioFlinger A2DP enabled status changed! %d", enabled); } void AudioSystem::setErrorCallback(audio_error_callback cb) { @@ -340,5 +353,31 @@ void AudioSystem::setErrorCallback(audio_error_callback cb) { gAudioErrorCallback = cb; } +int AudioSystem::getOutput(int streamType) +{ + if (streamType == DEFAULT) { + streamType = MUSIC; + } + if (gA2dpEnabled && routedToA2dpOutput(streamType)) { + return AUDIO_OUTPUT_A2DP; + } else { + return AUDIO_OUTPUT_HARDWARE; + } +} + +bool AudioSystem::routedToA2dpOutput(int streamType) { + switch(streamType) { + case MUSIC: + case VOICE_CALL: + case BLUETOOTH_SCO: + case SYSTEM: + return true; + default: + return false; + } +} + + + }; // namespace android diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 63b2012..1ffad46 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -128,22 +128,21 @@ status_t AudioTrack::set( return NO_INIT; } int afSampleRate; - if (AudioSystem::getOutputSamplingRate(&afSampleRate) != NO_ERROR) { + if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { return NO_INIT; } int afFrameCount; - if (AudioSystem::getOutputFrameCount(&afFrameCount) != NO_ERROR) { + if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) { return NO_INIT; } uint32_t afLatency; - if (AudioSystem::getOutputLatency(&afLatency) != NO_ERROR) { + if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) { return NO_INIT; } - // handle default values first. - if (streamType == DEFAULT) { - streamType = MUSIC; + if (streamType == AudioSystem::DEFAULT) { + streamType = AudioSystem::MUSIC; } if (sampleRate == 0) { sampleRate = afSampleRate; @@ -260,7 +259,7 @@ status_t AudioTrack::set( mMarkerPosition = 0; mNewPosition = 0; mUpdatePeriod = 0; - + return NO_ERROR; } @@ -434,7 +433,7 @@ void AudioTrack::setSampleRate(int rate) { int afSamplingRate; - if (AudioSystem::getOutputSamplingRate(&afSamplingRate) != NO_ERROR) { + if (AudioSystem::getOutputSamplingRate(&afSamplingRate, mStreamType) != NO_ERROR) { return; } // Resampler implementation limits input sampling rate to 2 x output sampling rate. diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 4215820..5cbb25c 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -53,7 +53,8 @@ enum { SET_PARAMETER, REGISTER_CLIENT, GET_INPUTBUFFERSIZE, - WAKE_UP + WAKE_UP, + IS_A2DP_ENABLED }; class BpAudioFlinger : public BpInterface @@ -123,42 +124,47 @@ public: return interface_cast(reply.readStrongBinder()); } - virtual uint32_t sampleRate() const + virtual uint32_t sampleRate(int output) const { Parcel data, reply; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(output); remote()->transact(SAMPLE_RATE, data, &reply); return reply.readInt32(); } - virtual int channelCount() const + virtual int channelCount(int output) const { Parcel data, reply; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(output); remote()->transact(CHANNEL_COUNT, data, &reply); return reply.readInt32(); } - virtual int format() const + virtual int format(int output) const { Parcel data, reply; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(output); remote()->transact(FORMAT, data, &reply); return reply.readInt32(); } - virtual size_t frameCount() const + virtual size_t frameCount(int output) const { Parcel data, reply; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(output); remote()->transact(FRAME_COUNT, data, &reply); return reply.readInt32(); } - virtual uint32_t latency() const + virtual uint32_t latency(int output) const { Parcel data, reply; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(output); remote()->transact(LATENCY, data, &reply); return reply.readInt32(); } @@ -333,6 +339,14 @@ public: remote()->transact(WAKE_UP, data, &reply); return; } + + virtual bool isA2dpEnabled() const + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + remote()->transact(IS_A2DP_ENABLED, data, &reply); + return (bool)reply.readInt32(); + } }; IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger"); @@ -385,27 +399,32 @@ status_t BnAudioFlinger::onTransact( } break; case SAMPLE_RATE: { CHECK_INTERFACE(IAudioFlinger, data, reply); - reply->writeInt32( sampleRate() ); + int output = data.readInt32(); + reply->writeInt32( sampleRate(output) ); return NO_ERROR; } break; case CHANNEL_COUNT: { CHECK_INTERFACE(IAudioFlinger, data, reply); - reply->writeInt32( channelCount() ); + int output = data.readInt32(); + reply->writeInt32( channelCount(output) ); return NO_ERROR; } break; case FORMAT: { CHECK_INTERFACE(IAudioFlinger, data, reply); - reply->writeInt32( format() ); + int output = data.readInt32(); + reply->writeInt32( format(output) ); return NO_ERROR; } break; case FRAME_COUNT: { CHECK_INTERFACE(IAudioFlinger, data, reply); - reply->writeInt32( frameCount() ); + int output = data.readInt32(); + reply->writeInt32( frameCount(output) ); return NO_ERROR; } break; case LATENCY: { CHECK_INTERFACE(IAudioFlinger, data, reply); - reply->writeInt32( latency() ); + int output = data.readInt32(); + reply->writeInt32( latency(output) ); return NO_ERROR; } break; case SET_MASTER_VOLUME: { @@ -519,7 +538,11 @@ status_t BnAudioFlinger::onTransact( wakeUp(); return NO_ERROR; } break; - + case IS_A2DP_ENABLED: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + reply->writeInt32( (int)isA2dpEnabled() ); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp index d956266..5feb11f 100644 --- a/media/libmedia/IAudioFlingerClient.cpp +++ b/media/libmedia/IAudioFlingerClient.cpp @@ -38,13 +38,11 @@ public: { } - void audioOutputChanged(uint32_t frameCount, uint32_t samplingRate, uint32_t latency) + void a2dpEnabledChanged(bool enabled) { Parcel data, reply; data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor()); - data.writeInt32(frameCount); - data.writeInt32(samplingRate); - data.writeInt32(latency); + data.writeInt32((int)enabled); remote()->transact(AUDIO_OUTPUT_CHANGED, data, &reply); } }; @@ -65,10 +63,8 @@ status_t BnAudioFlingerClient::onTransact( switch(code) { case AUDIO_OUTPUT_CHANGED: { CHECK_INTERFACE(IAudioFlingerClient, data, reply); - uint32_t frameCount = data.readInt32(); - uint32_t samplingRate = data.readInt32(); - uint32_t latency = data.readInt32(); - audioOutputChanged(frameCount, samplingRate, latency); + bool enabled = (bool)data.readInt32(); + a2dpEnabledChanged(enabled); return NO_ERROR; } break; default: diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp index 1f6d599..507d03e 100644 --- a/media/libmedia/IMediaRecorder.cpp +++ b/media/libmedia/IMediaRecorder.cpp @@ -39,7 +39,8 @@ enum { SET_OUTPUT_FORMAT, SET_VIDEO_ENCODER, SET_AUDIO_ENCODER, - SET_OUTPUT_FILE, + SET_OUTPUT_FILE_PATH, + SET_OUTPUT_FILE_FD, SET_VIDEO_SIZE, SET_VIDEO_FRAMERATE, SET_PREVIEW_SURFACE, @@ -139,7 +140,18 @@ public: Parcel data, reply; data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); data.writeCString(path); - remote()->transact(SET_OUTPUT_FILE, data, &reply); + remote()->transact(SET_OUTPUT_FILE_PATH, data, &reply); + return reply.readInt32(); + } + + status_t setOutputFile(int fd, int64_t offset, int64_t length) { + LOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + data.writeFileDescriptor(fd); + data.writeInt64(offset); + data.writeInt64(length); + remote()->transact(SET_OUTPUT_FILE_FD, data, &reply); return reply.readInt32(); } @@ -330,13 +342,22 @@ status_t BnMediaRecorder::onTransact( return NO_ERROR; } break; - case SET_OUTPUT_FILE: { - LOGV("SET_OUTPUT_FILE"); + case SET_OUTPUT_FILE_PATH: { + LOGV("SET_OUTPUT_FILE_PATH"); CHECK_INTERFACE(IMediaRecorder, data, reply); const char* path = data.readCString(); reply->writeInt32(setOutputFile(path)); return NO_ERROR; } break; + case SET_OUTPUT_FILE_FD: { + LOGV("SET_OUTPUT_FILE_FD"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + int fd = dup(data.readFileDescriptor()); + int64_t offset = data.readInt64(); + int64_t length = data.readInt64(); + reply->writeInt32(setOutputFile(fd, offset, length)); + return NO_ERROR; + } break; case SET_VIDEO_SIZE: { LOGV("SET_VIDEO_SIZE"); CHECK_INTERFACE(IMediaRecorder, data, reply); diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp index ead24d4..9bd75c2 100644 --- a/media/libmedia/JetPlayer.cpp +++ b/media/libmedia/JetPlayer.cpp @@ -96,7 +96,7 @@ int JetPlayer::init() // create the output AudioTrack mAudioTrack = new AudioTrack(); - mAudioTrack->set(AudioTrack::MUSIC, //TODO parametrize this + mAudioTrack->set(AudioSystem::MUSIC, //TODO parametrize this pLibConfig->sampleRate, 1, // format = PCM 16bits per sample, pLibConfig->numChannels, diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp index fa36460..7fafc56 100644 --- a/media/libmedia/ToneGenerator.cpp +++ b/media/libmedia/ToneGenerator.cpp @@ -93,7 +93,7 @@ ToneGenerator::ToneGenerator(int streamType, float volume) { mState = TONE_IDLE; - if (AudioSystem::getOutputSamplingRate(&mSamplingRate) != NO_ERROR) { + if (AudioSystem::getOutputSamplingRate(&mSamplingRate, streamType) != NO_ERROR) { LOGE("Unable to marshal AudioFlinger"); return; } @@ -182,7 +182,7 @@ bool ToneGenerator::startTone(int toneType) { mLock.lock(); if (mState == TONE_STARTING) { if (mWaitCbkCond.waitRelative(mLock, seconds(1)) != NO_ERROR) { - LOGE("--- timed out"); + LOGE("--- Immediate start timed out"); mState = TONE_IDLE; } } @@ -200,7 +200,7 @@ bool ToneGenerator::startTone(int toneType) { } LOGV("cond received"); } else { - LOGE("--- timed out"); + LOGE("--- Delayed start timed out"); mState = TONE_IDLE; } } @@ -235,7 +235,7 @@ void ToneGenerator::stopTone() { if (lStatus == NO_ERROR) { LOGV("track stop complete, time %d", (unsigned int)(systemTime()/1000000)); } else { - LOGE("--- timed out"); + LOGE("--- Stop timed out"); mState = TONE_IDLE; mpAudioTrack->stop(); } diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index 31ff507..bd8579c 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -82,7 +82,7 @@ MediaPlayer::MediaPlayer() mListener = NULL; mCookie = NULL; mDuration = -1; - mStreamType = AudioTrack::MUSIC; + mStreamType = AudioSystem::MUSIC; mCurrentPosition = -1; mSeekPosition = -1; mCurrentState = MEDIA_PLAYER_IDLE; diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index 6ee4c0d..4ab26ac 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -248,7 +248,33 @@ status_t MediaRecorder::setOutputFile(const char* path) status_t ret = mMediaRecorder->setOutputFile(path); if (OK != ret) { - LOGV("setAudioEncoder failed: %d", ret); + LOGV("setOutputFile failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return UNKNOWN_ERROR; + } + mIsOutputFileSet = true; + return ret; +} + +status_t MediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length) +{ + LOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length); + if(mMediaRecorder == NULL) { + LOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + if (mIsOutputFileSet) { + LOGE("output file has already been set"); + return INVALID_OPERATION; + } + if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { + LOGE("setOutputFile called in an invalid state(%d)", mCurrentState); + return INVALID_OPERATION; + } + + status_t ret = mMediaRecorder->setOutputFile(fd, offset, length); + if (OK != ret) { + LOGV("setOutputFile failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; return UNKNOWN_ERROR; } @@ -306,7 +332,7 @@ status_t MediaRecorder::prepare() return INVALID_OPERATION; } if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { - LOGE("setVideoFrameRate called in an invalid state: %d", mCurrentState); + LOGE("prepare called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } @@ -328,7 +354,7 @@ status_t MediaRecorder::getMaxAmplitude(int* max) return INVALID_OPERATION; } if (mCurrentState & MEDIA_RECORDER_ERROR) { - LOGE("setVideoFrameRate called in an invalid state: %d", mCurrentState); + LOGE("getMaxAmplitude called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 9e366e2..97e3536 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -818,7 +818,7 @@ Exit: MediaPlayerService::AudioOutput::AudioOutput() { mTrack = 0; - mStreamType = AudioTrack::MUSIC; + mStreamType = AudioSystem::MUSIC; mLeftVolume = 1.0; mRightVolume = 1.0; mLatency = 0; @@ -900,15 +900,15 @@ status_t MediaPlayerService::AudioOutput::open(uint32_t sampleRate, int channelC int afFrameCount; int frameCount; - if (AudioSystem::getOutputFrameCount(&afFrameCount) != NO_ERROR) { + if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) { return NO_INIT; } - if (AudioSystem::getOutputSamplingRate(&afSampleRate) != NO_ERROR) { + if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) { return NO_INIT; } - frameCount = (sampleRate*afFrameCount)/afSampleRate; - AudioTrack *t = new AudioTrack(mStreamType, sampleRate, format, channelCount, frameCount*bufferCount); + frameCount = (sampleRate*afFrameCount*bufferCount)/afSampleRate; + AudioTrack *t = new AudioTrack(mStreamType, sampleRate, format, channelCount, frameCount); if ((t == 0) || (t->initCheck() != NO_ERROR)) { LOGE("Unable to create audio track"); delete t; diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp index f326a0e..e8ba17f 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.cpp +++ b/media/libmediaplayerservice/MediaRecorderClient.cpp @@ -121,6 +121,17 @@ status_t MediaRecorderClient::setOutputFile(const char* path) return mRecorder->setOutputFile(path); } +status_t MediaRecorderClient::setOutputFile(int fd, int64_t offset, int64_t length) +{ + LOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length); + Mutex::Autolock lock(mLock); + if (mRecorder == NULL) { + LOGE("recorder is not initialized"); + return NO_INIT; + } + return mRecorder->setOutputFile(fd, offset, length); +} + status_t MediaRecorderClient::setVideoSize(int width, int height) { LOGV("setVideoSize(%dx%d)", width, height); diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h index 3158017..2b80c10 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.h +++ b/media/libmediaplayerservice/MediaRecorderClient.h @@ -36,6 +36,7 @@ public: virtual status_t setVideoEncoder(int ve); virtual status_t setAudioEncoder(int ae); virtual status_t setOutputFile(const char* path); + virtual status_t setOutputFile(int fd, int64_t offset, int64_t length); virtual status_t setVideoSize(int width, int height); virtual status_t setVideoFrameRate(int frames_per_second); virtual status_t prepare(); diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp index 7ce2fab..d03caa5 100644 --- a/media/libmediaplayerservice/MidiFile.cpp +++ b/media/libmediaplayerservice/MidiFile.cpp @@ -58,7 +58,7 @@ static const S_EAS_LIB_CONFIG* pLibConfig = NULL; MidiFile::MidiFile() : mEasData(NULL), mEasHandle(NULL), mAudioBuffer(NULL), mPlayTime(-1), mDuration(-1), mState(EAS_STATE_ERROR), - mStreamType(AudioTrack::MUSIC), mLoop(false), mExit(false), + mStreamType(AudioSystem::MUSIC), mLoop(false), mExit(false), mPaused(false), mRender(false), mTid(-1) { LOGV("constructor"); diff --git a/media/libmediaplayerservice/VorbisPlayer.cpp b/media/libmediaplayerservice/VorbisPlayer.cpp index 009d628..0ad335f 100644 --- a/media/libmediaplayerservice/VorbisPlayer.cpp +++ b/media/libmediaplayerservice/VorbisPlayer.cpp @@ -55,7 +55,7 @@ static status_t STATE_OPEN = 2; VorbisPlayer::VorbisPlayer() : mAudioBuffer(NULL), mPlayTime(-1), mDuration(-1), mState(STATE_ERROR), - mStreamType(AudioTrack::MUSIC), mLoop(false), mAndroidLoop(false), + mStreamType(AudioSystem::MUSIC), mLoop(false), mAndroidLoop(false), mExit(false), mPaused(false), mRender(false), mRenderTid(-1) { LOGV("constructor\n"); -- cgit v1.1 From 25658fd43d150a45fb37734a9f9f27f48bb5c133 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Thu, 19 Feb 2009 10:57:31 -0800 Subject: auto import from //branches/cupcake/...@132276 --- include/media/AudioSystem.h | 11 ++++++++++- media/libmedia/AudioTrack.cpp | 2 +- media/libmedia/JetPlayer.cpp | 11 ++++++++--- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index 7437f65..77c90ba 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -70,7 +70,16 @@ public: ROUTE_BLUETOOTH_SCO = (1 << 2), ROUTE_HEADSET = (1 << 3), ROUTE_BLUETOOTH_A2DP = (1 << 4), - ROUTE_ALL = 0xFFFFFFFF + ROUTE_ALL = -1UL, + }; + + enum audio_in_acoustics { + AGC_ENABLE = 0x0001, + AGC_DISABLE = 0, + NS_ENABLE = 0x0002, + NS_DISABLE = 0, + TX_IIR_ENABLE = 0x0004, + TX_DISABLE = 0 }; /* These are static methods to control the system-wide AudioFlinger diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 1ffad46..f8520a7 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -156,7 +156,7 @@ status_t AudioTrack::set( } // validate parameters - if (((format != AudioSystem::PCM_8_BIT) || mSharedBuffer != 0) && + if (((format != AudioSystem::PCM_8_BIT) || sharedBuffer != 0) && (format != AudioSystem::PCM_16_BIT)) { LOGE("Invalid format"); return BAD_VALUE; diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp index 9bd75c2..2c62104 100644 --- a/media/libmedia/JetPlayer.cpp +++ b/media/libmedia/JetPlayer.cpp @@ -86,8 +86,8 @@ int JetPlayer::init() mState = EAS_STATE_ERROR; return result; } - // init the JET library - result = JET_Init(mEasData, NULL, 0); + // init the JET library with the default app event controller range + result = JET_Init(mEasData, NULL, sizeof(S_JET_CONFIG)); if( result != EAS_SUCCESS) { LOGE("JetPlayer::init(): Error initializing JET library, aborting."); mState = EAS_STATE_ERROR; @@ -200,6 +200,11 @@ int JetPlayer::render() { while (!mRender) { LOGV("JetPlayer::render(): signal wait"); + if (audioStarted) { + mAudioTrack->pause(); + // we have to restart the playback once we start rendering again + audioStarted = false; + } mCondition.wait(mMutex); LOGV("JetPlayer::render(): signal rx'd"); } @@ -315,7 +320,7 @@ void JetPlayer::fireEventsFromJetQueue() while (JET_GetEvent(mEasData, NULL, NULL)) { } return; } - + EAS_U32 rawEvent; while (JET_GetEvent(mEasData, &rawEvent, NULL)) { mEventCallback( -- cgit v1.1 From 925a349b45d1d16eaaca6a1f4827191831271ca0 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Fri, 20 Feb 2009 07:38:31 -0800 Subject: auto import from //branches/cupcake/...@132569 --- media/libmedia/AudioRecord.cpp | 2 +- media/libmedia/ToneGenerator.cpp | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 3d39181..e833c85 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -400,7 +400,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) uint32_t u = cblk->user; uint32_t bufferEnd = cblk->userBase + cblk->frameCount; - if (u + framesReady > bufferEnd) { + if (u + framesReq > bufferEnd) { framesReq = bufferEnd - u; } diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp index 7fafc56..5416629 100644 --- a/media/libmedia/ToneGenerator.cpp +++ b/media/libmedia/ToneGenerator.cpp @@ -175,27 +175,28 @@ bool ToneGenerator::startTone(int toneType) { if (mState == TONE_INIT) { if (prepareWave()) { LOGV("Immediate start, time %d\n", (unsigned int)(systemTime()/1000000)); - + lResult = true; mState = TONE_STARTING; mLock.unlock(); mpAudioTrack->start(); mLock.lock(); if (mState == TONE_STARTING) { + LOGV("Wait for start callback"); if (mWaitCbkCond.waitRelative(mLock, seconds(1)) != NO_ERROR) { LOGE("--- Immediate start timed out"); mState = TONE_IDLE; + lResult = false; } } - - if (mState == TONE_PLAYING) - lResult = true; + } else { + mState == TONE_IDLE; } } else { LOGV("Delayed start\n"); mState = TONE_RESTARTING; if (mWaitCbkCond.waitRelative(mLock, seconds(1)) == NO_ERROR) { - if (mState != TONE_INIT) { + if (mState != TONE_IDLE) { lResult = true; } LOGV("cond received"); @@ -206,7 +207,8 @@ bool ToneGenerator::startTone(int toneType) { } mLock.unlock(); - LOGV("Tone started, time %d\n", (unsigned int)(systemTime()/1000000)); + LOGV_IF(lResult, "Tone started, time %d\n", (unsigned int)(systemTime()/1000000)); + LOGW_IF(!lResult, "Tone start failed!!!, time %d\n", (unsigned int)(systemTime()/1000000)); return lResult; } @@ -457,8 +459,11 @@ audioCallback_EndLoop: if (lpToneGen->prepareWave()) { lpToneGen->mState = TONE_STARTING; } else { - lpToneGen->mState = TONE_INIT; + LOGW("Cbk restarting prepareWave() failed\n"); + lpToneGen->mState = TONE_IDLE; lpToneGen->mpAudioTrack->stop(); + // Force loop exit + lNumSmp = 0; } lSignal = true; break; -- cgit v1.1 From 99ffda877980468a9ae31e013cd10fb3645df1b0 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Mon, 2 Mar 2009 22:54:33 -0800 Subject: auto import from //depot/cupcake/@137055 --- include/media/AudioRecord.h | 9 +- include/media/IMediaRecorder.h | 2 + include/media/PVMediaRecorder.h | 2 + include/media/mediarecorder.h | 39 ++++++-- media/libmedia/AudioRecord.cpp | 25 ++++- media/libmedia/AudioTrack.cpp | 13 ++- media/libmedia/IMediaRecorder.cpp | 22 ++++- media/libmedia/mediarecorder.cpp | 75 ++++++++++++++ media/libmediaplayerservice/MediaPlayerService.cpp | 110 +++++++++++++++++++++ .../libmediaplayerservice/MediaRecorderClient.cpp | 11 +++ media/libmediaplayerservice/MediaRecorderClient.h | 1 + 11 files changed, 293 insertions(+), 16 deletions(-) diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h index dd585c9..ff64855 100644 --- a/include/media/AudioRecord.h +++ b/include/media/AudioRecord.h @@ -125,7 +125,8 @@ public: * channelCount: Number of PCM channels (e.g 2 for stereo). * frameCount: Total size of track PCM buffer in frames. This defines the * latency of the track. - * flags: Reserved for future use. + * flags: A bitmask of acoustic values from enum record_flags. It enables + * AGC, NS, and IIR. * cbf: Callback function. If not null, this function is called periodically * to provide new PCM data. * notificationFrames: The callback function is called each time notificationFrames PCM @@ -133,6 +134,12 @@ public: * user Context for use by the callback receiver. */ + enum record_flags { + RECORD_AGC_ENABLE = AudioSystem::AGC_ENABLE, + RECORD_NS_ENABLE = AudioSystem::NS_ENABLE, + RECORD_IIR_ENABLE = AudioSystem::TX_IIR_ENABLE + }; + AudioRecord(int streamType, uint32_t sampleRate = 0, int format = 0, diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h index 0dff84e..eace996 100644 --- a/include/media/IMediaRecorder.h +++ b/include/media/IMediaRecorder.h @@ -24,6 +24,7 @@ namespace android { class ISurface; class ICamera; +class IMediaPlayerClient; class IMediaRecorder: public IInterface { @@ -41,6 +42,7 @@ public: virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0; virtual status_t setVideoSize(int width, int height) = 0; virtual status_t setVideoFrameRate(int frames_per_second) = 0; + virtual status_t setListener(const sp& listener) = 0; virtual status_t prepare() = 0; virtual status_t getMaxAmplitude(int* max) = 0; virtual status_t start() = 0; diff --git a/include/media/PVMediaRecorder.h b/include/media/PVMediaRecorder.h index f795d04..3315c59 100644 --- a/include/media/PVMediaRecorder.h +++ b/include/media/PVMediaRecorder.h @@ -19,6 +19,7 @@ #define ANDROID_PVMEDIARECORDER_H #include +#include namespace android { @@ -44,6 +45,7 @@ public: status_t setPreviewSurface(const sp& surface); status_t setOutputFile(const char *path); status_t setOutputFile(int fd, int64_t offset, int64_t length); + status_t setListener(const sp& listener); status_t prepare(); status_t start(); status_t stop(); diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h index 436e8f1..8991f08 100644 --- a/include/media/mediarecorder.h +++ b/include/media/mediarecorder.h @@ -19,6 +19,7 @@ #define ANDROID_MEDIARECORDER_H #include +#include namespace android { @@ -87,7 +88,24 @@ enum media_recorder_states { MEDIA_RECORDER_RECORDING = 1 << 4, }; -class MediaRecorder +// The "msg" code passed to the listener in notify. +enum { + MEDIA_RECORDER_EVENT_ERROR = 1 +}; + +enum { + MEDIA_RECORDER_ERROR_UNKNOWN = 1 +}; + +// ---------------------------------------------------------------------------- +// ref-counted object for callbacks +class MediaRecorderListener: virtual public RefBase +{ +public: + virtual void notify(int msg, int ext1, int ext2) = 0; +}; + +class MediaRecorder : public BnMediaPlayerClient { public: MediaRecorder(); @@ -105,6 +123,7 @@ public: status_t setOutputFile(int fd, int64_t offset, int64_t length); status_t setVideoSize(int width, int height); status_t setVideoFrameRate(int frames_per_second); + status_t setListener(const sp& listener); status_t prepare(); status_t getMaxAmplitude(int* max); status_t start(); @@ -113,18 +132,22 @@ public: status_t init(); status_t close(); status_t release(); + void notify(int msg, int ext1, int ext2); private: void doCleanUp(); status_t doReset(); - sp mMediaRecorder; - media_recorder_states mCurrentState; - bool mIsAudioSourceSet; - bool mIsVideoSourceSet; - bool mIsAudioEncoderSet; - bool mIsVideoEncoderSet; - bool mIsOutputFileSet; + sp mMediaRecorder; + sp mListener; + media_recorder_states mCurrentState; + bool mIsAudioSourceSet; + bool mIsVideoSourceSet; + bool mIsAudioEncoderSet; + bool mIsVideoEncoderSet; + bool mIsOutputFileSet; + Mutex mLock; + Mutex mNotifyLock; }; }; // namespace android diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index e833c85..7594ff0 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -128,8 +128,23 @@ status_t AudioRecord::set( return BAD_VALUE; } - // TODO: Get input frame count from hardware. - int minFrameCount = 1024*2; + // validate framecount + size_t inputBuffSizeInBytes = -1; + if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &inputBuffSizeInBytes) + != NO_ERROR) { + LOGE("AudioSystem could not query the input buffer size."); + return NO_INIT; + } + if (inputBuffSizeInBytes == 0) { + LOGE("Recording parameters are not supported: sampleRate %d, channelCount %d, format %d", + sampleRate, channelCount, format); + return BAD_VALUE; + } + int frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? 2 : 1); + + // We use 2* size of input buffer for ping pong use of record buffer. + int minFrameCount = 2 * inputBuffSizeInBytes / frameSizeInBytes; + LOGV("AudioRecord::set() minFrameCount = %d", minFrameCount); if (frameCount == 0) { frameCount = minFrameCount; @@ -144,7 +159,11 @@ status_t AudioRecord::set( // open record channel status_t status; sp record = audioFlinger->openRecord(getpid(), streamType, - sampleRate, format, channelCount, frameCount, flags, &status); + sampleRate, format, + channelCount, + frameCount, + ((uint16_t)flags) << 16, + &status); if (record == 0) { LOGE("AudioFlinger could not create record track, status: %d", status); return status; diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index f8520a7..2274521 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -168,6 +168,8 @@ status_t AudioTrack::set( // Ensure that buffer depth covers at least audio hardware latency uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate); + if (minBufCount < 2) minBufCount = 2; + // When playing from shared buffer, playback will start even if last audioflinger // block is partly filled. if (sharedBuffer != 0 && minBufCount > 1) { @@ -437,8 +439,8 @@ void AudioTrack::setSampleRate(int rate) return; } // Resampler implementation limits input sampling rate to 2 x output sampling rate. + if (rate <= 0) rate = 1; if (rate > afSamplingRate*2) rate = afSamplingRate*2; - if (rate > MAX_SAMPLE_RATE) rate = MAX_SAMPLE_RATE; mCblk->sampleRate = rate; @@ -466,10 +468,15 @@ status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount if (loopStart >= loopEnd || loopEnd - loopStart > mFrameCount) { - LOGW("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %d", loopStart, loopEnd, loopCount, mFrameCount, cblk->user); + LOGE("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %d", loopStart, loopEnd, loopCount, mFrameCount, cblk->user); return BAD_VALUE; } - // TODO handle shared buffer here: limit loop end to framecount + + if ((mSharedBuffer != 0) && (loopEnd > mFrameCount)) { + LOGE("setLoop invalid value: loop markers beyond data: loopStart %d, loopEnd %d, framecount %d", + loopStart, loopEnd, mFrameCount); + return BAD_VALUE; + } cblk->loopStart = loopStart; cblk->loopEnd = loopEnd; diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp index 507d03e..f187bf5 100644 --- a/media/libmedia/IMediaRecorder.cpp +++ b/media/libmedia/IMediaRecorder.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include namespace android { @@ -44,7 +45,8 @@ enum { SET_VIDEO_SIZE, SET_VIDEO_FRAMERATE, SET_PREVIEW_SURFACE, - SET_CAMERA + SET_CAMERA, + SET_LISTENER }; class BpMediaRecorder: public BpInterface @@ -176,6 +178,16 @@ public: return reply.readInt32(); } + status_t setListener(const sp& listener) + { + LOGV("setListener(%p)", listener.get()); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + data.writeStrongBinder(listener->asBinder()); + remote()->transact(SET_LISTENER, data, &reply); + return reply.readInt32(); + } + status_t prepare() { LOGV("prepare"); @@ -373,6 +385,14 @@ status_t BnMediaRecorder::onTransact( reply->writeInt32(setVideoFrameRate(frames_per_second)); return NO_ERROR; } break; + case SET_LISTENER: { + LOGV("SET_LISTENER"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + sp listener = + interface_cast(data.readStrongBinder()); + reply->writeInt32(setListener(listener)); + return NO_ERROR; + } break; case SET_PREVIEW_SURFACE: { LOGV("SET_PREVIEW_SURFACE"); CHECK_INTERFACE(IMediaRecorder, data, reply); diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index 4ab26ac..98aac39 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -58,6 +58,10 @@ status_t MediaRecorder::setPreviewSurface(const sp& surface) LOGE("setPreviewSurface called in an invalid state(%d)", mCurrentState); return INVALID_OPERATION; } + if (!mIsVideoSourceSet) { + LOGE("try to set preview surface without setting the video source first"); + return INVALID_OPERATION; + } status_t ret = mMediaRecorder->setPreviewSurface(surface->getISurface()); if (OK != ret) { @@ -86,6 +90,14 @@ status_t MediaRecorder::init() mCurrentState = MEDIA_RECORDER_ERROR; return UNKNOWN_ERROR; } + + ret = mMediaRecorder->setListener(this); + if (OK != ret) { + LOGV("setListener failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return UNKNOWN_ERROR; + } + mCurrentState = MEDIA_RECORDER_INITIALIZED; return ret; } @@ -167,6 +179,10 @@ status_t MediaRecorder::setOutputFormat(int of) LOGE("setOutputFormat called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } + if (mIsVideoSourceSet && of >= OUTPUT_FORMAT_RAW_AMR) { + LOGE("output format (%d) is meant for audio recording only and incompatible with video recording", of); + return INVALID_OPERATION; + } status_t ret = mMediaRecorder->setOutputFormat(of); if (OK != ret) { @@ -185,6 +201,10 @@ status_t MediaRecorder::setVideoEncoder(int ve) LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } + if (!mIsVideoSourceSet) { + LOGE("try to set the video encoder without setting the video source first"); + return INVALID_OPERATION; + } if (mIsVideoEncoderSet) { LOGE("video encoder has already been set"); return INVALID_OPERATION; @@ -211,6 +231,10 @@ status_t MediaRecorder::setAudioEncoder(int ae) LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } + if (!mIsAudioSourceSet) { + LOGE("try to set the audio encoder without setting the audio source first"); + return INVALID_OPERATION; + } if (mIsAudioEncoderSet) { LOGE("audio encoder has already been set"); return INVALID_OPERATION; @@ -293,6 +317,10 @@ status_t MediaRecorder::setVideoSize(int width, int height) LOGE("setVideoSize called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } + if (!mIsVideoSourceSet) { + LOGE("try to set video size without setting video source first"); + return INVALID_OPERATION; + } status_t ret = mMediaRecorder->setVideoSize(width, height); if (OK != ret) { @@ -314,6 +342,10 @@ status_t MediaRecorder::setVideoFrameRate(int frames_per_second) LOGE("setVideoFrameRate called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } + if (!mIsVideoSourceSet) { + LOGE("try to set video frame rate without setting video source first"); + return INVALID_OPERATION; + } status_t ret = mMediaRecorder->setVideoFrameRate(frames_per_second); if (OK != ret) { @@ -335,6 +367,23 @@ status_t MediaRecorder::prepare() LOGE("prepare called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } + if (mIsAudioSourceSet != mIsAudioEncoderSet) { + if (mIsAudioSourceSet) { + LOGE("audio source is set, but audio encoder is not set"); + } else { // must not happen, since setAudioEncoder checks this already + LOGE("audio encoder is set, but audio source is not set"); + } + return INVALID_OPERATION; + } + + if (mIsVideoSourceSet != mIsVideoEncoderSet) { + if (mIsVideoSourceSet) { + LOGE("video source is set, but video encoder is not set"); + } else { // must not happen, since setVideoEncoder checks this already + LOGE("video encoder is set, but video source is not set"); + } + return INVALID_OPERATION; + } status_t ret = mMediaRecorder->prepare(); if (OK != ret) { @@ -538,5 +587,31 @@ MediaRecorder::~MediaRecorder() } } +status_t MediaRecorder::setListener(const sp& listener) +{ + LOGV("setListener"); + Mutex::Autolock _l(mLock); + mListener = listener; + + return NO_ERROR; +} + +void MediaRecorder::notify(int msg, int ext1, int ext2) +{ + LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2); + + sp listener; + mLock.lock(); + listener = mListener; + mLock.unlock(); + + if (listener != NULL) { + Mutex::Autolock _l(mNotifyLock); + LOGV("callback application"); + listener->notify(msg, ext1, ext2); + LOGV("back from callback"); + } +} + }; // namespace android diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 97e3536..40705c6 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -218,6 +218,104 @@ static int myTid() { #endif } +#if defined(__arm__) +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); + +void memStatus(int fd, const Vector& args) +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + + typedef struct { + size_t size; + size_t dups; + intptr_t * backtrace; + } AllocEntry; + + uint8_t *info = NULL; + size_t overallSize = 0; + size_t infoSize = 0; + size_t totalMemory = 0; + size_t backtraceSize = 0; + + get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize); + if (info) { + uint8_t *ptr = info; + size_t count = overallSize / infoSize; + + snprintf(buffer, SIZE, " Allocation count %i\n", count); + result.append(buffer); + + AllocEntry * entries = new AllocEntry[count]; + + for (size_t i = 0; i < count; i++) { + // Each entry should be size_t, size_t, intptr_t[backtraceSize] + AllocEntry *e = &entries[i]; + + e->size = *reinterpret_cast(ptr); + ptr += sizeof(size_t); + + e->dups = *reinterpret_cast(ptr); + ptr += sizeof(size_t); + + e->backtrace = reinterpret_cast(ptr); + ptr += sizeof(intptr_t) * backtraceSize; + } + + // Now we need to sort the entries. They come sorted by size but + // not by stack trace which causes problems using diff. + bool moved; + do { + moved = false; + for (size_t i = 0; i < (count - 1); i++) { + AllocEntry *e1 = &entries[i]; + AllocEntry *e2 = &entries[i+1]; + + bool swap = e1->size < e2->size; + if (e1->size == e2->size) { + for(size_t j = 0; j < backtraceSize; j++) { + if (e1->backtrace[j] == e2->backtrace[j]) { + continue; + } + swap = e1->backtrace[j] < e2->backtrace[j]; + break; + } + } + if (swap) { + AllocEntry t = entries[i]; + entries[i] = entries[i+1]; + entries[i+1] = t; + moved = true; + } + } + } while (moved); + + for (size_t i = 0; i < count; i++) { + AllocEntry *e = &entries[i]; + + snprintf(buffer, SIZE, "size %8i, dup %4i", e->size, e->dups); + result.append(buffer); + for (size_t ct = 0; (ct < backtraceSize) && e->backtrace[ct]; ct++) { + if (ct) { + result.append(", "); + } + snprintf(buffer, SIZE, "0x%08x", e->backtrace[ct]); + result.append(buffer); + } + result.append("\n"); + } + + delete[] entries; + free_malloc_leak_info(info); + } + + write(fd, result.string(), result.size()); +} +#endif + status_t MediaPlayerService::dump(int fd, const Vector& args) { const size_t SIZE = 256; @@ -300,6 +398,18 @@ status_t MediaPlayerService::dump(int fd, const Vector& args) result.append(buffer); result.append("\n"); } + +#if defined(__arm__) + bool dumpMem = false; + for (size_t i = 0; i < args.size(); i++) { + if (args[i] == String16("-m")) { + dumpMem = true; + } + } + if (dumpMem) { + memStatus(fd, args); + } +#endif } write(fd, result.string(), result.size()); return NO_ERROR; diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp index e8ba17f..4b45acb 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.cpp +++ b/media/libmediaplayerservice/MediaRecorderClient.cpp @@ -258,5 +258,16 @@ MediaRecorderClient::~MediaRecorderClient() release(); } +status_t MediaRecorderClient::setListener(const sp& listener) +{ + LOGV("setListener"); + Mutex::Autolock lock(mLock); + if (mRecorder == NULL) { + LOGE("recorder is not initialized"); + return NO_INIT; + } + return mRecorder->setListener(listener); +} + }; // namespace android diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h index 2b80c10..93fd802 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.h +++ b/media/libmediaplayerservice/MediaRecorderClient.h @@ -39,6 +39,7 @@ public: virtual status_t setOutputFile(int fd, int64_t offset, int64_t length); virtual status_t setVideoSize(int width, int height); virtual status_t setVideoFrameRate(int frames_per_second); + virtual status_t setListener(const sp& listener); virtual status_t prepare(); virtual status_t getMaxAmplitude(int* max); virtual status_t start(); -- cgit v1.1 From ad04d9201452001dbaac4349f084cc9316190b89 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Tue, 3 Mar 2009 14:04:24 -0800 Subject: auto import from //depot/cupcake/@132589 --- include/media/AudioRecord.h | 9 +- include/media/IMediaRecorder.h | 2 - include/media/PVMediaRecorder.h | 2 - include/media/mediarecorder.h | 39 ++------ media/libmedia/AudioRecord.cpp | 25 +---- media/libmedia/AudioTrack.cpp | 13 +-- media/libmedia/IMediaRecorder.cpp | 22 +---- media/libmedia/mediarecorder.cpp | 75 -------------- media/libmediaplayerservice/MediaPlayerService.cpp | 110 --------------------- .../libmediaplayerservice/MediaRecorderClient.cpp | 11 --- media/libmediaplayerservice/MediaRecorderClient.h | 1 - 11 files changed, 16 insertions(+), 293 deletions(-) diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h index ff64855..dd585c9 100644 --- a/include/media/AudioRecord.h +++ b/include/media/AudioRecord.h @@ -125,8 +125,7 @@ public: * channelCount: Number of PCM channels (e.g 2 for stereo). * frameCount: Total size of track PCM buffer in frames. This defines the * latency of the track. - * flags: A bitmask of acoustic values from enum record_flags. It enables - * AGC, NS, and IIR. + * flags: Reserved for future use. * cbf: Callback function. If not null, this function is called periodically * to provide new PCM data. * notificationFrames: The callback function is called each time notificationFrames PCM @@ -134,12 +133,6 @@ public: * user Context for use by the callback receiver. */ - enum record_flags { - RECORD_AGC_ENABLE = AudioSystem::AGC_ENABLE, - RECORD_NS_ENABLE = AudioSystem::NS_ENABLE, - RECORD_IIR_ENABLE = AudioSystem::TX_IIR_ENABLE - }; - AudioRecord(int streamType, uint32_t sampleRate = 0, int format = 0, diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h index eace996..0dff84e 100644 --- a/include/media/IMediaRecorder.h +++ b/include/media/IMediaRecorder.h @@ -24,7 +24,6 @@ namespace android { class ISurface; class ICamera; -class IMediaPlayerClient; class IMediaRecorder: public IInterface { @@ -42,7 +41,6 @@ public: virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0; virtual status_t setVideoSize(int width, int height) = 0; virtual status_t setVideoFrameRate(int frames_per_second) = 0; - virtual status_t setListener(const sp& listener) = 0; virtual status_t prepare() = 0; virtual status_t getMaxAmplitude(int* max) = 0; virtual status_t start() = 0; diff --git a/include/media/PVMediaRecorder.h b/include/media/PVMediaRecorder.h index 3315c59..f795d04 100644 --- a/include/media/PVMediaRecorder.h +++ b/include/media/PVMediaRecorder.h @@ -19,7 +19,6 @@ #define ANDROID_PVMEDIARECORDER_H #include -#include namespace android { @@ -45,7 +44,6 @@ public: status_t setPreviewSurface(const sp& surface); status_t setOutputFile(const char *path); status_t setOutputFile(int fd, int64_t offset, int64_t length); - status_t setListener(const sp& listener); status_t prepare(); status_t start(); status_t stop(); diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h index 8991f08..436e8f1 100644 --- a/include/media/mediarecorder.h +++ b/include/media/mediarecorder.h @@ -19,7 +19,6 @@ #define ANDROID_MEDIARECORDER_H #include -#include namespace android { @@ -88,24 +87,7 @@ enum media_recorder_states { MEDIA_RECORDER_RECORDING = 1 << 4, }; -// The "msg" code passed to the listener in notify. -enum { - MEDIA_RECORDER_EVENT_ERROR = 1 -}; - -enum { - MEDIA_RECORDER_ERROR_UNKNOWN = 1 -}; - -// ---------------------------------------------------------------------------- -// ref-counted object for callbacks -class MediaRecorderListener: virtual public RefBase -{ -public: - virtual void notify(int msg, int ext1, int ext2) = 0; -}; - -class MediaRecorder : public BnMediaPlayerClient +class MediaRecorder { public: MediaRecorder(); @@ -123,7 +105,6 @@ public: status_t setOutputFile(int fd, int64_t offset, int64_t length); status_t setVideoSize(int width, int height); status_t setVideoFrameRate(int frames_per_second); - status_t setListener(const sp& listener); status_t prepare(); status_t getMaxAmplitude(int* max); status_t start(); @@ -132,22 +113,18 @@ public: status_t init(); status_t close(); status_t release(); - void notify(int msg, int ext1, int ext2); private: void doCleanUp(); status_t doReset(); - sp mMediaRecorder; - sp mListener; - media_recorder_states mCurrentState; - bool mIsAudioSourceSet; - bool mIsVideoSourceSet; - bool mIsAudioEncoderSet; - bool mIsVideoEncoderSet; - bool mIsOutputFileSet; - Mutex mLock; - Mutex mNotifyLock; + sp mMediaRecorder; + media_recorder_states mCurrentState; + bool mIsAudioSourceSet; + bool mIsVideoSourceSet; + bool mIsAudioEncoderSet; + bool mIsVideoEncoderSet; + bool mIsOutputFileSet; }; }; // namespace android diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 7594ff0..e833c85 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -128,23 +128,8 @@ status_t AudioRecord::set( return BAD_VALUE; } - // validate framecount - size_t inputBuffSizeInBytes = -1; - if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &inputBuffSizeInBytes) - != NO_ERROR) { - LOGE("AudioSystem could not query the input buffer size."); - return NO_INIT; - } - if (inputBuffSizeInBytes == 0) { - LOGE("Recording parameters are not supported: sampleRate %d, channelCount %d, format %d", - sampleRate, channelCount, format); - return BAD_VALUE; - } - int frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? 2 : 1); - - // We use 2* size of input buffer for ping pong use of record buffer. - int minFrameCount = 2 * inputBuffSizeInBytes / frameSizeInBytes; - LOGV("AudioRecord::set() minFrameCount = %d", minFrameCount); + // TODO: Get input frame count from hardware. + int minFrameCount = 1024*2; if (frameCount == 0) { frameCount = minFrameCount; @@ -159,11 +144,7 @@ status_t AudioRecord::set( // open record channel status_t status; sp record = audioFlinger->openRecord(getpid(), streamType, - sampleRate, format, - channelCount, - frameCount, - ((uint16_t)flags) << 16, - &status); + sampleRate, format, channelCount, frameCount, flags, &status); if (record == 0) { LOGE("AudioFlinger could not create record track, status: %d", status); return status; diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 2274521..f8520a7 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -168,8 +168,6 @@ status_t AudioTrack::set( // Ensure that buffer depth covers at least audio hardware latency uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate); - if (minBufCount < 2) minBufCount = 2; - // When playing from shared buffer, playback will start even if last audioflinger // block is partly filled. if (sharedBuffer != 0 && minBufCount > 1) { @@ -439,8 +437,8 @@ void AudioTrack::setSampleRate(int rate) return; } // Resampler implementation limits input sampling rate to 2 x output sampling rate. - if (rate <= 0) rate = 1; if (rate > afSamplingRate*2) rate = afSamplingRate*2; + if (rate > MAX_SAMPLE_RATE) rate = MAX_SAMPLE_RATE; mCblk->sampleRate = rate; @@ -468,15 +466,10 @@ status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount if (loopStart >= loopEnd || loopEnd - loopStart > mFrameCount) { - LOGE("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %d", loopStart, loopEnd, loopCount, mFrameCount, cblk->user); + LOGW("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %d", loopStart, loopEnd, loopCount, mFrameCount, cblk->user); return BAD_VALUE; } - - if ((mSharedBuffer != 0) && (loopEnd > mFrameCount)) { - LOGE("setLoop invalid value: loop markers beyond data: loopStart %d, loopEnd %d, framecount %d", - loopStart, loopEnd, mFrameCount); - return BAD_VALUE; - } + // TODO handle shared buffer here: limit loop end to framecount cblk->loopStart = loopStart; cblk->loopEnd = loopEnd; diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp index f187bf5..507d03e 100644 --- a/media/libmedia/IMediaRecorder.cpp +++ b/media/libmedia/IMediaRecorder.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include namespace android { @@ -45,8 +44,7 @@ enum { SET_VIDEO_SIZE, SET_VIDEO_FRAMERATE, SET_PREVIEW_SURFACE, - SET_CAMERA, - SET_LISTENER + SET_CAMERA }; class BpMediaRecorder: public BpInterface @@ -178,16 +176,6 @@ public: return reply.readInt32(); } - status_t setListener(const sp& listener) - { - LOGV("setListener(%p)", listener.get()); - Parcel data, reply; - data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - data.writeStrongBinder(listener->asBinder()); - remote()->transact(SET_LISTENER, data, &reply); - return reply.readInt32(); - } - status_t prepare() { LOGV("prepare"); @@ -385,14 +373,6 @@ status_t BnMediaRecorder::onTransact( reply->writeInt32(setVideoFrameRate(frames_per_second)); return NO_ERROR; } break; - case SET_LISTENER: { - LOGV("SET_LISTENER"); - CHECK_INTERFACE(IMediaRecorder, data, reply); - sp listener = - interface_cast(data.readStrongBinder()); - reply->writeInt32(setListener(listener)); - return NO_ERROR; - } break; case SET_PREVIEW_SURFACE: { LOGV("SET_PREVIEW_SURFACE"); CHECK_INTERFACE(IMediaRecorder, data, reply); diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index 98aac39..4ab26ac 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -58,10 +58,6 @@ status_t MediaRecorder::setPreviewSurface(const sp& surface) LOGE("setPreviewSurface called in an invalid state(%d)", mCurrentState); return INVALID_OPERATION; } - if (!mIsVideoSourceSet) { - LOGE("try to set preview surface without setting the video source first"); - return INVALID_OPERATION; - } status_t ret = mMediaRecorder->setPreviewSurface(surface->getISurface()); if (OK != ret) { @@ -90,14 +86,6 @@ status_t MediaRecorder::init() mCurrentState = MEDIA_RECORDER_ERROR; return UNKNOWN_ERROR; } - - ret = mMediaRecorder->setListener(this); - if (OK != ret) { - LOGV("setListener failed: %d", ret); - mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; - } - mCurrentState = MEDIA_RECORDER_INITIALIZED; return ret; } @@ -179,10 +167,6 @@ status_t MediaRecorder::setOutputFormat(int of) LOGE("setOutputFormat called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } - if (mIsVideoSourceSet && of >= OUTPUT_FORMAT_RAW_AMR) { - LOGE("output format (%d) is meant for audio recording only and incompatible with video recording", of); - return INVALID_OPERATION; - } status_t ret = mMediaRecorder->setOutputFormat(of); if (OK != ret) { @@ -201,10 +185,6 @@ status_t MediaRecorder::setVideoEncoder(int ve) LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } - if (!mIsVideoSourceSet) { - LOGE("try to set the video encoder without setting the video source first"); - return INVALID_OPERATION; - } if (mIsVideoEncoderSet) { LOGE("video encoder has already been set"); return INVALID_OPERATION; @@ -231,10 +211,6 @@ status_t MediaRecorder::setAudioEncoder(int ae) LOGE("media recorder is not initialized yet"); return INVALID_OPERATION; } - if (!mIsAudioSourceSet) { - LOGE("try to set the audio encoder without setting the audio source first"); - return INVALID_OPERATION; - } if (mIsAudioEncoderSet) { LOGE("audio encoder has already been set"); return INVALID_OPERATION; @@ -317,10 +293,6 @@ status_t MediaRecorder::setVideoSize(int width, int height) LOGE("setVideoSize called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } - if (!mIsVideoSourceSet) { - LOGE("try to set video size without setting video source first"); - return INVALID_OPERATION; - } status_t ret = mMediaRecorder->setVideoSize(width, height); if (OK != ret) { @@ -342,10 +314,6 @@ status_t MediaRecorder::setVideoFrameRate(int frames_per_second) LOGE("setVideoFrameRate called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } - if (!mIsVideoSourceSet) { - LOGE("try to set video frame rate without setting video source first"); - return INVALID_OPERATION; - } status_t ret = mMediaRecorder->setVideoFrameRate(frames_per_second); if (OK != ret) { @@ -367,23 +335,6 @@ status_t MediaRecorder::prepare() LOGE("prepare called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } - if (mIsAudioSourceSet != mIsAudioEncoderSet) { - if (mIsAudioSourceSet) { - LOGE("audio source is set, but audio encoder is not set"); - } else { // must not happen, since setAudioEncoder checks this already - LOGE("audio encoder is set, but audio source is not set"); - } - return INVALID_OPERATION; - } - - if (mIsVideoSourceSet != mIsVideoEncoderSet) { - if (mIsVideoSourceSet) { - LOGE("video source is set, but video encoder is not set"); - } else { // must not happen, since setVideoEncoder checks this already - LOGE("video encoder is set, but video source is not set"); - } - return INVALID_OPERATION; - } status_t ret = mMediaRecorder->prepare(); if (OK != ret) { @@ -587,31 +538,5 @@ MediaRecorder::~MediaRecorder() } } -status_t MediaRecorder::setListener(const sp& listener) -{ - LOGV("setListener"); - Mutex::Autolock _l(mLock); - mListener = listener; - - return NO_ERROR; -} - -void MediaRecorder::notify(int msg, int ext1, int ext2) -{ - LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2); - - sp listener; - mLock.lock(); - listener = mListener; - mLock.unlock(); - - if (listener != NULL) { - Mutex::Autolock _l(mNotifyLock); - LOGV("callback application"); - listener->notify(msg, ext1, ext2); - LOGV("back from callback"); - } -} - }; // namespace android diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 40705c6..97e3536 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -218,104 +218,6 @@ static int myTid() { #endif } -#if defined(__arm__) -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); - -void memStatus(int fd, const Vector& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - - typedef struct { - size_t size; - size_t dups; - intptr_t * backtrace; - } AllocEntry; - - uint8_t *info = NULL; - size_t overallSize = 0; - size_t infoSize = 0; - size_t totalMemory = 0; - size_t backtraceSize = 0; - - get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize); - if (info) { - uint8_t *ptr = info; - size_t count = overallSize / infoSize; - - snprintf(buffer, SIZE, " Allocation count %i\n", count); - result.append(buffer); - - AllocEntry * entries = new AllocEntry[count]; - - for (size_t i = 0; i < count; i++) { - // Each entry should be size_t, size_t, intptr_t[backtraceSize] - AllocEntry *e = &entries[i]; - - e->size = *reinterpret_cast(ptr); - ptr += sizeof(size_t); - - e->dups = *reinterpret_cast(ptr); - ptr += sizeof(size_t); - - e->backtrace = reinterpret_cast(ptr); - ptr += sizeof(intptr_t) * backtraceSize; - } - - // Now we need to sort the entries. They come sorted by size but - // not by stack trace which causes problems using diff. - bool moved; - do { - moved = false; - for (size_t i = 0; i < (count - 1); i++) { - AllocEntry *e1 = &entries[i]; - AllocEntry *e2 = &entries[i+1]; - - bool swap = e1->size < e2->size; - if (e1->size == e2->size) { - for(size_t j = 0; j < backtraceSize; j++) { - if (e1->backtrace[j] == e2->backtrace[j]) { - continue; - } - swap = e1->backtrace[j] < e2->backtrace[j]; - break; - } - } - if (swap) { - AllocEntry t = entries[i]; - entries[i] = entries[i+1]; - entries[i+1] = t; - moved = true; - } - } - } while (moved); - - for (size_t i = 0; i < count; i++) { - AllocEntry *e = &entries[i]; - - snprintf(buffer, SIZE, "size %8i, dup %4i", e->size, e->dups); - result.append(buffer); - for (size_t ct = 0; (ct < backtraceSize) && e->backtrace[ct]; ct++) { - if (ct) { - result.append(", "); - } - snprintf(buffer, SIZE, "0x%08x", e->backtrace[ct]); - result.append(buffer); - } - result.append("\n"); - } - - delete[] entries; - free_malloc_leak_info(info); - } - - write(fd, result.string(), result.size()); -} -#endif - status_t MediaPlayerService::dump(int fd, const Vector& args) { const size_t SIZE = 256; @@ -398,18 +300,6 @@ status_t MediaPlayerService::dump(int fd, const Vector& args) result.append(buffer); result.append("\n"); } - -#if defined(__arm__) - bool dumpMem = false; - for (size_t i = 0; i < args.size(); i++) { - if (args[i] == String16("-m")) { - dumpMem = true; - } - } - if (dumpMem) { - memStatus(fd, args); - } -#endif } write(fd, result.string(), result.size()); return NO_ERROR; diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp index 4b45acb..e8ba17f 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.cpp +++ b/media/libmediaplayerservice/MediaRecorderClient.cpp @@ -258,16 +258,5 @@ MediaRecorderClient::~MediaRecorderClient() release(); } -status_t MediaRecorderClient::setListener(const sp& listener) -{ - LOGV("setListener"); - Mutex::Autolock lock(mLock); - if (mRecorder == NULL) { - LOGE("recorder is not initialized"); - return NO_INIT; - } - return mRecorder->setListener(listener); -} - }; // namespace android diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h index 93fd802..2b80c10 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.h +++ b/media/libmediaplayerservice/MediaRecorderClient.h @@ -39,7 +39,6 @@ public: virtual status_t setOutputFile(int fd, int64_t offset, int64_t length); virtual status_t setVideoSize(int width, int height); virtual status_t setVideoFrameRate(int frames_per_second); - virtual status_t setListener(const sp& listener); virtual status_t prepare(); virtual status_t getMaxAmplitude(int* max); virtual status_t start(); -- cgit v1.1 From 15f767b960b38059a74a42a33e16d8df2aec8bc1 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Tue, 3 Mar 2009 18:28:45 -0800 Subject: auto import from //depot/cupcake/@135843 --- include/media/AudioRecord.h | 337 ------- include/media/AudioSystem.h | 177 ---- include/media/AudioTrack.h | 419 -------- include/media/IAudioFlinger.h | 141 --- include/media/IAudioFlingerClient.h | 55 - include/media/IAudioRecord.h | 68 -- include/media/IAudioTrack.h | 84 -- include/media/IMediaMetadataRetriever.h | 56 -- include/media/IMediaPlayer.h | 64 -- include/media/IMediaPlayerClient.h | 48 - include/media/IMediaPlayerService.h | 60 -- include/media/IMediaRecorder.h | 68 -- include/media/JetPlayer.h | 107 -- include/media/MediaMetadataRetrieverInterface.h | 52 - include/media/MediaPlayerInterface.h | 126 --- include/media/PVMediaRecorder.h | 63 -- include/media/PVMetadataRetriever.h | 51 - include/media/PVPlayer.h | 81 -- include/media/ToneGenerator.h | 176 ---- include/media/mediametadataretriever.h | 95 -- include/media/mediaplayer.h | 144 --- include/media/mediarecorder.h | 132 --- include/media/mediascanner.h | 85 -- include/media/thread_init.h | 25 - include/private/media/AudioTrackShared.h | 83 -- include/private/media/VideoFrame.h | 127 --- include/private/opengles/gl_context.h | 632 ------------ include/private/ui/LayerState.h | 75 -- include/private/ui/SharedState.h | 168 ---- include/private/ui/SurfaceFlingerSynchro.h | 76 -- include/private/utils/Static.h | 58 -- include/private/utils/binder_module.h | 148 --- include/private/utils/futex_synchro.h | 60 -- media/libmedia/Android.mk | 39 - media/libmedia/AudioRecord.cpp | 555 ---------- media/libmedia/AudioSystem.cpp | 383 ------- media/libmedia/AudioTrack.cpp | 1011 ------------------- media/libmedia/IAudioFlinger.cpp | 553 ---------- media/libmedia/IAudioFlingerClient.cpp | 77 -- media/libmedia/IAudioRecord.cpp | 100 -- media/libmedia/IAudioTrack.cpp | 140 --- media/libmedia/IMediaMetadataRetriever.cpp | 218 ---- media/libmedia/IMediaPlayer.cpp | 275 ----- media/libmedia/IMediaPlayerClient.cpp | 77 -- media/libmedia/IMediaPlayerService.cpp | 198 ---- media/libmedia/IMediaRecorder.cpp | 397 -------- media/libmedia/JetPlayer.cpp | 489 --------- media/libmedia/MODULE_LICENSE_APACHE2 | 0 media/libmedia/NOTICE | 190 ---- media/libmedia/ToneGenerator.cpp | 730 -------------- media/libmedia/mediametadataretriever.cpp | 188 ---- media/libmedia/mediaplayer.cpp | 624 ------------ media/libmedia/mediarecorder.cpp | 542 ---------- media/libmediaplayerservice/Android.mk | 36 - media/libmediaplayerservice/MediaPlayerService.cpp | 1063 -------------------- media/libmediaplayerservice/MediaPlayerService.h | 238 ----- .../libmediaplayerservice/MediaRecorderClient.cpp | 262 ----- media/libmediaplayerservice/MediaRecorderClient.h | 65 -- .../MetadataRetrieverClient.cpp | 250 ----- .../MetadataRetrieverClient.h | 71 -- media/libmediaplayerservice/MidiFile.cpp | 558 ---------- media/libmediaplayerservice/MidiFile.h | 77 -- media/libmediaplayerservice/VorbisPlayer.cpp | 529 ---------- media/libmediaplayerservice/VorbisPlayer.h | 91 -- media/mediaserver/Android.mk | 22 - media/mediaserver/main_mediaserver.cpp | 45 - 66 files changed, 14234 deletions(-) delete mode 100644 include/media/AudioRecord.h delete mode 100644 include/media/AudioSystem.h delete mode 100644 include/media/AudioTrack.h delete mode 100644 include/media/IAudioFlinger.h delete mode 100644 include/media/IAudioFlingerClient.h delete mode 100644 include/media/IAudioRecord.h delete mode 100644 include/media/IAudioTrack.h delete mode 100644 include/media/IMediaMetadataRetriever.h delete mode 100644 include/media/IMediaPlayer.h delete mode 100644 include/media/IMediaPlayerClient.h delete mode 100644 include/media/IMediaPlayerService.h delete mode 100644 include/media/IMediaRecorder.h delete mode 100644 include/media/JetPlayer.h delete mode 100644 include/media/MediaMetadataRetrieverInterface.h delete mode 100644 include/media/MediaPlayerInterface.h delete mode 100644 include/media/PVMediaRecorder.h delete mode 100644 include/media/PVMetadataRetriever.h delete mode 100644 include/media/PVPlayer.h delete mode 100644 include/media/ToneGenerator.h delete mode 100644 include/media/mediametadataretriever.h delete mode 100644 include/media/mediaplayer.h delete mode 100644 include/media/mediarecorder.h delete mode 100644 include/media/mediascanner.h delete mode 100644 include/media/thread_init.h delete mode 100644 include/private/media/AudioTrackShared.h delete mode 100644 include/private/media/VideoFrame.h delete mode 100644 include/private/opengles/gl_context.h delete mode 100644 include/private/ui/LayerState.h delete mode 100644 include/private/ui/SharedState.h delete mode 100644 include/private/ui/SurfaceFlingerSynchro.h delete mode 100644 include/private/utils/Static.h delete mode 100644 include/private/utils/binder_module.h delete mode 100644 include/private/utils/futex_synchro.h delete mode 100644 media/libmedia/Android.mk delete mode 100644 media/libmedia/AudioRecord.cpp delete mode 100644 media/libmedia/AudioSystem.cpp delete mode 100644 media/libmedia/AudioTrack.cpp delete mode 100644 media/libmedia/IAudioFlinger.cpp delete mode 100644 media/libmedia/IAudioFlingerClient.cpp delete mode 100644 media/libmedia/IAudioRecord.cpp delete mode 100644 media/libmedia/IAudioTrack.cpp delete mode 100644 media/libmedia/IMediaMetadataRetriever.cpp delete mode 100644 media/libmedia/IMediaPlayer.cpp delete mode 100644 media/libmedia/IMediaPlayerClient.cpp delete mode 100644 media/libmedia/IMediaPlayerService.cpp delete mode 100644 media/libmedia/IMediaRecorder.cpp delete mode 100644 media/libmedia/JetPlayer.cpp delete mode 100644 media/libmedia/MODULE_LICENSE_APACHE2 delete mode 100644 media/libmedia/NOTICE delete mode 100644 media/libmedia/ToneGenerator.cpp delete mode 100644 media/libmedia/mediametadataretriever.cpp delete mode 100644 media/libmedia/mediaplayer.cpp delete mode 100644 media/libmedia/mediarecorder.cpp delete mode 100644 media/libmediaplayerservice/Android.mk delete mode 100644 media/libmediaplayerservice/MediaPlayerService.cpp delete mode 100644 media/libmediaplayerservice/MediaPlayerService.h delete mode 100644 media/libmediaplayerservice/MediaRecorderClient.cpp delete mode 100644 media/libmediaplayerservice/MediaRecorderClient.h delete mode 100644 media/libmediaplayerservice/MetadataRetrieverClient.cpp delete mode 100644 media/libmediaplayerservice/MetadataRetrieverClient.h delete mode 100644 media/libmediaplayerservice/MidiFile.cpp delete mode 100644 media/libmediaplayerservice/MidiFile.h delete mode 100644 media/libmediaplayerservice/VorbisPlayer.cpp delete mode 100644 media/libmediaplayerservice/VorbisPlayer.h delete mode 100644 media/mediaserver/Android.mk delete mode 100644 media/mediaserver/main_mediaserver.cpp diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h deleted file mode 100644 index dd585c9..0000000 --- a/include/media/AudioRecord.h +++ /dev/null @@ -1,337 +0,0 @@ -/* - * 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 AUDIORECORD_H_ -#define AUDIORECORD_H_ - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - - -namespace android { - -// ---------------------------------------------------------------------------- - -class AudioRecord -{ -public: - - enum stream_type { - DEFAULT_INPUT =-1, - MIC_INPUT = 0, - NUM_STREAM_TYPES - }; - - static const int DEFAULT_SAMPLE_RATE = 8000; - - /* Events used by AudioRecord callback function (callback_t). - * - * to keep in sync with frameworks/base/media/java/android/media/AudioRecord.java - */ - enum event_type { - EVENT_MORE_DATA = 0, // Request to reqd more data from PCM buffer. - EVENT_OVERRUN = 1, // PCM buffer overrun occured. - EVENT_MARKER = 2, // Record head is at the specified marker position - // (See setMarkerPosition()). - EVENT_NEW_POS = 3, // Record head is at a new position - // (See setPositionUpdatePeriod()). - }; - - /* Create Buffer on the stack and pass it to obtainBuffer() - * and releaseBuffer(). - */ - - class Buffer - { - public: - enum { - MUTE = 0x00000001 - }; - uint32_t flags; - int channelCount; - int format; - size_t frameCount; - size_t size; - union { - void* raw; - short* i16; - int8_t* i8; - }; - }; - - /* These are static methods to control the system-wide AudioFlinger - * only privileged processes can have access to them - */ - -// static status_t setMasterMute(bool mute); - - /* As a convenience, if a callback is supplied, a handler thread - * is automatically created with the appropriate priority. This thread - * invokes the callback when a new buffer becomes ready or an overrun condition occurs. - * Parameters: - * - * event: type of event notified (see enum AudioRecord::event_type). - * user: Pointer to context for use by the callback receiver. - * info: Pointer to optional parameter according to event type: - * - EVENT_MORE_DATA: pointer to AudioRecord::Buffer struct. The callback must not read - * more bytes than indicated by 'size' field and update 'size' if less bytes are - * read. - * - EVENT_OVERRUN: unused. - * - EVENT_MARKER: pointer to an uin32_t containing the marker position in frames. - * - EVENT_NEW_POS: pointer to an uin32_t containing the new position in frames. - */ - - typedef void (*callback_t)(int event, void* user, void *info); - - /* Constructs an uninitialized AudioRecord. No connection with - * AudioFlinger takes place. - */ - AudioRecord(); - - /* Creates an AudioRecord track and registers it with AudioFlinger. - * Once created, the track needs to be started before it can be used. - * Unspecified values are set to the audio hardware's current - * values. - * - * Parameters: - * - * streamType: Select the audio input to record to (e.g. AudioRecord::MIC_INPUT). - * sampleRate: Track sampling rate in Hz. - * format: PCM sample format (e.g AudioSystem::PCM_16_BIT for signed - * 16 bits per sample). - * channelCount: Number of PCM channels (e.g 2 for stereo). - * frameCount: Total size of track PCM buffer in frames. This defines the - * latency of the track. - * flags: Reserved for future use. - * cbf: Callback function. If not null, this function is called periodically - * to provide new PCM data. - * notificationFrames: The callback function is called each time notificationFrames PCM - * frames are ready in record track output buffer. - * user Context for use by the callback receiver. - */ - - AudioRecord(int streamType, - uint32_t sampleRate = 0, - int format = 0, - int channelCount = 0, - int frameCount = 0, - uint32_t flags = 0, - callback_t cbf = 0, - void* user = 0, - int notificationFrames = 0); - - - /* Terminates the AudioRecord and unregisters it from AudioFlinger. - * Also destroys all resources assotiated with the AudioRecord. - */ - ~AudioRecord(); - - - /* Initialize an uninitialized AudioRecord. - * Returned status (from utils/Errors.h) can be: - * - NO_ERROR: successful intialization - * - INVALID_OPERATION: AudioRecord is already intitialized or record device is already in use - * - BAD_VALUE: invalid parameter (channelCount, format, sampleRate...) - * - NO_INIT: audio server or audio hardware not initialized - * - PERMISSION_DENIED: recording is not allowed for the requesting process - * */ - status_t set(int streamType = 0, - uint32_t sampleRate = 0, - int format = 0, - int channelCount = 0, - int frameCount = 0, - uint32_t flags = 0, - callback_t cbf = 0, - void* user = 0, - int notificationFrames = 0, - bool threadCanCallJava = false); - - - /* Result of constructing the AudioRecord. This must be checked - * before using any AudioRecord API (except for set()), using - * an uninitialized AudioRecord produces undefined results. - * See set() method above for possible return codes. - */ - status_t initCheck() const; - - /* Returns this track's latency in milliseconds. - * This includes the latency due to AudioRecord buffer size - * and audio hardware driver. - */ - uint32_t latency() const; - - /* getters, see constructor */ - - uint32_t sampleRate() const; - int format() const; - int channelCount() const; - uint32_t frameCount() const; - int frameSize() const; - - - /* After it's created the track is not active. Call start() to - * make it active. If set, the callback will start being called. - */ - status_t start(); - - /* Stop a track. If set, the callback will cease being called and - * obtainBuffer returns STOPPED. Note that obtainBuffer() still works - * and will fill up buffers until the pool is exhausted. - */ - status_t stop(); - bool stopped() const; - - /* get sample rate for this track - */ - uint32_t getSampleRate(); - - /* Sets marker position. When record reaches the number of frames specified, - * a callback with event type EVENT_MARKER is called. Calling setMarkerPosition - * with marker == 0 cancels marker notification callback. - * If the AudioRecord has been opened with no callback function associated, - * the operation will fail. - * - * Parameters: - * - * marker: marker position expressed in frames. - * - * Returned status (from utils/Errors.h) can be: - * - NO_ERROR: successful operation - * - INVALID_OPERATION: the AudioRecord has no callback installed. - */ - status_t setMarkerPosition(uint32_t marker); - status_t getMarkerPosition(uint32_t *marker); - - - /* Sets position update period. Every time the number of frames specified has been recorded, - * a callback with event type EVENT_NEW_POS is called. - * Calling setPositionUpdatePeriod with updatePeriod == 0 cancels new position notification - * callback. - * If the AudioRecord has been opened with no callback function associated, - * the operation will fail. - * - * Parameters: - * - * updatePeriod: position update notification period expressed in frames. - * - * Returned status (from utils/Errors.h) can be: - * - NO_ERROR: successful operation - * - INVALID_OPERATION: the AudioRecord has no callback installed. - */ - status_t setPositionUpdatePeriod(uint32_t updatePeriod); - status_t getPositionUpdatePeriod(uint32_t *updatePeriod); - - - /* Gets record head position. The position is the total number of frames - * recorded since record start. - * - * Parameters: - * - * position: Address where to return record head position within AudioRecord buffer. - * - * Returned status (from utils/Errors.h) can be: - * - NO_ERROR: successful operation - * - BAD_VALUE: position is NULL - */ - status_t getPosition(uint32_t *position); - - - - /* obtains a buffer of "frameCount" frames. The buffer must be - * filled entirely. If the track is stopped, obtainBuffer() returns - * STOPPED instead of NO_ERROR as long as there are buffers availlable, - * at which point NO_MORE_BUFFERS is returned. - * Buffers will be returned until the pool (buffercount()) - * is exhausted, at which point obtainBuffer() will either block - * or return WOULD_BLOCK depending on the value of the "blocking" - * parameter. - */ - - enum { - NO_MORE_BUFFERS = 0x80000001, - STOPPED = 1 - }; - - status_t obtainBuffer(Buffer* audioBuffer, int32_t waitCount); - void releaseBuffer(Buffer* audioBuffer); - - - /* As a convenience we provide a read() interface to the audio buffer. - * This is implemented on top of lockBuffer/unlockBuffer. - */ - ssize_t read(void* buffer, size_t size); - -private: - /* copying audio tracks is not allowed */ - AudioRecord(const AudioRecord& other); - AudioRecord& operator = (const AudioRecord& other); - - /* a small internal class to handle the callback */ - class ClientRecordThread : public Thread - { - public: - ClientRecordThread(AudioRecord& receiver, bool bCanCallJava = false); - private: - friend class AudioRecord; - virtual bool threadLoop(); - virtual status_t readyToRun() { return NO_ERROR; } - virtual void onFirstRef() {} - AudioRecord& mReceiver; - Mutex mLock; - }; - - bool processAudioBuffer(const sp& thread); - - sp mAudioFlinger; - sp mAudioRecord; - sp mCblkMemory; - sp mClientRecordThread; - Mutex mRecordThreadLock; - - uint32_t mSampleRate; - uint32_t mFrameCount; - - audio_track_cblk_t* mCblk; - uint8_t mFormat; - uint8_t mChannelCount; - uint8_t mReserved[2]; - status_t mStatus; - uint32_t mLatency; - - volatile int32_t mActive; - - callback_t mCbf; - void* mUserData; - uint32_t mNotificationFrames; - uint32_t mRemainingFrames; - uint32_t mMarkerPosition; - uint32_t mNewPosition; - uint32_t mUpdatePeriod; -}; - -}; // namespace android - -#endif /*AUDIORECORD_H_*/ diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h deleted file mode 100644 index 77c90ba..0000000 --- a/include/media/AudioSystem.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * 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_AUDIOSYSTEM_H_ -#define ANDROID_AUDIOSYSTEM_H_ - -#include -#include -#include - -namespace android { - -typedef void (*audio_error_callback)(status_t err); - -class AudioSystem -{ -public: - - enum stream_type { - DEFAULT =-1, - VOICE_CALL = 0, - SYSTEM = 1, - RING = 2, - MUSIC = 3, - ALARM = 4, - NOTIFICATION = 5, - BLUETOOTH_SCO = 6, - NUM_STREAM_TYPES - }; - - enum audio_output_type { - AUDIO_OUTPUT_DEFAULT =-1, - AUDIO_OUTPUT_HARDWARE = 0, - AUDIO_OUTPUT_A2DP = 1, - NUM_AUDIO_OUTPUT_TYPES - }; - - enum audio_format { - FORMAT_DEFAULT = 0, - PCM_16_BIT, - PCM_8_BIT, - INVALID_FORMAT - }; - - enum audio_mode { - MODE_INVALID = -2, - MODE_CURRENT = -1, - MODE_NORMAL = 0, - MODE_RINGTONE, - MODE_IN_CALL, - NUM_MODES // not a valid entry, denotes end-of-list - }; - - enum audio_routes { - ROUTE_EARPIECE = (1 << 0), - ROUTE_SPEAKER = (1 << 1), - ROUTE_BLUETOOTH_SCO = (1 << 2), - ROUTE_HEADSET = (1 << 3), - ROUTE_BLUETOOTH_A2DP = (1 << 4), - ROUTE_ALL = -1UL, - }; - - enum audio_in_acoustics { - AGC_ENABLE = 0x0001, - AGC_DISABLE = 0, - NS_ENABLE = 0x0002, - NS_DISABLE = 0, - TX_IIR_ENABLE = 0x0004, - TX_DISABLE = 0 - }; - - /* These are static methods to control the system-wide AudioFlinger - * only privileged processes can have access to them - */ - - // routing helper functions - static status_t speakerphone(bool state); - static status_t isSpeakerphoneOn(bool* state); - static status_t bluetoothSco(bool state); - static status_t isBluetoothScoOn(bool* state); - static status_t muteMicrophone(bool state); - static status_t isMicrophoneMuted(bool *state); - - static status_t setMasterVolume(float value); - static status_t setMasterMute(bool mute); - static status_t getMasterVolume(float* volume); - static status_t getMasterMute(bool* mute); - - static status_t setStreamVolume(int stream, float value); - static status_t setStreamMute(int stream, bool mute); - static status_t getStreamVolume(int stream, float* volume); - static status_t getStreamMute(int stream, bool* mute); - - static status_t setMode(int mode); - static status_t getMode(int* mode); - - static status_t setRouting(int mode, uint32_t routes, uint32_t mask); - static status_t getRouting(int mode, uint32_t* routes); - - static status_t isMusicActive(bool *state); - - // Temporary interface, do not use - // TODO: Replace with a more generic key:value get/set mechanism - static status_t setParameter(const char* key, const char* value); - - static void setErrorCallback(audio_error_callback cb); - - // helper function to obtain AudioFlinger service handle - static const sp& get_audio_flinger(); - - static float linearToLog(int volume); - static int logToLinear(float volume); - - static status_t getOutputSamplingRate(int* samplingRate, int stream = DEFAULT); - static status_t getOutputFrameCount(int* frameCount, int stream = DEFAULT); - static status_t getOutputLatency(uint32_t* latency, int stream = DEFAULT); - - static bool routedToA2dpOutput(int streamType); - - static status_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount, - size_t* buffSize); - - // ---------------------------------------------------------------------------- - -private: - - class AudioFlingerClient: public IBinder::DeathRecipient, public BnAudioFlingerClient - { - public: - AudioFlingerClient() { - } - - // DeathRecipient - virtual void binderDied(const wp& who); - - // IAudioFlingerClient - virtual void a2dpEnabledChanged(bool enabled); - - }; - static int getOutput(int streamType); - - static sp gAudioFlingerClient; - - friend class AudioFlingerClient; - - static Mutex gLock; - static sp gAudioFlinger; - static audio_error_callback gAudioErrorCallback; - static int gOutSamplingRate[NUM_AUDIO_OUTPUT_TYPES]; - static int gOutFrameCount[NUM_AUDIO_OUTPUT_TYPES]; - static uint32_t gOutLatency[NUM_AUDIO_OUTPUT_TYPES]; - static bool gA2dpEnabled; - - static size_t gInBuffSize; - // previous parameters for recording buffer size queries - static uint32_t gPrevInSamplingRate; - static int gPrevInFormat; - static int gPrevInChannelCount; - -}; - -}; // namespace android - -#endif /*ANDROID_AUDIOSYSTEM_H_*/ diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h deleted file mode 100644 index 659f5f8..0000000 --- a/include/media/AudioTrack.h +++ /dev/null @@ -1,419 +0,0 @@ -/* - * Copyright (C) 2007 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_AUDIOTRACK_H -#define ANDROID_AUDIOTRACK_H - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - - -namespace android { - -// ---------------------------------------------------------------------------- - -class audio_track_cblk_t; - -// ---------------------------------------------------------------------------- - -class AudioTrack -{ -public: - enum channel_index { - MONO = 0, - LEFT = 0, - RIGHT = 1 - }; - - /* Events used by AudioTrack callback function (audio_track_cblk_t). - */ - enum event_type { - EVENT_MORE_DATA = 0, // Request to write more data to PCM buffer. - EVENT_UNDERRUN = 1, // PCM buffer underrun occured. - EVENT_LOOP_END = 2, // Sample loop end was reached; playback restarted from loop start if loop count was not 0. - EVENT_MARKER = 3, // Playback head is at the specified marker position (See setMarkerPosition()). - EVENT_NEW_POS = 4, // Playback head is at a new position (See setPositionUpdatePeriod()). - EVENT_BUFFER_END = 5 // Playback head is at the end of the buffer. - }; - - /* Create Buffer on the stack and pass it to obtainBuffer() - * and releaseBuffer(). - */ - - class Buffer - { - public: - enum { - MUTE = 0x00000001 - }; - uint32_t flags; - int channelCount; - int format; - size_t frameCount; - size_t size; - union { - void* raw; - short* i16; - int8_t* i8; - }; - }; - - - /* As a convenience, if a callback is supplied, a handler thread - * is automatically created with the appropriate priority. This thread - * invokes the callback when a new buffer becomes availlable or an underrun condition occurs. - * Parameters: - * - * event: type of event notified (see enum AudioTrack::event_type). - * user: Pointer to context for use by the callback receiver. - * info: Pointer to optional parameter according to event type: - * - EVENT_MORE_DATA: pointer to AudioTrack::Buffer struct. The callback must not write - * more bytes than indicated by 'size' field and update 'size' if less bytes are - * written. - * - EVENT_UNDERRUN: unused. - * - EVENT_LOOP_END: pointer to an int indicating the number of loops remaining. - * - EVENT_MARKER: pointer to an uin32_t containing the marker position in frames. - * - EVENT_NEW_POS: pointer to an uin32_t containing the new position in frames. - * - EVENT_BUFFER_END: unused. - */ - - typedef void (*callback_t)(int event, void* user, void *info); - - /* Constructs an uninitialized AudioTrack. No connection with - * AudioFlinger takes place. - */ - AudioTrack(); - - /* Creates an audio track and registers it with AudioFlinger. - * Once created, the track needs to be started before it can be used. - * Unspecified values are set to the audio hardware's current - * values. - * - * Parameters: - * - * streamType: Select the type of audio stream this track is attached to - * (e.g. AudioSystem::MUSIC). - * sampleRate: Track sampling rate in Hz. - * format: PCM sample format (e.g AudioSystem::PCM_16_BIT for signed - * 16 bits per sample). - * channelCount: Number of PCM channels (e.g 2 for stereo). - * frameCount: Total size of track PCM buffer in frames. This defines the - * latency of the track. - * flags: Reserved for future use. - * cbf: Callback function. If not null, this function is called periodically - * to request new PCM data. - * notificationFrames: The callback function is called each time notificationFrames PCM - * frames have been comsumed from track input buffer. - * user Context for use by the callback receiver. - */ - - AudioTrack( int streamType, - uint32_t sampleRate = 0, - int format = 0, - int channelCount = 0, - int frameCount = 0, - uint32_t flags = 0, - callback_t cbf = 0, - void* user = 0, - int notificationFrames = 0); - - /* Creates an audio track and registers it with AudioFlinger. With this constructor, - * The PCM data to be rendered by AudioTrack is passed in a shared memory buffer - * identified by the argument sharedBuffer. This prototype is for static buffer playback. - * PCM data must be present into memory before the AudioTrack is started. - * The Write() and Flush() methods are not supported in this case. - * It is recommented to pass a callback function to be notified of playback end by an - * EVENT_UNDERRUN event. - */ - - AudioTrack( int streamType, - uint32_t sampleRate = 0, - int format = 0, - int channelCount = 0, - const sp& sharedBuffer = 0, - uint32_t flags = 0, - callback_t cbf = 0, - void* user = 0, - int notificationFrames = 0); - - /* Terminates the AudioTrack and unregisters it from AudioFlinger. - * Also destroys all resources assotiated with the AudioTrack. - */ - ~AudioTrack(); - - - /* Initialize an uninitialized AudioTrack. - * Returned status (from utils/Errors.h) can be: - * - NO_ERROR: successful intialization - * - INVALID_OPERATION: AudioTrack is already intitialized - * - BAD_VALUE: invalid parameter (channelCount, format, sampleRate...) - * - NO_INIT: audio server or audio hardware not initialized - * */ - status_t set(int streamType =-1, - uint32_t sampleRate = 0, - int format = 0, - int channelCount = 0, - int frameCount = 0, - uint32_t flags = 0, - callback_t cbf = 0, - void* user = 0, - int notificationFrames = 0, - const sp& sharedBuffer = 0, - bool threadCanCallJava = false); - - - /* Result of constructing the AudioTrack. This must be checked - * before using any AudioTrack API (except for set()), using - * an uninitialized AudioTrack produces undefined results. - * See set() method above for possible return codes. - */ - status_t initCheck() const; - - /* Returns this track's latency in milliseconds. - * This includes the latency due to AudioTrack buffer size, AudioMixer (if any) - * and audio hardware driver. - */ - uint32_t latency() const; - - /* getters, see constructor */ - - int streamType() const; - uint32_t sampleRate() const; - int format() const; - int channelCount() const; - uint32_t frameCount() const; - int frameSize() const; - sp& sharedBuffer(); - - - /* After it's created the track is not active. Call start() to - * make it active. If set, the callback will start being called. - */ - void start(); - - /* Stop a track. If set, the callback will cease being called and - * obtainBuffer returns STOPPED. Note that obtainBuffer() still works - * and will fill up buffers until the pool is exhausted. - */ - void stop(); - bool stopped() const; - - /* flush a stopped track. All pending buffers are discarded. - * This function has no effect if the track is not stoped. - */ - void flush(); - - /* Pause a track. If set, the callback will cease being called and - * obtainBuffer returns STOPPED. Note that obtainBuffer() still works - * and will fill up buffers until the pool is exhausted. - */ - void pause(); - - /* mute or unmutes this track. - * While mutted, the callback, if set, is still called. - */ - void mute(bool); - bool muted() const; - - - /* set volume for this track, mostly used for games' sound effects - */ - void setVolume(float left, float right); - void getVolume(float* left, float* right); - - /* set sample rate for this track, mostly used for games' sound effects - */ - void setSampleRate(int sampleRate); - uint32_t getSampleRate(); - - /* Enables looping and sets the start and end points of looping. - * - * Parameters: - * - * loopStart: loop start expressed as the number of PCM frames played since AudioTrack start. - * loopEnd: loop end expressed as the number of PCM frames played since AudioTrack start. - * loopCount: number of loops to execute. Calling setLoop() with loopCount == 0 cancels any pending or - * active loop. loopCount = -1 means infinite looping. - * - * For proper operation the following condition must be respected: - * (loopEnd-loopStart) <= framecount() - */ - status_t setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount); - status_t getLoop(uint32_t *loopStart, uint32_t *loopEnd, int *loopCount); - - - /* Sets marker position. When playback reaches the number of frames specified, a callback with event - * type EVENT_MARKER is called. Calling setMarkerPosition with marker == 0 cancels marker notification - * callback. - * If the AudioTrack has been opened with no callback function associated, the operation will fail. - * - * Parameters: - * - * marker: marker position expressed in frames. - * - * Returned status (from utils/Errors.h) can be: - * - NO_ERROR: successful operation - * - INVALID_OPERATION: the AudioTrack has no callback installed. - */ - status_t setMarkerPosition(uint32_t marker); - status_t getMarkerPosition(uint32_t *marker); - - - /* Sets position update period. Every time the number of frames specified has been played, - * a callback with event type EVENT_NEW_POS is called. - * Calling setPositionUpdatePeriod with updatePeriod == 0 cancels new position notification - * callback. - * If the AudioTrack has been opened with no callback function associated, the operation will fail. - * - * Parameters: - * - * updatePeriod: position update notification period expressed in frames. - * - * Returned status (from utils/Errors.h) can be: - * - NO_ERROR: successful operation - * - INVALID_OPERATION: the AudioTrack has no callback installed. - */ - status_t setPositionUpdatePeriod(uint32_t updatePeriod); - status_t getPositionUpdatePeriod(uint32_t *updatePeriod); - - - /* Sets playback head position within AudioTrack buffer. The new position is specified - * in number of frames. - * This method must be called with the AudioTrack in paused or stopped state. - * Note that the actual position set is modulo the AudioTrack buffer size in frames. - * Therefore using this method makes sense only when playing a "static" audio buffer - * as opposed to streaming. - * The getPosition() method on the other hand returns the total number of frames played since - * playback start. - * - * Parameters: - * - * position: New playback head position within AudioTrack buffer. - * - * Returned status (from utils/Errors.h) can be: - * - NO_ERROR: successful operation - * - INVALID_OPERATION: the AudioTrack is not stopped. - * - BAD_VALUE: The specified position is beyond the number of frames present in AudioTrack buffer - */ - status_t setPosition(uint32_t position); - status_t getPosition(uint32_t *position); - - /* Forces AudioTrack buffer full condition. When playing a static buffer, this method avoids - * rewriting the buffer before restarting playback after a stop. - * This method must be called with the AudioTrack in paused or stopped state. - * - * Returned status (from utils/Errors.h) can be: - * - NO_ERROR: successful operation - * - INVALID_OPERATION: the AudioTrack is not stopped. - */ - status_t reload(); - - /* obtains a buffer of "frameCount" frames. The buffer must be - * filled entirely. If the track is stopped, obtainBuffer() returns - * STOPPED instead of NO_ERROR as long as there are buffers availlable, - * at which point NO_MORE_BUFFERS is returned. - * Buffers will be returned until the pool (buffercount()) - * is exhausted, at which point obtainBuffer() will either block - * or return WOULD_BLOCK depending on the value of the "blocking" - * parameter. - */ - - enum { - NO_MORE_BUFFERS = 0x80000001, - STOPPED = 1 - }; - - status_t obtainBuffer(Buffer* audioBuffer, int32_t waitCount); - void releaseBuffer(Buffer* audioBuffer); - - - /* As a convenience we provide a write() interface to the audio buffer. - * This is implemented on top of lockBuffer/unlockBuffer. For best - * performance - * - */ - ssize_t write(const void* buffer, size_t size); - - /* - * Dumps the state of an audio track. - */ - status_t dump(int fd, const Vector& args) const; - -private: - /* copying audio tracks is not allowed */ - AudioTrack(const AudioTrack& other); - AudioTrack& operator = (const AudioTrack& other); - - /* a small internal class to handle the callback */ - class AudioTrackThread : public Thread - { - public: - AudioTrackThread(AudioTrack& receiver, bool bCanCallJava = false); - private: - friend class AudioTrack; - virtual bool threadLoop(); - virtual status_t readyToRun(); - virtual void onFirstRef(); - AudioTrack& mReceiver; - Mutex mLock; - }; - - bool processAudioBuffer(const sp& thread); - - sp mAudioFlinger; - sp mAudioTrack; - sp mCblkMemory; - sp mAudioTrackThread; - - float mVolume[2]; - uint32_t mSampleRate; - uint32_t mFrameCount; - - audio_track_cblk_t* mCblk; - uint8_t mStreamType; - uint8_t mFormat; - uint8_t mChannelCount; - uint8_t mMuted; - status_t mStatus; - uint32_t mLatency; - - volatile int32_t mActive; - - callback_t mCbf; - void* mUserData; - uint32_t mNotificationFrames; - sp mSharedBuffer; - int mLoopCount; - uint32_t mRemainingFrames; - uint32_t mMarkerPosition; - uint32_t mNewPosition; - uint32_t mUpdatePeriod; -}; - - -}; // namespace android - -#endif // ANDROID_AUDIOTRACK_H diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h deleted file mode 100644 index 6f13fe0..0000000 --- a/include/media/IAudioFlinger.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2007 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_IAUDIOFLINGER_H -#define ANDROID_IAUDIOFLINGER_H - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - - -namespace android { - -// ---------------------------------------------------------------------------- - -class IAudioFlinger : public IInterface -{ -public: - DECLARE_META_INTERFACE(AudioFlinger); - - /* create an audio track and registers it with AudioFlinger. - * return null if the track cannot be created. - */ - virtual sp createTrack( - pid_t pid, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags, - const sp& sharedBuffer, - status_t *status) = 0; - - virtual sp openRecord( - pid_t pid, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags, - status_t *status) = 0; - - /* query the audio hardware state. This state never changes, - * and therefore can be cached. - */ - virtual uint32_t sampleRate(int output) const = 0; - virtual int channelCount(int output) const = 0; - virtual int format(int output) const = 0; - virtual size_t frameCount(int output) const = 0; - virtual uint32_t latency(int output) const = 0; - - /* set/get the audio hardware state. This will probably be used by - * the preference panel, mostly. - */ - virtual status_t setMasterVolume(float value) = 0; - virtual status_t setMasterMute(bool muted) = 0; - - virtual float masterVolume() const = 0; - virtual bool masterMute() const = 0; - - /* set/get stream type state. This will probably be used by - * the preference panel, mostly. - */ - virtual status_t setStreamVolume(int stream, float value) = 0; - virtual status_t setStreamMute(int stream, bool muted) = 0; - - virtual float streamVolume(int stream) const = 0; - virtual bool streamMute(int stream) const = 0; - - // set/get audio routing - virtual status_t setRouting(int mode, uint32_t routes, uint32_t mask) = 0; - virtual uint32_t getRouting(int mode) const = 0; - - // set/get audio mode - virtual status_t setMode(int mode) = 0; - virtual int getMode() const = 0; - - // mic mute/state - virtual status_t setMicMute(bool state) = 0; - virtual bool getMicMute() const = 0; - - // is a music stream active? - virtual bool isMusicActive() const = 0; - - // pass a generic configuration parameter to libaudio - // Temporary interface, do not use - // TODO: Replace with a more generic key:value get/set mechanism - virtual status_t setParameter(const char* key, const char* value) = 0; - - // register a current process for audio output change notifications - virtual void registerClient(const sp& client) = 0; - - // retrieve the audio recording buffer size - virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount) = 0; - - // force AudioFlinger thread out of standby - virtual void wakeUp() = 0; - - // is A2DP output enabled - virtual bool isA2dpEnabled() const = 0; -}; - - -// ---------------------------------------------------------------------------- - -class BnAudioFlinger : public BnInterface -{ -public: - virtual status_t onTransact( uint32_t code, - const Parcel& data, - Parcel* reply, - uint32_t flags = 0); -}; - -// ---------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_IAUDIOFLINGER_H diff --git a/include/media/IAudioFlingerClient.h b/include/media/IAudioFlingerClient.h deleted file mode 100644 index c3deb0b..0000000 --- a/include/media/IAudioFlingerClient.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2009 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_IAUDIOFLINGERCLIENT_H -#define ANDROID_IAUDIOFLINGERCLIENT_H - - -#include -#include - - -namespace android { - -// ---------------------------------------------------------------------------- - -class IAudioFlingerClient : public IInterface -{ -public: - DECLARE_META_INTERFACE(AudioFlingerClient); - - // Notifies a change of audio output from/to hardware to/from A2DP. - virtual void a2dpEnabledChanged(bool enabled) = 0; - -}; - - -// ---------------------------------------------------------------------------- - -class BnAudioFlingerClient : public BnInterface -{ -public: - virtual status_t onTransact( uint32_t code, - const Parcel& data, - Parcel* reply, - uint32_t flags = 0); -}; - -// ---------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_IAUDIOFLINGERCLIENT_H diff --git a/include/media/IAudioRecord.h b/include/media/IAudioRecord.h deleted file mode 100644 index 9d45d2d..0000000 --- a/include/media/IAudioRecord.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2007 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 IAUDIORECORD_H_ -#define IAUDIORECORD_H_ - -#include -#include - -#include -#include -#include -#include - - -namespace android { - -// ---------------------------------------------------------------------------- - -class IAudioRecord : public IInterface -{ -public: - DECLARE_META_INTERFACE(AudioRecord); - - /* After it's created the track is not active. Call start() to - * make it active. If set, the callback will start being called. - */ - virtual status_t start() = 0; - - /* Stop a track. If set, the callback will cease being called and - * obtainBuffer will return an error. Buffers that are already released - * will be processed, unless flush() is called. - */ - virtual void stop() = 0; - - /* get this tracks control block */ - virtual sp getCblk() const = 0; -}; - -// ---------------------------------------------------------------------------- - -class BnAudioRecord : public BnInterface -{ -public: - virtual status_t onTransact( uint32_t code, - const Parcel& data, - Parcel* reply, - uint32_t flags = 0); -}; - -// ---------------------------------------------------------------------------- - -}; // namespace android - -#endif /*IAUDIORECORD_H_*/ diff --git a/include/media/IAudioTrack.h b/include/media/IAudioTrack.h deleted file mode 100644 index 12f2111..0000000 --- a/include/media/IAudioTrack.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2007 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_IAUDIOTRACK_H -#define ANDROID_IAUDIOTRACK_H - -#include -#include - -#include -#include -#include -#include - - -namespace android { - -// ---------------------------------------------------------------------------- - -class IAudioTrack : public IInterface -{ -public: - DECLARE_META_INTERFACE(AudioTrack); - - /* After it's created the track is not active. Call start() to - * make it active. If set, the callback will start being called. - */ - virtual status_t start() = 0; - - /* Stop a track. If set, the callback will cease being called and - * obtainBuffer will return an error. Buffers that are already released - * will be processed, unless flush() is called. - */ - virtual void stop() = 0; - - /* flush a stopped track. All pending buffers are discarded. - * This function has no effect if the track is not stoped. - */ - virtual void flush() = 0; - - /* mute or unmutes this track. - * While mutted, the callback, if set, is still called. - */ - virtual void mute(bool) = 0; - - /* Pause a track. If set, the callback will cease being called and - * obtainBuffer will return an error. Buffers that are already released - * will be processed, unless flush() is called. - */ - virtual void pause() = 0; - - /* get this tracks control block */ - virtual sp getCblk() const = 0; -}; - -// ---------------------------------------------------------------------------- - -class BnAudioTrack : public BnInterface -{ -public: - virtual status_t onTransact( uint32_t code, - const Parcel& data, - Parcel* reply, - uint32_t flags = 0); -}; - -// ---------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_IAUDIOTRACK_H diff --git a/include/media/IMediaMetadataRetriever.h b/include/media/IMediaMetadataRetriever.h deleted file mode 100644 index c677e83..0000000 --- a/include/media/IMediaMetadataRetriever.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -** -** 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_IMEDIAMETADATARETRIEVER_H -#define ANDROID_IMEDIAMETADATARETRIEVER_H - -#include -#include -#include -#include - -namespace android { - -class IMediaMetadataRetriever: public IInterface -{ -public: - DECLARE_META_INTERFACE(MediaMetadataRetriever); - virtual void disconnect() = 0; - virtual status_t setDataSource(const char* srcUrl) = 0; - virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; - virtual status_t setMode(int mode) = 0; - virtual status_t getMode(int* mode) const = 0; - virtual sp captureFrame() = 0; - virtual sp extractAlbumArt() = 0; - virtual const char* extractMetadata(int keyCode) = 0; -}; - -// ---------------------------------------------------------------------------- - -class BnMediaMetadataRetriever: public BnInterface -{ -public: - virtual status_t onTransact(uint32_t code, - const Parcel& data, - Parcel* reply, - uint32_t flags = 0); -}; - -}; // namespace android - -#endif // ANDROID_IMEDIAMETADATARETRIEVER_H - diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h deleted file mode 100644 index a683e74..0000000 --- a/include/media/IMediaPlayer.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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_IMEDIAPLAYER_H -#define ANDROID_IMEDIAPLAYER_H - -#include -#include -#include - -namespace android { - -class ISurface; - -class IMediaPlayer: public IInterface -{ -public: - DECLARE_META_INTERFACE(MediaPlayer); - - virtual void disconnect() = 0; - - virtual status_t setVideoSurface(const sp& surface) = 0; - virtual status_t prepareAsync() = 0; - virtual status_t start() = 0; - virtual status_t stop() = 0; - virtual status_t pause() = 0; - virtual status_t isPlaying(bool* state) = 0; - virtual status_t seekTo(int msec) = 0; - virtual status_t getCurrentPosition(int* msec) = 0; - virtual status_t getDuration(int* msec) = 0; - virtual status_t reset() = 0; - virtual status_t setAudioStreamType(int type) = 0; - virtual status_t setLooping(int loop) = 0; - virtual status_t setVolume(float leftVolume, float rightVolume) = 0; -}; - -// ---------------------------------------------------------------------------- - -class BnMediaPlayer: public BnInterface -{ -public: - virtual status_t onTransact( uint32_t code, - const Parcel& data, - Parcel* reply, - uint32_t flags = 0); -}; - -}; // namespace android - -#endif // ANDROID_IMEDIAPLAYER_H - diff --git a/include/media/IMediaPlayerClient.h b/include/media/IMediaPlayerClient.h deleted file mode 100644 index 5d32811..0000000 --- a/include/media/IMediaPlayerClient.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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_IMEDIAPLAYERCLIENT_H -#define ANDROID_IMEDIAPLAYERCLIENT_H - -#include -#include -#include - -namespace android { - -class IMediaPlayerClient: public IInterface -{ -public: - DECLARE_META_INTERFACE(MediaPlayerClient); - - virtual void notify(int msg, int ext1, int ext2) = 0; -}; - -// ---------------------------------------------------------------------------- - -class BnMediaPlayerClient: public BnInterface -{ -public: - virtual status_t onTransact( uint32_t code, - const Parcel& data, - Parcel* reply, - uint32_t flags = 0); -}; - -}; // namespace android - -#endif // ANDROID_IMEDIAPLAYERCLIENT_H - diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h deleted file mode 100644 index 8125cc9..0000000 --- a/include/media/IMediaPlayerService.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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_IMEDIAPLAYERSERVICE_H -#define ANDROID_IMEDIAPLAYERSERVICE_H - -#include -#include -#include - -#include -#include -#include - -namespace android { - -class IMediaRecorder; - -class IMediaPlayerService: public IInterface -{ -public: - DECLARE_META_INTERFACE(MediaPlayerService); - - virtual sp createMediaRecorder(pid_t pid) = 0; - virtual sp createMetadataRetriever(pid_t pid) = 0; - - virtual sp create(pid_t pid, const sp& client, const char* url) = 0; - virtual sp create(pid_t pid, const sp& client, int fd, int64_t offset, int64_t length) = 0; - virtual sp decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0; - virtual sp decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0; -}; - -// ---------------------------------------------------------------------------- - -class BnMediaPlayerService: public BnInterface -{ -public: - virtual status_t onTransact( uint32_t code, - const Parcel& data, - Parcel* reply, - uint32_t flags = 0); -}; - -}; // namespace android - -#endif // ANDROID_IMEDIAPLAYERSERVICE_H - diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h deleted file mode 100644 index 0dff84e..0000000 --- a/include/media/IMediaRecorder.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - ** - ** 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_IMEDIARECORDER_H -#define ANDROID_IMEDIARECORDER_H - -#include - -namespace android { - -class ISurface; -class ICamera; - -class IMediaRecorder: public IInterface -{ -public: - DECLARE_META_INTERFACE(MediaRecorder); - - virtual status_t setCamera(const sp& camera) = 0; - virtual status_t setPreviewSurface(const sp& surface) = 0; - virtual status_t setVideoSource(int vs) = 0; - virtual status_t setAudioSource(int as) = 0; - virtual status_t setOutputFormat(int of) = 0; - virtual status_t setVideoEncoder(int ve) = 0; - virtual status_t setAudioEncoder(int ae) = 0; - virtual status_t setOutputFile(const char* path) = 0; - virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0; - virtual status_t setVideoSize(int width, int height) = 0; - virtual status_t setVideoFrameRate(int frames_per_second) = 0; - virtual status_t prepare() = 0; - virtual status_t getMaxAmplitude(int* max) = 0; - virtual status_t start() = 0; - virtual status_t stop() = 0; - virtual status_t reset() = 0; - virtual status_t init() = 0; - virtual status_t close() = 0; - virtual status_t release() = 0; -}; - -// ---------------------------------------------------------------------------- - -class BnMediaRecorder: public BnInterface -{ -public: - virtual status_t onTransact( uint32_t code, - const Parcel& data, - Parcel* reply, - uint32_t flags = 0); -}; - -}; // namespace android - -#endif // ANDROID_IMEDIARECORDER_H - diff --git a/include/media/JetPlayer.h b/include/media/JetPlayer.h deleted file mode 100644 index 16764a9..0000000 --- a/include/media/JetPlayer.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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 JETPLAYER_H_ -#define JETPLAYER_H_ - -#include -#include - -#include -#include -#include "AudioTrack.h" - - -namespace android { - -typedef void (*jetevent_callback)(int eventType, int val1, int val2, void *cookie); - -class JetPlayer { - -public: - - // to keep in sync with the JetPlayer class constants - // defined in frameworks/base/media/java/android/media/JetPlayer.java - static const int JET_EVENT = 1; - static const int JET_USERID_UPDATE = 2; - static const int JET_NUMQUEUEDSEGMENT_UPDATE = 3; - static const int JET_PAUSE_UPDATE = 4; - - JetPlayer(jobject javaJetPlayer, - int maxTracks = 32, - int trackBufferSize = 1200); - ~JetPlayer(); - int init(); - int release(); - - int loadFromFile(const char* url); - int loadFromFD(const int fd, const long long offset, const long long length); - int closeFile(); - int play(); - int pause(); - int queueSegment(int segmentNum, int libNum, int repeatCount, int transpose, - EAS_U32 muteFlags, EAS_U8 userID); - int setMuteFlags(EAS_U32 muteFlags, bool sync); - int setMuteFlag(int trackNum, bool muteFlag, bool sync); - int triggerClip(int clipId); - int clearQueue(); - - void setEventCallback(jetevent_callback callback); - - int getMaxTracks() { return mMaxTracks; }; - - -private: - static int renderThread(void*); - int render(); - void fireUpdateOnStatusChange(); - void fireEventsFromJetQueue(); - - JetPlayer() {} // no default constructor - void dump(); - void dumpJetStatus(S_JET_STATUS* pJetStatus); - - jetevent_callback mEventCallback; - - jobject mJavaJetPlayerRef; - Mutex mMutex; // mutex to sync the render and playback thread with the JET calls - pid_t mTid; - Condition mCondition; - volatile bool mRender; - bool mPaused; - - EAS_STATE mState; - int* mMemFailedVar; - - int mMaxTracks; // max number of MIDI tracks, usually 32 - EAS_DATA_HANDLE mEasData; - EAS_FILE_LOCATOR mEasJetFileLoc; - EAS_PCM* mAudioBuffer;// EAS renders the MIDI data into this buffer, - AudioTrack* mAudioTrack; // and we play it in this audio track - int mTrackBufferSize; - S_JET_STATUS mJetStatus; - S_JET_STATUS mPreviousJetStatus; - - char mJetFilePath[256]; - - -}; // end class JetPlayer - -} // end namespace android - - - -#endif /*JETPLAYER_H_*/ diff --git a/include/media/MediaMetadataRetrieverInterface.h b/include/media/MediaMetadataRetrieverInterface.h deleted file mode 100644 index b178836..0000000 --- a/include/media/MediaMetadataRetrieverInterface.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -** -** 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_MEDIAMETADATARETRIEVERINTERFACE_H -#define ANDROID_MEDIAMETADATARETRIEVERINTERFACE_H - -#include -#include -#include - -namespace android { - -// Abstract base class -class MediaMetadataRetrieverBase : public RefBase -{ -public: - MediaMetadataRetrieverBase() {} - virtual ~MediaMetadataRetrieverBase() {} - virtual status_t setDataSource(const char *url) = 0; - virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; - virtual status_t setMode(int mode) = 0; - virtual status_t getMode(int* mode) const = 0; - virtual VideoFrame* captureFrame() = 0; - virtual MediaAlbumArt* extractAlbumArt() = 0; - virtual const char* extractMetadata(int keyCode) = 0; -}; - -// MediaMetadataRetrieverInterface -class MediaMetadataRetrieverInterface : public MediaMetadataRetrieverBase -{ -public: - virtual ~MediaMetadataRetrieverInterface() {} -}; - -}; // namespace android - -#endif // ANDROID_MEDIAMETADATARETRIEVERINTERFACE_H - diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h deleted file mode 100644 index 7f0e7b3..0000000 --- a/include/media/MediaPlayerInterface.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2007 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_MEDIAPLAYERINTERFACE_H -#define ANDROID_MEDIAPLAYERINTERFACE_H - -#ifdef __cplusplus - -#include -#include - -#include -#include - -namespace android { - -enum player_type { - PV_PLAYER = 1, - SONIVOX_PLAYER = 2, - VORBIS_PLAYER = 3 -}; - -#define DEFAULT_AUDIOSINK_BUFFERCOUNT 4 -#define DEFAULT_AUDIOSINK_BUFFERSIZE 1200 -#define DEFAULT_AUDIOSINK_SAMPLERATE 44100 - - -// callback mechanism for passing messages to MediaPlayer object -typedef void (*notify_callback_f)(void* cookie, int msg, int ext1, int ext2); - -// abstract base class - use MediaPlayerInterface -class MediaPlayerBase : public RefBase -{ -public: - - // AudioSink: abstraction layer for audio output - class AudioSink : public RefBase { - public: - virtual ~AudioSink() {} - virtual bool ready() const = 0; // audio output is open and ready - virtual bool realtime() const = 0; // audio output is real-time output - virtual ssize_t bufferSize() const = 0; - virtual ssize_t frameCount() const = 0; - virtual ssize_t channelCount() const = 0; - virtual ssize_t frameSize() const = 0; - virtual uint32_t latency() const = 0; - virtual float msecsPerFrame() const = 0; - virtual status_t open(uint32_t sampleRate, int channelCount, int format=AudioSystem::PCM_16_BIT, int bufferCount=DEFAULT_AUDIOSINK_BUFFERCOUNT) = 0; - virtual void start() = 0; - virtual ssize_t write(const void* buffer, size_t size) = 0; - virtual void stop() = 0; - virtual void flush() = 0; - virtual void pause() = 0; - virtual void close() = 0; - }; - - MediaPlayerBase() : mCookie(0), mNotify(0) {} - virtual ~MediaPlayerBase() {} - virtual status_t initCheck() = 0; - virtual bool hardwareOutput() = 0; - virtual status_t setDataSource(const char *url) = 0; - virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; - virtual status_t setVideoSurface(const sp& surface) = 0; - virtual status_t prepare() = 0; - virtual status_t prepareAsync() = 0; - virtual status_t start() = 0; - virtual status_t stop() = 0; - virtual status_t pause() = 0; - virtual bool isPlaying() = 0; - virtual status_t seekTo(int msec) = 0; - virtual status_t getCurrentPosition(int *msec) = 0; - virtual status_t getDuration(int *msec) = 0; - virtual status_t reset() = 0; - virtual status_t setLooping(int loop) = 0; - virtual player_type playerType() = 0; - virtual void setNotifyCallback(void* cookie, notify_callback_f notifyFunc) { - mCookie = cookie; mNotify = notifyFunc; } - -protected: - virtual void sendEvent(int msg, int ext1=0, int ext2=0) { if (mNotify) mNotify(mCookie, msg, ext1, ext2); } - - void* mCookie; - notify_callback_f mNotify; -}; - -// Implement this class for media players that use the AudioFlinger software mixer -class MediaPlayerInterface : public MediaPlayerBase -{ -public: - virtual ~MediaPlayerInterface() { } - virtual bool hardwareOutput() { return false; } - virtual void setAudioSink(const sp& audioSink) { mAudioSink = audioSink; } -protected: - sp mAudioSink; -}; - -// Implement this class for media players that output directo to hardware -class MediaPlayerHWInterface : public MediaPlayerBase -{ -public: - virtual ~MediaPlayerHWInterface() {} - virtual bool hardwareOutput() { return true; } - virtual status_t setVolume(float leftVolume, float rightVolume) = 0; - virtual status_t setAudioStreamType(int streamType) = 0; -}; - -}; // namespace android - -#endif // __cplusplus - - -#endif // ANDROID_MEDIAPLAYERINTERFACE_H - diff --git a/include/media/PVMediaRecorder.h b/include/media/PVMediaRecorder.h deleted file mode 100644 index f795d04..0000000 --- a/include/media/PVMediaRecorder.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - ** - ** 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_PVMEDIARECORDER_H -#define ANDROID_PVMEDIARECORDER_H - -#include - -namespace android { - -class ISurface; -class ICamera; -class AuthorDriverWrapper; - -class PVMediaRecorder -{ -public: - PVMediaRecorder(); - ~PVMediaRecorder(); - - status_t init(); - status_t setAudioSource(audio_source as); - status_t setVideoSource(video_source vs); - status_t setOutputFormat(output_format of); - status_t setAudioEncoder(audio_encoder ae); - status_t setVideoEncoder(video_encoder ve); - status_t setVideoSize(int width, int height); - status_t setVideoFrameRate(int frames_per_second); - status_t setCamera(const sp& camera); - status_t setPreviewSurface(const sp& surface); - status_t setOutputFile(const char *path); - status_t setOutputFile(int fd, int64_t offset, int64_t length); - status_t prepare(); - status_t start(); - status_t stop(); - status_t close(); - status_t reset(); - status_t getMaxAmplitude(int *max); - -private: - status_t doStop(); - - AuthorDriverWrapper* mAuthorDriverWrapper; -}; - -}; // namespace android - -#endif // ANDROID_PVMEDIARECORDER_H - diff --git a/include/media/PVMetadataRetriever.h b/include/media/PVMetadataRetriever.h deleted file mode 100644 index c202dfe..0000000 --- a/include/media/PVMetadataRetriever.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -** -** 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_PVMETADATARETRIEVER_H -#define ANDROID_PVMETADATARETRIEVER_H - -#include -#include -#include - -namespace android { - -class MetadataDriver; - -class PVMetadataRetriever : public MediaMetadataRetrieverInterface -{ -public: - PVMetadataRetriever(); - virtual ~PVMetadataRetriever(); - - 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 VideoFrame* captureFrame(); - virtual MediaAlbumArt* extractAlbumArt(); - virtual const char* extractMetadata(int keyCode); - -private: - mutable Mutex mLock; - MetadataDriver* mMetadataDriver; - char* mDataSourcePath; -}; - -}; // namespace android - -#endif // ANDROID_PVMETADATARETRIEVER_H diff --git a/include/media/PVPlayer.h b/include/media/PVPlayer.h deleted file mode 100644 index 6d98852..0000000 --- a/include/media/PVPlayer.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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_PVPLAYER_H -#define ANDROID_PVPLAYER_H - -#include -#include - -#define MAX_OPENCORE_INSTANCES 25 - -#ifdef MAX_OPENCORE_INSTANCES -#include -#endif - -class PlayerDriver; - -namespace android { - -class PVPlayer : public MediaPlayerInterface -{ -public: - PVPlayer(); - virtual ~PVPlayer(); - - virtual status_t initCheck(); - virtual status_t setDataSource(const char *url); - virtual status_t setDataSource(int fd, int64_t offset, int64_t length); - virtual status_t setVideoSurface(const sp& surface); - virtual status_t prepare(); - virtual status_t prepareAsync(); - virtual status_t start(); - virtual status_t stop(); - virtual status_t pause(); - virtual bool isPlaying(); - virtual status_t seekTo(int msec); - virtual status_t getCurrentPosition(int *msec); - virtual status_t getDuration(int *msec); - virtual status_t reset(); - virtual status_t setLooping(int loop); - virtual player_type playerType() { return PV_PLAYER; } - - // make available to PlayerDriver - void sendEvent(int msg, int ext1=0, int ext2=0) { MediaPlayerBase::sendEvent(msg, ext1, ext2); } - -private: - static void do_nothing(status_t s, void *cookie, bool cancelled) { } - static void run_init(status_t s, void *cookie, bool cancelled); - static void run_set_video_surface(status_t s, void *cookie, bool cancelled); - static void run_set_audio_output(status_t s, void *cookie, bool cancelled); - static void run_prepare(status_t s, void *cookie, bool cancelled); - - PlayerDriver* mPlayerDriver; - char * mDataSourcePath; - bool mIsDataSourceSet; - sp mSurface; - int mSharedFd; - status_t mInit; - int mDuration; - -#ifdef MAX_OPENCORE_INSTANCES - static volatile int32_t sNumInstances; -#endif -}; - -}; // namespace android - -#endif // ANDROID_PVPLAYER_H diff --git a/include/media/ToneGenerator.h b/include/media/ToneGenerator.h deleted file mode 100644 index ec64e4d..0000000 --- a/include/media/ToneGenerator.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * 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_TONEGENERATOR_H_ -#define ANDROID_TONEGENERATOR_H_ - -#include -#include -#include -#include -#include - -namespace android { - -class ToneGenerator { -public: - - // List of all available tones - // This enum must be kept consistant with constants in ToneGenerator JAVA class - enum tone_type { - // DTMF tones ITU-T Recommendation Q.23 - TONE_DTMF_0 = 0, // 0 key: 1336Hz, 941Hz - TONE_DTMF_1, // 1 key: 1209Hz, 697Hz - TONE_DTMF_2, // 2 key: 1336Hz, 697Hz - TONE_DTMF_3, // 3 key: 1477Hz, 697Hz - TONE_DTMF_4, // 4 key: 1209Hz, 770Hz - TONE_DTMF_5, // 5 key: 1336Hz, 770Hz - TONE_DTMF_6, // 6 key: 1477Hz, 770Hz - TONE_DTMF_7, // 7 key: 1209Hz, 852Hz - TONE_DTMF_8, // 8 key: 1336Hz, 852Hz - TONE_DTMF_9, // 9 key: 1477Hz, 852Hz - TONE_DTMF_S, // * key: 1209Hz, 941Hz - TONE_DTMF_P, // # key: 1477Hz, 941Hz - TONE_DTMF_A, // A key: 1633Hz, 697Hz - TONE_DTMF_B, // B key: 1633Hz, 770Hz - TONE_DTMF_C, // C key: 1633Hz, 852Hz - TONE_DTMF_D, // D key: 1633Hz, 941Hz - // Call supervisory tones: 3GPP TS 22.001 (CEPT) - TONE_SUP_DIAL, // Dial tone: 425Hz, continuous - TONE_SUP_BUSY, // Busy tone: 425Hz, 500ms ON, 500ms OFF... - TONE_SUP_CONGESTION, // Congestion tone: 425Hz, 200ms ON, 200ms OFF... - TONE_SUP_RADIO_ACK, // Radio path acknowlegment: 425Hz, 200ms ON - TONE_SUP_RADIO_NOTAVAIL, // Radio path not available: 425Hz, 200ms ON, 200 OFF 3 bursts - TONE_SUP_ERROR, // Error/Special info: 950Hz+1400Hz+1800Hz, 330ms ON, 1s OFF... - TONE_SUP_CALL_WAITING, // Call Waiting: 425Hz, 200ms ON, 600ms OFF, 200ms ON, 3s OFF... - TONE_SUP_RINGTONE, // Ring Tone: 425Hz, 1s ON, 4s OFF... - // Proprietary tones: 3GPP TS 31.111 - TONE_PROP_BEEP, // General beep: 400Hz+1200Hz, 35ms ON - TONE_PROP_ACK, // Positive Acknowlgement: 1200Hz, 100ms ON, 100ms OFF 2 bursts - TONE_PROP_NACK, // Negative Acknowlgement: 300Hz+400Hz+500Hz, 400ms ON - TONE_PROP_PROMPT, // Prompt tone: 400Hz+1200Hz, 200ms ON - TONE_PROP_BEEP2, // General double beep: 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms on - NUM_TONES - }; - - ToneGenerator(int streamType, float volume); - ~ToneGenerator(); - - bool startTone(int toneType); - void stopTone(); - - bool isInited() { return (mState == TONE_IDLE)?false:true;} - -private: - - enum tone_state { - TONE_IDLE, // ToneGenerator is being initialized or initialization failed - TONE_INIT, // ToneGenerator has been successfully initialized and is not playing - TONE_STARTING, // ToneGenerator is starting playing - TONE_PLAYING, // ToneGenerator is playing - TONE_STOPPING, // ToneGenerator is stoping - TONE_RESTARTING // - }; - - static const unsigned int TONEGEN_MAX_WAVES = 3; - static const unsigned int TONEGEN_MAX_SEGMENTS = 4; // Maximun number of elenemts in - static const unsigned int TONEGEN_INF = 0xFFFFFFFF; // Represents infinite time duration - static const float TONEGEN_GAIN = 0.9; // Default gain passed to WaveGenerator(). - - // ToneDescriptor class contains all parameters needed to generate a tone: - // - The array waveFreq[] contains the frequencies of all individual waves making the multi-tone. - // The number of sine waves varies from 1 to TONEGEN_MAX_WAVES. - // The first null value indicates that no more waves are needed. - // - The array segments[] is used to generate the tone pulses. A segment is a period of time - // during which the tone is ON or OFF. Segments with even index (starting from 0) - // correspond to tone ON state and segments with odd index to OFF state. - // The data stored in segments[] is the duration of the corresponding period in ms. - // The first segment encountered with a 0 duration indicates that no more segment follows. - // - repeatCnt indicates the number of times the sequence described by segments[] array must be repeated. - // When the tone generator encounters the first 0 duration segment, it will compare repeatCnt to mCurCount. - // If mCurCount > repeatCnt, the tone is stopped automatically. - - class ToneDescriptor { - public: - unsigned short waveFreq[TONEGEN_MAX_WAVES+1]; - unsigned long segments[TONEGEN_MAX_SEGMENTS+1]; - unsigned long repeatCnt; - }; - - static const ToneDescriptor toneDescriptors[NUM_TONES]; - - unsigned int mTotalSmp; // Total number of audio samples played (gives current time) - unsigned int mNextSegSmp; // Position of next segment transition expressed in samples - // NOTE: because mTotalSmp, mNextSegSmp are stored on 32 bit, current design will operate properly - // only if tone duration is less than about 27 Hours(@44100Hz sampling rate). If this time is exceeded, - // no crash will occur but tone sequence will show a glitch. - - unsigned short mCurSegment; // Current segment index in ToneDescriptor segments[] - unsigned short mCurCount; // Current sequence repeat count - volatile unsigned short mState; // ToneGenerator state (tone_state) - const ToneDescriptor *mpToneDesc; // pointer to active tone descriptor - const ToneDescriptor *mpNewToneDesc; // pointer to next active tone descriptor - - int mSamplingRate; // AudioFlinger Sampling rate - AudioTrack *mpAudioTrack; // Pointer to audio track used for playback - Mutex mLock; // Mutex to control concurent access to ToneGenerator object from audio callback and application API - Mutex mCbkCondLock; // Mutex associated to mWaitCbkCond - Condition mWaitCbkCond; // condition enabling interface to wait for audio callback completion after a change is requested - float mVolume; // Volume applied to audio track - int mStreamType; // Audio stream used for output - unsigned int mProcessSize; // Size of audio blocks generated at a time by audioCallback() (in PCM frames). - - bool initAudioTrack(); - static void audioCallback(int event, void* user, void *info); - bool prepareWave(); - unsigned int numWaves(); - void clearWaveGens(); - - // WaveGenerator generates a single sine wave - class WaveGenerator { - public: - enum gen_command { - WAVEGEN_START, // Start/restart wave from phase 0 - WAVEGEN_CONT, // Continue wave from current phase - WAVEGEN_STOP // Stop wave on zero crossing - }; - - WaveGenerator(unsigned short samplingRate, unsigned short frequency, - float volume); - ~WaveGenerator(); - - void getSamples(short *outBuffer, unsigned int count, - unsigned int command); - - private: - static const short GEN_AMP = 32000; // amplitude of generator - static const short S_Q14 = 14; // shift for Q14 - static const short S_Q15 = 15; // shift for Q15 - - short mA1_Q14; // Q14 coefficient - // delay line of full amplitude generator - short mS1, mS2; // delay line S2 oldest - short mS2_0; // saved value for reinitialisation - short mAmplitude_Q15; // Q15 amplitude - }; - - Vector mWaveGens; // list of active wave generators. -}; - -} -; // namespace android - -#endif /*ANDROID_TONEGENERATOR_H_*/ diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h deleted file mode 100644 index f2719d3..0000000 --- a/include/media/mediametadataretriever.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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 MEDIAMETADATARETRIEVER_H -#define MEDIAMETADATARETRIEVER_H - -#include // for status_t -#include -#include -#include - -namespace android { - -class IMediaPlayerService; -class IMediaMetadataRetriever; - -// Keep these in synch with the constants defined in MediaMetadataRetriever.java -// class. -enum { - METADATA_KEY_CD_TRACK_NUMBER = 0, - METADATA_KEY_ALBUM = 1, - METADATA_KEY_ARTIST = 2, - METADATA_KEY_AUTHOR = 3, - METADATA_KEY_COMPOSER = 4, - METADATA_KEY_DATE = 5, - METADATA_KEY_GENRE = 6, - METADATA_KEY_TITLE = 7, - METADATA_KEY_YEAR = 8, - METADATA_KEY_DURATION = 9, - METADATA_KEY_NUM_TRACKS = 10, - METADATA_KEY_IS_DRM_CRIPPLED = 11, - METADATA_KEY_CODEC = 12, - METADATA_KEY_RATING = 13, - METADATA_KEY_COMMENT = 14, - METADATA_KEY_COPYRIGHT = 15, - METADATA_KEY_BIT_RATE = 16, - METADATA_KEY_FRAME_RATE = 17, - METADATA_KEY_VIDEO_FORMAT = 18, - METADATA_KEY_VIDEO_HEIGHT = 19, - METADATA_KEY_VIDEO_WIDTH = 20, - // Add more here... -}; - - -class MediaMetadataRetriever: public RefBase -{ -public: - MediaMetadataRetriever(); - ~MediaMetadataRetriever(); - void disconnect(); - status_t setDataSource(const char* dataSourceUrl); - status_t setDataSource(int fd, int64_t offset, int64_t length); - status_t setMode(int mode); - status_t getMode(int* mode); - sp captureFrame(); - sp extractAlbumArt(); - const char* extractMetadata(int keyCode); - -private: - static const sp& getService(); - - class DeathNotifier: public IBinder::DeathRecipient - { - public: - DeathNotifier() {} - virtual ~DeathNotifier(); - virtual void binderDied(const wp& who); - }; - - static sp sDeathNotifier; - static Mutex sServiceLock; - static sp sService; - - Mutex mLock; - sp mRetriever; - -}; - -}; // namespace android - -#endif // MEDIAMETADATARETRIEVER_H diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h deleted file mode 100644 index 7288445..0000000 --- a/include/media/mediaplayer.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2007 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_MEDIAPLAYER_H -#define ANDROID_MEDIAPLAYER_H - -#include -#include -#include -#include -#include -#include - -namespace android { - -enum media_event_type { - MEDIA_NOP = 0, // interface test message - MEDIA_PREPARED = 1, - MEDIA_PLAYBACK_COMPLETE = 2, - MEDIA_BUFFERING_UPDATE = 3, - MEDIA_SEEK_COMPLETE = 4, - MEDIA_SET_VIDEO_SIZE = 5, - MEDIA_ERROR = 100, -}; - -typedef int media_error_type; -const media_error_type MEDIA_ERROR_UNKNOWN = 1; -const media_error_type MEDIA_ERROR_SERVER_DIED = 100; - -enum media_player_states { - MEDIA_PLAYER_STATE_ERROR = 0, - MEDIA_PLAYER_IDLE = 1 << 0, - MEDIA_PLAYER_INITIALIZED = 1 << 1, - MEDIA_PLAYER_PREPARING = 1 << 2, - MEDIA_PLAYER_PREPARED = 1 << 3, - MEDIA_PLAYER_STARTED = 1 << 4, - MEDIA_PLAYER_PAUSED = 1 << 5, - MEDIA_PLAYER_STOPPED = 1 << 6, - MEDIA_PLAYER_PLAYBACK_COMPLETE = 1 << 7 -}; - -// ---------------------------------------------------------------------------- -// ref-counted object for callbacks -class MediaPlayerListener: virtual public RefBase -{ -public: - virtual void notify(int msg, int ext1, int ext2) = 0; -}; - -class MediaPlayer : public BnMediaPlayerClient -{ -public: - MediaPlayer(); - ~MediaPlayer(); - void onFirstRef(); - void disconnect(); - status_t setDataSource(const char *url); - status_t setDataSource(int fd, int64_t offset, int64_t length); - status_t setVideoSurface(const sp& surface); - status_t setListener(const sp& listener); - status_t prepare(); - status_t prepareAsync(); - status_t start(); - status_t stop(); - status_t pause(); - bool isPlaying(); - status_t getVideoWidth(int *w); - status_t getVideoHeight(int *h); - status_t seekTo(int msec); - status_t getCurrentPosition(int *msec); - status_t getDuration(int *msec); - status_t reset(); - status_t setAudioStreamType(int type); - status_t setLooping(int loop); - bool isLooping(); - status_t setVolume(float leftVolume, float rightVolume); - void notify(int msg, int ext1, int ext2); - static sp decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat); - static sp decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat); - -private: - void clear_l(); - status_t seekTo_l(int msec); - status_t prepareAsync_l(); - status_t getDuration_l(int *msec); - status_t setDataSource(const sp& player); - - static const sp& getMediaPlayerService(); - static void addObitRecipient(const wp& recipient); - static void removeObitRecipient(const wp& recipient); - - class DeathNotifier: public IBinder::DeathRecipient - { - public: - DeathNotifier() {} - virtual ~DeathNotifier(); - - virtual void binderDied(const wp& who); - }; - - sp mPlayer; - Mutex mLock; - Mutex mNotifyLock; - Condition mSignal; - sp mListener; - void* mCookie; - media_player_states mCurrentState; - int mDuration; - int mCurrentPosition; - int mSeekPosition; - bool mPrepareSync; - status_t mPrepareStatus; - int mStreamType; - bool mLoop; - float mLeftVolume; - float mRightVolume; - int mVideoWidth; - int mVideoHeight; - - friend class DeathNotifier; - - static Mutex sServiceLock; - static sp sMediaPlayerService; - static sp sDeathNotifier; - static SortedVector< wp > sObitRecipients; -}; - -}; // namespace android - -#endif // ANDROID_MEDIAPLAYER_H - diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h deleted file mode 100644 index 436e8f1..0000000 --- a/include/media/mediarecorder.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - ** 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_MEDIARECORDER_H -#define ANDROID_MEDIARECORDER_H - -#include - -namespace android { - -class Surface; -class IMediaRecorder; -class ICamera; - -typedef void (*media_completion_f)(status_t status, void *cookie); - -/* Do not change these values without updating their counterparts - * in java/android/android/media/MediaRecorder.java! - */ -enum audio_source { - AUDIO_SOURCE_DEFAULT = 0, - AUDIO_SOURCE_MIC = 1, -}; - -enum video_source { - VIDEO_SOURCE_DEFAULT = 0, - VIDEO_SOURCE_CAMERA = 1, -}; - -//Please update java/android/android/media/MediaRecorder.java if the following is updated. -enum output_format { - OUTPUT_FORMAT_DEFAULT = 0, - OUTPUT_FORMAT_THREE_GPP, - OUTPUT_FORMAT_MPEG_4, - OUTPUT_FORMAT_RAW_AMR, - OUTPUT_FORMAT_LIST_END // must be last - used to validate format type -}; - -enum audio_encoder { - AUDIO_ENCODER_DEFAULT = 0, - AUDIO_ENCODER_AMR_NB = 1, -}; - -enum video_encoder { - VIDEO_ENCODER_DEFAULT = 0, - VIDEO_ENCODER_H263 = 1, - VIDEO_ENCODER_H264 = 2, - VIDEO_ENCODER_MPEG_4_SP = 3, -}; - -// Maximum frames per second is 24 -#define MEDIA_RECORDER_MAX_FRAME_RATE 24 - -/* - * The state machine of the media_recorder uses a set of different state names. - * The mapping between the media_recorder and the pvauthorengine is shown below: - * - * mediarecorder pvauthorengine - * ---------------------------------------------------------------- - * MEDIA_RECORDER_ERROR ERROR - * MEDIA_RECORDER_IDLE IDLE - * MEDIA_RECORDER_INITIALIZED OPENED - * MEDIA_RECORDER_DATASOURCE_CONFIGURED - * MEDIA_RECORDER_PREPARED INITIALIZED - * MEDIA_RECORDER_RECORDING RECORDING - */ -enum media_recorder_states { - MEDIA_RECORDER_ERROR = 0, - MEDIA_RECORDER_IDLE = 1 << 0, - MEDIA_RECORDER_INITIALIZED = 1 << 1, - MEDIA_RECORDER_DATASOURCE_CONFIGURED = 1 << 2, - MEDIA_RECORDER_PREPARED = 1 << 3, - MEDIA_RECORDER_RECORDING = 1 << 4, -}; - -class MediaRecorder -{ -public: - MediaRecorder(); - ~MediaRecorder(); - - status_t initCheck(); - status_t setCamera(const sp& camera); - status_t setPreviewSurface(const sp& surface); - status_t setVideoSource(int vs); - status_t setAudioSource(int as); - status_t setOutputFormat(int of); - status_t setVideoEncoder(int ve); - status_t setAudioEncoder(int ae); - status_t setOutputFile(const char* path); - status_t setOutputFile(int fd, int64_t offset, int64_t length); - status_t setVideoSize(int width, int height); - status_t setVideoFrameRate(int frames_per_second); - status_t prepare(); - status_t getMaxAmplitude(int* max); - status_t start(); - status_t stop(); - status_t reset(); - status_t init(); - status_t close(); - status_t release(); - -private: - void doCleanUp(); - status_t doReset(); - - sp mMediaRecorder; - media_recorder_states mCurrentState; - bool mIsAudioSourceSet; - bool mIsVideoSourceSet; - bool mIsAudioEncoderSet; - bool mIsVideoEncoderSet; - bool mIsOutputFileSet; -}; - -}; // namespace android - -#endif // ANDROID_MEDIARECORDER_H diff --git a/include/media/mediascanner.h b/include/media/mediascanner.h deleted file mode 100644 index fbef1db..0000000 --- a/include/media/mediascanner.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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 MEDIASCANNER_H -#define MEDIASCANNER_H - -#include -#include - -namespace android { - -class MediaScannerClient; -class StringArray; - -class MediaScanner -{ -public: - MediaScanner(); - ~MediaScanner(); - - typedef bool (*ExceptionCheck)(void* env); - - status_t processFile(const char *path, const char *mimeType, MediaScannerClient& client); - status_t processDirectory(const char *path, const char* extensions, - MediaScannerClient& client, ExceptionCheck exceptionCheck, void* exceptionEnv); - void setLocale(const char* locale); - - // extracts album art as a block of data - char* extractAlbumArt(int fd); - - static void uninitializeForThread(); - -private: - status_t doProcessDirectory(char *path, int pathRemaining, const char* extensions, - MediaScannerClient& client, ExceptionCheck exceptionCheck, void* exceptionEnv); - void initializeForThread(); - - // current locale (like "ja_JP"), created/destroyed with strdup()/free() - char* mLocale; -}; - - -class MediaScannerClient -{ -public: - MediaScannerClient(); - virtual ~MediaScannerClient(); - void setLocale(const char* locale); - void beginFile(); - bool addStringTag(const char* name, const char* value); - void endFile(); - - virtual bool scanFile(const char* path, long long lastModified, long long fileSize) = 0; - virtual bool handleStringTag(const char* name, const char* value) = 0; - virtual bool setMimeType(const char* mimeType) = 0; - -protected: - void convertValues(uint32_t encoding); - -protected: - // cached name and value strings, for native encoding support. - StringArray* mNames; - StringArray* mValues; - - // default encoding based on MediaScanner::mLocale string - uint32_t mLocaleEncoding; -}; - -}; // namespace android - -#endif // MEDIASCANNER_H - diff --git a/include/media/thread_init.h b/include/media/thread_init.h deleted file mode 100644 index 2c0c1f1..0000000 --- a/include/media/thread_init.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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 THREAD_INIT_H -#define THREAD_INIT_H - -bool InitializeForThread(); -void UninitializeForThread(); -void keydestructor(void*); - -#endif /* THREAD_INIT_H*/ - diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h deleted file mode 100644 index 1991aa7..0000000 --- a/include/private/media/AudioTrackShared.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2007 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_AUDIO_TRACK_SHARED_H -#define ANDROID_AUDIO_TRACK_SHARED_H - -#include -#include - -#include - -namespace android { - -// ---------------------------------------------------------------------------- - -#define MAX_SAMPLE_RATE 65535 -#define THREAD_PRIORITY_AUDIO_CLIENT (ANDROID_PRIORITY_AUDIO) -// Maximum cumulated timeout milliseconds before restarting audioflinger thread -#define MAX_STARTUP_TIMEOUT_MS 3000 // Longer timeout period at startup to cope with A2DP init time -#define MAX_RUN_TIMEOUT_MS 1000 -#define WAIT_PERIOD_MS 10 - - -struct audio_track_cblk_t -{ - - // The data members are grouped so that members accessed frequently and in the same context - // are in the same line of data cache. - Mutex lock; - Condition cv; - volatile uint32_t user; - volatile uint32_t server; - uint32_t userBase; - uint32_t serverBase; - void* buffers; - uint32_t frameCount; - // Cache line boundary - uint32_t loopStart; - uint32_t loopEnd; - int loopCount; - volatile union { - uint16_t volume[2]; - uint32_t volumeLR; - }; - uint16_t sampleRate; - uint16_t channels; - int16_t flowControlFlag; // underrun (out) or overrrun (in) indication - uint8_t out; // out equals 1 for AudioTrack and 0 for AudioRecord - uint8_t forceReady; - uint16_t bufferTimeoutMs; // Maximum cumulated timeout before restarting audioflinger - uint16_t waitTimeMs; // Cumulated wait time - // Padding ensuring that data buffer starts on a cache line boundary (32 bytes). - // See AudioFlinger::TrackBase constructor - int32_t Padding[3]; - - audio_track_cblk_t(); - uint32_t stepUser(uint32_t frameCount); - bool stepServer(uint32_t frameCount); - void* buffer(uint32_t offset) const; - uint32_t framesAvailable(); - uint32_t framesAvailable_l(); - uint32_t framesReady(); -}; - - -// ---------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_AUDIO_TRACK_SHARED_H diff --git a/include/private/media/VideoFrame.h b/include/private/media/VideoFrame.h deleted file mode 100644 index 9c35274..0000000 --- a/include/private/media/VideoFrame.h +++ /dev/null @@ -1,127 +0,0 @@ -/* -** -** 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_VIDEO_FRAME_H -#define ANDROID_VIDEO_FRAME_H - -#include -#include -#include -#include - -namespace android { - -// A simple buffer to hold binary data -class MediaAlbumArt -{ -public: - MediaAlbumArt(): mSize(0), mData(0) {} - - explicit MediaAlbumArt(const char* url) { - mSize = 0; - mData = NULL; - FILE *in = fopen(url, "r"); - if (!in) { - return; - } - fseek(in, 0, SEEK_END); - mSize = ftell(in); // Allocating buffer of size equals to the external file size. - if (mSize == 0 || (mData = new uint8_t[mSize]) == NULL) { - fclose(in); - if (mSize != 0) { - mSize = 0; - } - return; - } - rewind(in); - if (fread(mData, 1, mSize, in) != mSize) { // Read failed. - delete[] mData; - mData = NULL; - mSize = 0; - return; - } - fclose(in); - } - - MediaAlbumArt(const MediaAlbumArt& copy) { - mSize = copy.mSize; - mData = NULL; // initialize it first - if (mSize > 0 && copy.mData != NULL) { - mData = new uint8_t[copy.mSize]; - if (mData != NULL) { - memcpy(mData, copy.mData, mSize); - } else { - mSize = 0; - } - } - } - - ~MediaAlbumArt() { - if (mData != 0) { - delete[] mData; - } - } - - // Intentional public access modifier: - // We have to know the internal structure in order to share it between - // processes? - uint32_t mSize; // Number of bytes in mData - uint8_t* mData; // Actual binary data -}; - -// Represents a color converted (RGB-based) video frame -// with bitmap pixels stored in FrameBuffer -class VideoFrame -{ -public: - VideoFrame(): mWidth(0), mHeight(0), mDisplayWidth(0), mDisplayHeight(0), mSize(0), mData(0) {} - - VideoFrame(const VideoFrame& copy) { - mWidth = copy.mWidth; - mHeight = copy.mHeight; - mDisplayWidth = copy.mDisplayWidth; - mDisplayHeight = copy.mDisplayHeight; - mSize = copy.mSize; - mData = NULL; // initialize it first - if (mSize > 0 && copy.mData != NULL) { - mData = new uint8_t[mSize]; - if (mData != NULL) { - memcpy(mData, copy.mData, mSize); - } else { - mSize = 0; - } - } - } - - ~VideoFrame() { - if (mData != 0) { - delete[] mData; - } - } - - // Intentional public access modifier: - uint32_t mWidth; - uint32_t mHeight; - uint32_t mDisplayWidth; - uint32_t mDisplayHeight; - uint32_t mSize; // Number of bytes in mData - uint8_t* mData; // Actual binary data -}; - -}; // namespace android - -#endif // ANDROID_VIDEO_FRAME_H diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h deleted file mode 100644 index 0c7ad46..0000000 --- a/include/private/opengles/gl_context.h +++ /dev/null @@ -1,632 +0,0 @@ -/* - * Copyright (C) 2006 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_OPENGLES_CONTEXT_H -#define ANDROID_OPENGLES_CONTEXT_H - -#include -#include -#include -#include -#ifdef HAVE_ANDROID_OS -#include -#endif - -#include - -#include -#include - -namespace android { - -const unsigned int OGLES_NUM_COMPRESSED_TEXTURE_FORMATS = 10; - -class EGLTextureObject; -class EGLSurfaceManager; -class EGLBufferObjectManager; - -namespace gl { - -struct ogles_context_t; -struct matrixx_t; -struct transform_t; -struct buffer_t; - -ogles_context_t* getGlContext(); - -template -static inline void swap(T& a, T& b) { - T t(a); a = b; b = t; -} -template -inline T max(T a, T b) { - return a -inline T max(T a, T b, T c) { - return max(a, max(b, c)); -} -template -inline T min(T a, T b) { - return a -inline T min(T a, T b, T c) { - return min(a, min(b, c)); -} -template -inline T min(T a, T b, T c, T d) { - return min(min(a,b), min(c,d)); -} - -// ---------------------------------------------------------------------------- -// vertices -// ---------------------------------------------------------------------------- - -struct vec3_t { - union { - struct { GLfixed x, y, z; }; - struct { GLfixed r, g, b; }; - struct { GLfixed S, T, R; }; - GLfixed v[3]; - }; -}; - -struct vec4_t { - union { - struct { GLfixed x, y, z, w; }; - struct { GLfixed r, g, b, a; }; - struct { GLfixed S, T, R, Q; }; - GLfixed v[4]; - }; -}; - -struct vertex_t { - enum { - // these constant matter for our clipping - CLIP_L = 0x0001, // clipping flags - CLIP_R = 0x0002, - CLIP_B = 0x0004, - CLIP_T = 0x0008, - CLIP_N = 0x0010, - CLIP_F = 0x0020, - - EYE = 0x0040, - RESERVED = 0x0080, - - USER_CLIP_0 = 0x0100, // user clipping flags - USER_CLIP_1 = 0x0200, - USER_CLIP_2 = 0x0400, - USER_CLIP_3 = 0x0800, - USER_CLIP_4 = 0x1000, - USER_CLIP_5 = 0x2000, - - LIT = 0x4000, // lighting has been applied - TT = 0x8000, // texture coords transformed - - FRUSTUM_CLIP_ALL= 0x003F, - USER_CLIP_ALL = 0x3F00, - CLIP_ALL = 0x3F3F, - }; - - // the fields below are arranged to minimize d-cache usage - // we group together, by cache-line, the fields most likely to be used - - union { - vec4_t obj; - vec4_t eye; - }; - vec4_t clip; - - uint32_t flags; - size_t index; // cache tag, and vertex index - GLfixed fog; - uint8_t locked; - uint8_t mru; - uint8_t reserved[2]; - vec4_t window; - - vec4_t color; - vec4_t texture[GGL_TEXTURE_UNIT_COUNT]; - uint32_t reserved1[4]; - - inline void clear() { - flags = index = locked = mru = 0; - } -}; - -struct point_size_t { - GGLcoord size; - GLboolean smooth; -}; - -struct line_width_t { - GGLcoord width; - GLboolean smooth; -}; - -struct polygon_offset_t { - GLfixed factor; - GLfixed units; - GLboolean enable; -}; - -// ---------------------------------------------------------------------------- -// arrays -// ---------------------------------------------------------------------------- - -struct array_t { - typedef void (*fetcher_t)(ogles_context_t*, GLfixed*, const GLvoid*); - fetcher_t fetch; - GLvoid const* physical_pointer; - GLint size; - GLsizei stride; - GLvoid const* pointer; - buffer_t const* bo; - uint16_t type; - GLboolean enable; - GLboolean pad; - GLsizei bounds; - void init(GLint, GLenum, GLsizei, const GLvoid *, const buffer_t*, GLsizei); - inline void resolve(); - inline const GLubyte* element(GLint i) const { - return (const GLubyte*)physical_pointer + i * stride; - } -}; - -struct array_machine_t { - array_t vertex; - array_t normal; - array_t color; - array_t texture[GGL_TEXTURE_UNIT_COUNT]; - uint8_t activeTexture; - uint8_t tmu; - uint16_t cull; - uint32_t flags; - GLenum indicesType; - buffer_t const* array_buffer; - buffer_t const* element_array_buffer; - - void (*compileElements)(ogles_context_t*, vertex_t*, GLint, GLsizei); - void (*compileElement)(ogles_context_t*, vertex_t*, GLint); - - void (*mvp_transform)(transform_t const*, vec4_t*, vec4_t const*); - void (*mv_transform)(transform_t const*, vec4_t*, vec4_t const*); - void (*tex_transform[2])(transform_t const*, vec4_t*, vec4_t const*); - void (*perspective)(ogles_context_t*c, vertex_t* v); - void (*clipVertex)(ogles_context_t* c, vertex_t* nv, - GGLfixed t, const vertex_t* s, const vertex_t* p); - void (*clipEye)(ogles_context_t* c, vertex_t* nv, - GGLfixed t, const vertex_t* s, const vertex_t* p); -}; - -struct vertex_cache_t { - enum { - // must be at least 4 - // 3 vertice for triangles - // or 2 + 2 for indexed triangles w/ cache contention - VERTEX_BUFFER_SIZE = 8, - // must be a power of two and at least 3 - VERTEX_CACHE_SIZE = 64, // 8 KB - - INDEX_BITS = 16, - INDEX_MASK = ((1LU<(pthread_getspecific(gGLKey)); - } -#endif - - -struct prims_t { - typedef ogles_context_t* GL; - void (*renderPoint)(GL, vertex_t*); - void (*renderLine)(GL, vertex_t*, vertex_t*); - void (*renderTriangle)(GL, vertex_t*, vertex_t*, vertex_t*); -}; - -struct ogles_context_t { - context_t rasterizer; - array_machine_t arrays __attribute__((aligned(32))); - texture_state_t textures; - transform_state_t transforms; - vertex_cache_t vc; - prims_t prims; - culling_t cull; - lighting_t lighting; - user_clip_planes_t clipPlanes; - compute_iterators_t lerp; __attribute__((aligned(32))); - vertex_t current; - vec4_t currentColorClamped; - vec3_t currentNormal; - viewport_t viewport; - point_size_t point; - line_width_t line; - polygon_offset_t polygonOffset; - fog_t fog; - uint32_t perspective : 1; - uint32_t transformTextures : 1; - EGLSurfaceManager* surfaceManager; - EGLBufferObjectManager* bufferObjectManager; - GLenum error; - - static inline ogles_context_t* get() { - return getGlThreadSpecific(); - } - -}; - -}; // namespace gl -}; // namespace android - -#endif // ANDROID_OPENGLES_CONTEXT_H - diff --git a/include/private/ui/LayerState.h b/include/private/ui/LayerState.h deleted file mode 100644 index b6fcd80..0000000 --- a/include/private/ui/LayerState.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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_COMPOSER_LAYER_STATE_H -#define ANDROID_COMPOSER_LAYER_STATE_H - -#include -#include - -#include - -#include -#include - -#include - -namespace android { - -class Parcel; - -struct layer_state_t { - - layer_state_t() - : surface(0), what(0), - x(0), y(0), z(0), w(0), h(0), - alpha(0), tint(0), flags(0), mask(0), - reserved(0) - { - matrix.dsdx = matrix.dtdy = 1.0f; - matrix.dsdy = matrix.dtdx = 0.0f; - } - - status_t write(Parcel& output) const; - status_t read(const Parcel& input); - - struct matrix22_t { - float dsdx; - float dtdx; - float dsdy; - float dtdy; - }; - SurfaceID surface; - uint32_t what; - int32_t x; - int32_t y; - uint32_t z; - uint32_t w; - uint32_t h; - float alpha; - uint32_t tint; - uint8_t flags; - uint8_t mask; - uint8_t reserved; - matrix22_t matrix; - // non POD must be last. see write/read - Region transparentRegion; -}; - -}; // namespace android - -#endif // ANDROID_COMPOSER_LAYER_STATE_H - diff --git a/include/private/ui/SharedState.h b/include/private/ui/SharedState.h deleted file mode 100644 index 546d0ad..0000000 --- a/include/private/ui/SharedState.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (C) 2007 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_UI_SHARED_STATE_H -#define ANDROID_UI_SHARED_STATE_H - -#include -#include - -#include - -namespace android { - -/* - * These structures are shared between the composer process and its clients - */ - -// --------------------------------------------------------------------------- - -struct surface_info_t { // 4 longs, 16 bytes - enum { - eBufferDirty = 0x01 - }; - uint16_t w; - uint16_t h; - uint16_t stride; - uint16_t bpr; - uint16_t reserved; - uint8_t format; - uint8_t flags; - ssize_t bits_offset; -}; - -// --------------------------------------------------------------------------- - -const uint32_t NUM_LAYERS_MAX = 31; - -enum { // layer_cblk_t swapState - eIndex = 0x00000001, - eFlipRequested = 0x00000002, - - eResizeBuffer0 = 0x00000004, - eResizeBuffer1 = 0x00000008, - eResizeRequested = eResizeBuffer0 | eResizeBuffer1, - - eBusy = 0x00000010, - eLocked = 0x00000020, - eNextFlipPending = 0x00000040, - eInvalidSurface = 0x00000080 -}; - -enum { // layer_cblk_t flags - eLayerNotPosted = 0x00000001, - eNoCopyBack = 0x00000002, - eReserved = 0x0000007C, - eBufferIndexShift = 7, - eBufferIndex = 1<>1)); - } - static inline int frontBuffer(uint32_t state) { - return 1 - backBuffer(state); - } -}; - -// --------------------------------------------------------------------------- - -struct per_client_cblk_t // 4KB max -{ - Mutex lock; - Condition cv; - layer_cblk_t layers[NUM_LAYERS_MAX] __attribute__((aligned(32))); - - enum { - BLOCKING = 0x00000001, - INSPECT = 0x00000002 - }; - - per_client_cblk_t(); - - // these functions are used by the clients - status_t validate(size_t i) const; - int32_t lock_layer(size_t i, uint32_t flags); - uint32_t unlock_layer_and_post(size_t i); - void unlock_layer(size_t i); -}; -// --------------------------------------------------------------------------- - -const uint32_t NUM_DISPLAY_MAX = 4; - -struct display_cblk_t -{ - uint16_t w; - uint16_t h; - uint8_t format; - uint8_t orientation; - uint8_t reserved[2]; - float fps; - float density; - float xdpi; - float ydpi; - uint32_t pad[2]; -}; - -struct surface_flinger_cblk_t // 4KB max -{ - surface_flinger_cblk_t(); - - uint8_t connected; - uint8_t reserved[3]; - uint32_t pad[7]; - - display_cblk_t displays[NUM_DISPLAY_MAX]; -}; - -// --------------------------------------------------------------------------- - -template struct CTA; -template<> struct CTA { }; - -// compile-time assertions. just to avoid catastrophes. -inline void compile_time_asserts() { - CTA sizeof__layer_cblk_t__eq_128; - (void)sizeof__layer_cblk_t__eq_128; // we don't want a warning - CTA sizeof__per_client_cblk_t__le_4096; - (void)sizeof__per_client_cblk_t__le_4096; // we don't want a warning - CTA sizeof__surface_flinger_cblk_t__le_4096; - (void)sizeof__surface_flinger_cblk_t__le_4096; // we don't want a warning -} - -}; // namespace android - -#endif // ANDROID_UI_SHARED_STATE_H - diff --git a/include/private/ui/SurfaceFlingerSynchro.h b/include/private/ui/SurfaceFlingerSynchro.h deleted file mode 100644 index ff91b61..0000000 --- a/include/private/ui/SurfaceFlingerSynchro.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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_SURFACE_FLINGER_SYNCHRO_H -#define ANDROID_SURFACE_FLINGER_SYNCHRO_H - -#include -#include -#include -#include -#include - -namespace android { - -class SurfaceFlinger; - -class SurfaceFlingerSynchro -{ -public: - - // client constructor - SurfaceFlingerSynchro(const sp& flinger); - ~SurfaceFlingerSynchro(); - - // signal surfaceflinger for some work - status_t signal(); - -private: - class Barrier { - public: - Barrier(); - ~Barrier(); - void open(); - void close(); - void waitAndClose(); - status_t waitAndClose(nsecs_t timeout); - private: - enum { OPENED, CLOSED }; - mutable Mutex lock; - mutable Condition cv; - volatile int state; - }; - - friend class SurfaceFlinger; - - // server constructor - SurfaceFlingerSynchro(); - - void open(); - - // wait until there is some work to do - status_t wait(); - status_t wait(nsecs_t timeout); - - sp mSurfaceComposer; - Barrier mBarrier; -}; - -}; // namespace android - -#endif // ANDROID_SURFACE_FLINGER_SYNCHRO_H - diff --git a/include/private/utils/Static.h b/include/private/utils/Static.h deleted file mode 100644 index f1439b7..0000000 --- a/include/private/utils/Static.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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. - */ - -// All static variables go here, to control initialization and -// destruction order in the library. - -#include -#include - -#ifndef LIBUTILS_NATIVE -#include -#include -#include -#include -#include -#endif - -namespace android { -// For TextStream.cpp -extern Vector gTextBuffers; - -// For String8.cpp -extern void initialize_string8(); -extern void terminate_string8(); - -// For String16.cpp -extern void initialize_string16(); -extern void terminate_string16(); - - - -#ifndef LIBUTILS_NATIVE - -// For ProcessState.cpp -extern Mutex gProcessMutex; -extern sp gProcess; - -// For ServiceManager.cpp -extern Mutex gDefaultServiceManagerLock; -extern sp gDefaultServiceManager; -extern sp gPermissionController; - -#endif - -} // namespace android diff --git a/include/private/utils/binder_module.h b/include/private/utils/binder_module.h deleted file mode 100644 index fdf327e..0000000 --- a/include/private/utils/binder_module.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * 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 _BINDER_MODULE_H_ -#define _BINDER_MODULE_H_ - -#ifdef __cplusplus -namespace android { -#endif - -#if defined(HAVE_ANDROID_OS) - -/* obtain structures and constants from the kernel header */ - -#include -#include - -#else - -/* Some parts of the simulator need fake versions of this - * stuff in order to compile. Really this should go away - * entirely... - */ - -#define BINDER_CURRENT_PROTOCOL_VERSION 7 - -#define BINDER_TYPE_BINDER 1 -#define BINDER_TYPE_WEAK_BINDER 2 -#define BINDER_TYPE_HANDLE 3 -#define BINDER_TYPE_WEAK_HANDLE 4 -#define BINDER_TYPE_FD 5 - -struct flat_binder_object { - unsigned long type; - unsigned long flags; - union { - void *binder; - signed long handle; - }; - void *cookie; -}; - -struct binder_write_read { - signed long write_size; - signed long write_consumed; - unsigned long write_buffer; - signed long read_size; - signed long read_consumed; - unsigned long read_buffer; -}; - -struct binder_transaction_data { - union { - size_t handle; - void *ptr; - } target; - void *cookie; - unsigned int code; - - unsigned int flags; - pid_t sender_pid; - uid_t sender_euid; - size_t data_size; - size_t offsets_size; - - union { - struct { - const void *buffer; - const void *offsets; - } ptr; - uint8_t buf[8]; - } data; -}; - -enum transaction_flags { - TF_ONE_WAY = 0x01, - TF_ROOT_OBJECT = 0x04, - TF_STATUS_CODE = 0x08, - TF_ACCEPT_FDS = 0x10, -}; - - -enum { - FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff, - FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100, -}; - -enum BinderDriverReturnProtocol { - BR_ERROR, - BR_OK, - BR_TRANSACTION, - BR_REPLY, - BR_ACQUIRE_RESULT, - BR_DEAD_REPLY, - BR_TRANSACTION_COMPLETE, - BR_INCREFS, - BR_ACQUIRE, - BR_RELEASE, - BR_DECREFS, - BR_ATTEMPT_ACQUIRE, - BR_NOOP, - BR_SPAWN_LOOPER, - BR_FINISHED, - BR_DEAD_BINDER, - BR_CLEAR_DEATH_NOTIFICATION_DONE, - BR_FAILED_REPLY, -}; - -enum BinderDriverCommandProtocol { - BC_TRANSACTION, - BC_REPLY, - BC_ACQUIRE_RESULT, - BC_FREE_BUFFER, - BC_INCREFS, - BC_ACQUIRE, - BC_RELEASE, - BC_DECREFS, - BC_INCREFS_DONE, - BC_ACQUIRE_DONE, - BC_ATTEMPT_ACQUIRE, - BC_REGISTER_LOOPER, - BC_ENTER_LOOPER, - BC_EXIT_LOOPER, - BC_REQUEST_DEATH_NOTIFICATION, - BC_CLEAR_DEATH_NOTIFICATION, - BC_DEAD_BINDER_DONE, -}; - -#endif - -#ifdef __cplusplus -} // namespace android -#endif - -#endif // _BINDER_MODULE_H_ diff --git a/include/private/utils/futex_synchro.h b/include/private/utils/futex_synchro.h deleted file mode 100644 index ac2ab19..0000000 --- a/include/private/utils/futex_synchro.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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 _FUTEX_SYNCHRO_H -#define _FUTEX_SYNCHRO_H - -#ifndef HAVE_FUTEX -#error "HAVE_FUTEX not defined" -#endif - -#define FUTEX_WAIT_INFINITE (0) - -typedef struct futex_mutex_t futex_mutex_t; - -struct futex_mutex_t -{ - volatile int value; -}; - -typedef struct futex_cond_t futex_cond_t; - -struct futex_cond_t -{ - volatile int value; -}; - - -#if __cplusplus -extern "C" { -#endif - -void futex_mutex_init(futex_mutex_t *m); -int futex_mutex_lock(futex_mutex_t *m, unsigned msec); -void futex_mutex_unlock(futex_mutex_t *m); -int futex_mutex_trylock(futex_mutex_t *m); - -void futex_cond_init(futex_cond_t *c); -int futex_cond_wait(futex_cond_t *c, futex_mutex_t *m, unsigned msec); -void futex_cond_signal(futex_cond_t *c); -void futex_cond_broadcast(futex_cond_t *c); - -#if __cplusplus -} // extern "C" -#endif - -#endif // _FUTEX_SYNCHRO_H - diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk deleted file mode 100644 index 8020da2..0000000 --- a/media/libmedia/Android.mk +++ /dev/null @@ -1,39 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - AudioTrack.cpp \ - IAudioFlinger.cpp \ - IAudioFlingerClient.cpp \ - IAudioTrack.cpp \ - IAudioRecord.cpp \ - AudioRecord.cpp \ - AudioSystem.cpp \ - mediaplayer.cpp \ - IMediaPlayerService.cpp \ - IMediaPlayerClient.cpp \ - IMediaPlayer.cpp \ - IMediaRecorder.cpp \ - mediarecorder.cpp \ - IMediaMetadataRetriever.cpp \ - mediametadataretriever.cpp \ - ToneGenerator.cpp \ - JetPlayer.cpp - -LOCAL_SHARED_LIBRARIES := \ - libui libcutils libutils libsonivox - -LOCAL_MODULE:= libmedia - -ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true) -LOCAL_LDLIBS += -ldl -endif - -ifneq ($(TARGET_SIMULATOR),true) -LOCAL_SHARED_LIBRARIES += libdl -endif - -LOCAL_C_INCLUDES := \ - $(call include-path-for, graphics corecg) - -include $(BUILD_SHARED_LIBRARY) diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp deleted file mode 100644 index e833c85..0000000 --- a/media/libmedia/AudioRecord.cpp +++ /dev/null @@ -1,555 +0,0 @@ -/* -** -** Copyright 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 "AudioRecord" - -#include -#include - -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) -#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) - -namespace android { - -// --------------------------------------------------------------------------- - -AudioRecord::AudioRecord() - : mStatus(NO_INIT) -{ -} - -AudioRecord::AudioRecord( - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags, - callback_t cbf, - void* user, - int notificationFrames) - : mStatus(NO_INIT) -{ - mStatus = set(streamType, sampleRate, format, channelCount, - frameCount, flags, cbf, user, notificationFrames); -} - -AudioRecord::~AudioRecord() -{ - if (mStatus == NO_ERROR) { - // Make sure that callback function exits in the case where - // it is looping on buffer empty condition in obtainBuffer(). - // Otherwise the callback thread will never exit. - stop(); - if (mClientRecordThread != 0) { - mCblk->cv.signal(); - mClientRecordThread->requestExitAndWait(); - mClientRecordThread.clear(); - } - mAudioRecord.clear(); - IPCThreadState::self()->flushCommands(); - } -} - -status_t AudioRecord::set( - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags, - callback_t cbf, - void* user, - int notificationFrames, - bool threadCanCallJava) -{ - - LOGV("set(): sampleRate %d, channelCount %d, frameCount %d",sampleRate, channelCount, frameCount); - if (mAudioFlinger != 0) { - return INVALID_OPERATION; - } - - const sp& audioFlinger = AudioSystem::get_audio_flinger(); - if (audioFlinger == 0) { - return NO_INIT; - } - - if (streamType == DEFAULT_INPUT) { - streamType = MIC_INPUT; - } - - if (sampleRate == 0) { - sampleRate = DEFAULT_SAMPLE_RATE; - } - // these below should probably come from the audioFlinger too... - if (format == 0) { - format = AudioSystem::PCM_16_BIT; - } - if (channelCount == 0) { - channelCount = 1; - } - - // validate parameters - if (format != AudioSystem::PCM_16_BIT) { - return BAD_VALUE; - } - if (channelCount != 1 && channelCount != 2) { - return BAD_VALUE; - } - - // TODO: Get input frame count from hardware. - int minFrameCount = 1024*2; - - if (frameCount == 0) { - frameCount = minFrameCount; - } else if (frameCount < minFrameCount) { - return BAD_VALUE; - } - - if (notificationFrames == 0) { - notificationFrames = frameCount/2; - } - - // open record channel - status_t status; - sp record = audioFlinger->openRecord(getpid(), streamType, - sampleRate, format, channelCount, frameCount, flags, &status); - if (record == 0) { - LOGE("AudioFlinger could not create record track, status: %d", status); - return status; - } - sp cblk = record->getCblk(); - if (cblk == 0) { - return NO_INIT; - } - if (cbf != 0) { - mClientRecordThread = new ClientRecordThread(*this, threadCanCallJava); - if (mClientRecordThread == 0) { - return NO_INIT; - } - } - - mStatus = NO_ERROR; - - mAudioFlinger = audioFlinger; - mAudioRecord = record; - mCblkMemory = cblk; - mCblk = static_cast(cblk->pointer()); - mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); - mCblk->out = 0; - mSampleRate = sampleRate; - mFormat = format; - // Update buffer size in case it has been limited by AudioFlinger during track creation - mFrameCount = mCblk->frameCount; - mChannelCount = channelCount; - mActive = 0; - mCbf = cbf; - mNotificationFrames = notificationFrames; - mRemainingFrames = notificationFrames; - mUserData = user; - // TODO: add audio hardware input latency here - mLatency = (1000*mFrameCount) / mSampleRate; - mMarkerPosition = 0; - mNewPosition = 0; - mUpdatePeriod = 0; - - return NO_ERROR; -} - -status_t AudioRecord::initCheck() const -{ - return mStatus; -} - -// ------------------------------------------------------------------------- - -uint32_t AudioRecord::latency() const -{ - return mLatency; -} - -uint32_t AudioRecord::sampleRate() const -{ - return mSampleRate; -} - -int AudioRecord::format() const -{ - return mFormat; -} - -int AudioRecord::channelCount() const -{ - return mChannelCount; -} - -uint32_t AudioRecord::frameCount() const -{ - return mFrameCount; -} - -int AudioRecord::frameSize() const -{ - return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t)); -} - -// ------------------------------------------------------------------------- - -status_t AudioRecord::start() -{ - status_t ret = NO_ERROR; - sp t = mClientRecordThread; - - LOGV("start"); - - if (t != 0) { - if (t->exitPending()) { - if (t->requestExitAndWait() == WOULD_BLOCK) { - LOGE("AudioRecord::start called from thread"); - return WOULD_BLOCK; - } - } - t->mLock.lock(); - } - - if (android_atomic_or(1, &mActive) == 0) { - mNewPosition = mCblk->user + mUpdatePeriod; - mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; - mCblk->waitTimeMs = 0; - if (t != 0) { - t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT); - } else { - setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT); - } - ret = mAudioRecord->start(); - } - - if (t != 0) { - t->mLock.unlock(); - } - - return ret; -} - -status_t AudioRecord::stop() -{ - sp t = mClientRecordThread; - - LOGV("stop"); - - if (t != 0) { - t->mLock.lock(); - } - - if (android_atomic_and(~1, &mActive) == 1) { - mAudioRecord->stop(); - if (t != 0) { - t->requestExit(); - } else { - setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL); - } - } - - if (t != 0) { - t->mLock.unlock(); - } - - return NO_ERROR; -} - -bool AudioRecord::stopped() const -{ - return !mActive; -} - -status_t AudioRecord::setMarkerPosition(uint32_t marker) -{ - if (mCbf == 0) return INVALID_OPERATION; - - mMarkerPosition = marker; - - return NO_ERROR; -} - -status_t AudioRecord::getMarkerPosition(uint32_t *marker) -{ - if (marker == 0) return BAD_VALUE; - - *marker = mMarkerPosition; - - return NO_ERROR; -} - -status_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod) -{ - if (mCbf == 0) return INVALID_OPERATION; - - uint32_t curPosition; - getPosition(&curPosition); - mNewPosition = curPosition + updatePeriod; - mUpdatePeriod = updatePeriod; - - return NO_ERROR; -} - -status_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) -{ - if (updatePeriod == 0) return BAD_VALUE; - - *updatePeriod = mUpdatePeriod; - - return NO_ERROR; -} - -status_t AudioRecord::getPosition(uint32_t *position) -{ - if (position == 0) return BAD_VALUE; - - *position = mCblk->user; - - return NO_ERROR; -} - - -// ------------------------------------------------------------------------- - -status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) -{ - int active; - int timeout = 0; - status_t result; - audio_track_cblk_t* cblk = mCblk; - uint32_t framesReq = audioBuffer->frameCount; - - audioBuffer->frameCount = 0; - audioBuffer->size = 0; - - uint32_t framesReady = cblk->framesReady(); - - if (framesReady == 0) { - Mutex::Autolock _l(cblk->lock); - goto start_loop_here; - while (framesReady == 0) { - active = mActive; - if (UNLIKELY(!active)) - return NO_MORE_BUFFERS; - if (UNLIKELY(!waitCount)) - return WOULD_BLOCK; - timeout = 0; - result = cblk->cv.waitRelative(cblk->lock, milliseconds(WAIT_PERIOD_MS)); - if (__builtin_expect(result!=NO_ERROR, false)) { - cblk->waitTimeMs += WAIT_PERIOD_MS; - if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) { - LOGW( "obtainBuffer timed out (is the CPU pegged?) " - "user=%08x, server=%08x", cblk->user, cblk->server); - timeout = 1; - cblk->waitTimeMs = 0; - } - if (--waitCount == 0) { - return TIMED_OUT; - } - } - // read the server count again - start_loop_here: - framesReady = cblk->framesReady(); - } - } - - LOGW_IF(timeout, - "*** SERIOUS WARNING *** obtainBuffer() timed out " - "but didn't need to be locked. We recovered, but " - "this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server); - - cblk->waitTimeMs = 0; - - if (framesReq > framesReady) { - framesReq = framesReady; - } - - uint32_t u = cblk->user; - uint32_t bufferEnd = cblk->userBase + cblk->frameCount; - - if (u + framesReq > bufferEnd) { - framesReq = bufferEnd - u; - } - - audioBuffer->flags = 0; - audioBuffer->channelCount= mChannelCount; - audioBuffer->format = mFormat; - audioBuffer->frameCount = framesReq; - audioBuffer->size = framesReq*mChannelCount*sizeof(int16_t); - audioBuffer->raw = (int8_t*)cblk->buffer(u); - active = mActive; - return active ? status_t(NO_ERROR) : status_t(STOPPED); -} - -void AudioRecord::releaseBuffer(Buffer* audioBuffer) -{ - audio_track_cblk_t* cblk = mCblk; - cblk->stepUser(audioBuffer->frameCount); -} - -// ------------------------------------------------------------------------- - -ssize_t AudioRecord::read(void* buffer, size_t userSize) -{ - ssize_t read = 0; - Buffer audioBuffer; - int8_t *dst = static_cast(buffer); - - if (ssize_t(userSize) < 0) { - // sanity-check. user is most-likely passing an error code. - LOGE("AudioRecord::read(buffer=%p, size=%u (%d)", - buffer, userSize, userSize); - return BAD_VALUE; - } - - LOGV("read size: %d", userSize); - - do { - - audioBuffer.frameCount = userSize/mChannelCount/sizeof(int16_t); - - // Calling obtainBuffer() with a negative wait count causes - // an (almost) infinite wait time. - status_t err = obtainBuffer(&audioBuffer, -1); - if (err < 0) { - // out of buffers, return #bytes written - if (err == status_t(NO_MORE_BUFFERS)) - break; - return ssize_t(err); - } - - size_t bytesRead = audioBuffer.size; - memcpy(dst, audioBuffer.i8, bytesRead); - - dst += bytesRead; - userSize -= bytesRead; - read += bytesRead; - - releaseBuffer(&audioBuffer); - } while (userSize); - - return read; -} - -// ------------------------------------------------------------------------- - -bool AudioRecord::processAudioBuffer(const sp& thread) -{ - Buffer audioBuffer; - uint32_t frames = mRemainingFrames; - size_t readSize; - - // Manage marker callback - if (mMarkerPosition > 0) { - if (mCblk->user >= mMarkerPosition) { - mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition); - mMarkerPosition = 0; - } - } - - // Manage new position callback - if (mUpdatePeriod > 0) { - while (mCblk->user >= mNewPosition) { - mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition); - mNewPosition += mUpdatePeriod; - } - } - - do { - audioBuffer.frameCount = frames; - // Calling obtainBuffer() with a wait count of 1 - // limits wait time to WAIT_PERIOD_MS. This prevents from being - // stuck here not being able to handle timed events (position, markers). - status_t err = obtainBuffer(&audioBuffer, 1); - if (err < NO_ERROR) { - if (err != TIMED_OUT) { - LOGE("Error obtaining an audio buffer, giving up."); - return false; - } - break; - } - if (err == status_t(STOPPED)) return false; - - size_t reqSize = audioBuffer.size; - mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer); - readSize = audioBuffer.size; - - // Sanity check on returned size - if (ssize_t(readSize) <= 0) break; - if (readSize > reqSize) readSize = reqSize; - - audioBuffer.size = readSize; - audioBuffer.frameCount = readSize/mChannelCount/sizeof(int16_t); - frames -= audioBuffer.frameCount; - - releaseBuffer(&audioBuffer); - - } while (frames); - - - // Manage overrun callback - if (mActive && (mCblk->framesAvailable_l() == 0)) { - LOGV("Overrun user: %x, server: %x, flowControlFlag %d", mCblk->user, mCblk->server, mCblk->flowControlFlag); - if (mCblk->flowControlFlag == 0) { - mCbf(EVENT_OVERRUN, mUserData, 0); - mCblk->flowControlFlag = 1; - } - } - - if (frames == 0) { - mRemainingFrames = mNotificationFrames; - } else { - mRemainingFrames = frames; - } - return true; -} - -// ========================================================================= - -AudioRecord::ClientRecordThread::ClientRecordThread(AudioRecord& receiver, bool bCanCallJava) - : Thread(bCanCallJava), mReceiver(receiver) -{ -} - -bool AudioRecord::ClientRecordThread::threadLoop() -{ - return mReceiver.processAudioBuffer(this); -} - -// ------------------------------------------------------------------------- - -}; // namespace android - diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp deleted file mode 100644 index 63dfc3b..0000000 --- a/media/libmedia/AudioSystem.cpp +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright (C) 2006-2007 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_TAG "AudioSystem" -//#define LOG_NDEBUG 0 - -#include -#include -#include -#include - -namespace android { - -// client singleton for AudioFlinger binder interface -Mutex AudioSystem::gLock; -sp AudioSystem::gAudioFlinger; -sp AudioSystem::gAudioFlingerClient; -audio_error_callback AudioSystem::gAudioErrorCallback = NULL; -// Cached values -int AudioSystem::gOutSamplingRate[NUM_AUDIO_OUTPUT_TYPES]; -int AudioSystem::gOutFrameCount[NUM_AUDIO_OUTPUT_TYPES]; -uint32_t AudioSystem::gOutLatency[NUM_AUDIO_OUTPUT_TYPES]; -bool AudioSystem::gA2dpEnabled; -// Cached values for recording queries -uint32_t AudioSystem::gPrevInSamplingRate = 16000; -int AudioSystem::gPrevInFormat = AudioSystem::PCM_16_BIT; -int AudioSystem::gPrevInChannelCount = 1; -size_t AudioSystem::gInBuffSize = 0; - - -// establish binder interface to AudioFlinger service -const sp& AudioSystem::get_audio_flinger() -{ - Mutex::Autolock _l(gLock); - if (gAudioFlinger.get() == 0) { - sp sm = defaultServiceManager(); - sp binder; - do { - binder = sm->getService(String16("media.audio_flinger")); - if (binder != 0) - break; - LOGW("AudioFlinger not published, waiting..."); - usleep(500000); // 0.5 s - } while(true); - if (gAudioFlingerClient == NULL) { - gAudioFlingerClient = new AudioFlingerClient(); - } else { - if (gAudioErrorCallback) { - gAudioErrorCallback(NO_ERROR); - } - } - binder->linkToDeath(gAudioFlingerClient); - gAudioFlinger = interface_cast(binder); - gAudioFlinger->registerClient(gAudioFlingerClient); - // Cache frequently accessed parameters - for (int output = 0; output < NUM_AUDIO_OUTPUT_TYPES; output++) { - gOutFrameCount[output] = (int)gAudioFlinger->frameCount(output); - gOutSamplingRate[output] = (int)gAudioFlinger->sampleRate(output); - gOutLatency[output] = gAudioFlinger->latency(output); - } - gA2dpEnabled = gAudioFlinger->isA2dpEnabled(); - } - LOGE_IF(gAudioFlinger==0, "no AudioFlinger!?"); - return gAudioFlinger; -} - -// routing helper functions -status_t AudioSystem::speakerphone(bool state) { - uint32_t routes = state ? ROUTE_SPEAKER : ROUTE_EARPIECE; - return setRouting(MODE_IN_CALL, routes, ROUTE_ALL); -} - -status_t AudioSystem::isSpeakerphoneOn(bool* state) { - uint32_t routes = 0; - status_t s = getRouting(MODE_IN_CALL, &routes); - *state = !!(routes & ROUTE_SPEAKER); - return s; -} - -status_t AudioSystem::bluetoothSco(bool state) { - uint32_t mask = ROUTE_BLUETOOTH_SCO; - uint32_t routes = state ? mask : ROUTE_EARPIECE; - return setRouting(MODE_IN_CALL, routes, ROUTE_ALL); -} - -status_t AudioSystem::isBluetoothScoOn(bool* state) { - uint32_t routes = 0; - status_t s = getRouting(MODE_IN_CALL, &routes); - *state = !!(routes & ROUTE_BLUETOOTH_SCO); - return s; -} - -status_t AudioSystem::muteMicrophone(bool state) { - const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - return af->setMicMute(state); -} - -status_t AudioSystem::isMicrophoneMuted(bool* state) { - const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - *state = af->getMicMute(); - return NO_ERROR; -} - -status_t AudioSystem::setMasterVolume(float value) -{ - const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - af->setMasterVolume(value); - return NO_ERROR; -} - -status_t AudioSystem::setMasterMute(bool mute) -{ - const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - af->setMasterMute(mute); - return NO_ERROR; -} - -status_t AudioSystem::getMasterVolume(float* volume) -{ - const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - *volume = af->masterVolume(); - return NO_ERROR; -} - -status_t AudioSystem::getMasterMute(bool* mute) -{ - const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - *mute = af->masterMute(); - return NO_ERROR; -} - -status_t AudioSystem::setStreamVolume(int stream, float value) -{ - if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE; - const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - af->setStreamVolume(stream, value); - return NO_ERROR; -} - -status_t AudioSystem::setStreamMute(int stream, bool mute) -{ - if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE; - const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - af->setStreamMute(stream, mute); - return NO_ERROR; -} - -status_t AudioSystem::getStreamVolume(int stream, float* volume) -{ - if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE; - const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - *volume = af->streamVolume(stream); - return NO_ERROR; -} - -status_t AudioSystem::getStreamMute(int stream, bool* mute) -{ - if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE; - const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - *mute = af->streamMute(stream); - return NO_ERROR; -} - -status_t AudioSystem::setMode(int mode) -{ - if (mode >= NUM_MODES) return BAD_VALUE; - const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - return af->setMode(mode); -} - -status_t AudioSystem::getMode(int* mode) -{ - const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - *mode = af->getMode(); - return NO_ERROR; -} - -status_t AudioSystem::setRouting(int mode, uint32_t routes, uint32_t mask) -{ - const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - return af->setRouting(mode, routes, mask); -} - -status_t AudioSystem::getRouting(int mode, uint32_t* routes) -{ - const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - uint32_t r = af->getRouting(mode); - *routes = r; - return NO_ERROR; -} - -status_t AudioSystem::isMusicActive(bool* state) { - const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - *state = af->isMusicActive(); - return NO_ERROR; -} - -// Temporary interface, do not use -// TODO: Replace with a more generic key:value get/set mechanism -status_t AudioSystem::setParameter(const char* key, const char* value) { - const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - return af->setParameter(key, value); -} - -// convert volume steps to natural log scale - -// change this value to change volume scaling -static const float dBPerStep = 0.5f; -// shouldn't need to touch these -static const float dBConvert = -dBPerStep * 2.302585093f / 20.0f; -static const float dBConvertInverse = 1.0f / dBConvert; - -float AudioSystem::linearToLog(int volume) -{ - // float v = volume ? exp(float(100 - volume) * dBConvert) : 0; - // LOGD("linearToLog(%d)=%f", volume, v); - // return v; - return volume ? exp(float(100 - volume) * dBConvert) : 0; -} - -int AudioSystem::logToLinear(float volume) -{ - // int v = volume ? 100 - int(dBConvertInverse * log(volume) + 0.5) : 0; - // LOGD("logTolinear(%d)=%f", v, volume); - // return v; - return volume ? 100 - int(dBConvertInverse * log(volume) + 0.5) : 0; -} - -status_t AudioSystem::getOutputSamplingRate(int* samplingRate, int streamType) -{ - int output = getOutput(streamType); - - if (gOutSamplingRate[output] == 0) { - const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - // gOutSamplingRate is updated by get_audio_flinger() - } - LOGV("getOutputSamplingRate() streamType %d, output %d, sampling rate %d", streamType, output, gOutSamplingRate[output]); - *samplingRate = gOutSamplingRate[output]; - - return NO_ERROR; -} - -status_t AudioSystem::getOutputFrameCount(int* frameCount, int streamType) -{ - int output = getOutput(streamType); - - if (gOutFrameCount[output] == 0) { - const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - // gOutFrameCount is updated by get_audio_flinger() - } - LOGV("getOutputFrameCount() streamType %d, output %d, frame count %d", streamType, output, gOutFrameCount[output]); - - *frameCount = gOutFrameCount[output]; - return NO_ERROR; -} - -status_t AudioSystem::getOutputLatency(uint32_t* latency, int streamType) -{ - int output = getOutput(streamType); - - if (gOutLatency[output] == 0) { - const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - // gOutLatency is updated by get_audio_flinger() - } - LOGV("getOutputLatency() streamType %d, output %d, latency %d", streamType, output, gOutLatency[output]); - - *latency = gOutLatency[output]; - - return NO_ERROR; -} - -status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, int format, int channelCount, - size_t* buffSize) -{ - // Do we have a stale gInBufferSize or are we requesting the input buffer size for new values - if ((gInBuffSize == 0) || (sampleRate != gPrevInSamplingRate) || (format != gPrevInFormat) - || (channelCount != gPrevInChannelCount)) { - // save the request params - gPrevInSamplingRate = sampleRate; - gPrevInFormat = format; - gPrevInChannelCount = channelCount; - - gInBuffSize = 0; - const sp& af = AudioSystem::get_audio_flinger(); - if (af == 0) { - return PERMISSION_DENIED; - } - gInBuffSize = af->getInputBufferSize(sampleRate, format, channelCount); - } - *buffSize = gInBuffSize; - - return NO_ERROR; -} - -// --------------------------------------------------------------------------- - -void AudioSystem::AudioFlingerClient::binderDied(const wp& who) { - Mutex::Autolock _l(AudioSystem::gLock); - AudioSystem::gAudioFlinger.clear(); - - for (int output = 0; output < NUM_AUDIO_OUTPUT_TYPES; output++) { - gOutFrameCount[output] = 0; - gOutSamplingRate[output] = 0; - gOutLatency[output] = 0; - } - AudioSystem::gInBuffSize = 0; - - if (gAudioErrorCallback) { - gAudioErrorCallback(DEAD_OBJECT); - } - LOGW("AudioFlinger server died!"); -} - -void AudioSystem::AudioFlingerClient::a2dpEnabledChanged(bool enabled) { - gA2dpEnabled = enabled; - LOGV("AudioFlinger A2DP enabled status changed! %d", enabled); -} - -void AudioSystem::setErrorCallback(audio_error_callback cb) { - Mutex::Autolock _l(AudioSystem::gLock); - gAudioErrorCallback = cb; -} - -int AudioSystem::getOutput(int streamType) -{ - if (streamType == DEFAULT) { - streamType = MUSIC; - } - if (gA2dpEnabled && routedToA2dpOutput(streamType)) { - return AUDIO_OUTPUT_A2DP; - } else { - return AUDIO_OUTPUT_HARDWARE; - } -} - -bool AudioSystem::routedToA2dpOutput(int streamType) { - switch(streamType) { - case MUSIC: - case VOICE_CALL: - case BLUETOOTH_SCO: - case SYSTEM: - return true; - default: - return false; - } -} - - - -}; // namespace android - diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp deleted file mode 100644 index f8520a7..0000000 --- a/media/libmedia/AudioTrack.cpp +++ /dev/null @@ -1,1011 +0,0 @@ -/* //device/extlibs/pv/android/AudioTrack.cpp -** -** Copyright 2007, 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 "AudioTrack" - -#include -#include -#include - -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) -#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) - -namespace android { - -// --------------------------------------------------------------------------- - -AudioTrack::AudioTrack() - : mStatus(NO_INIT) -{ -} - -AudioTrack::AudioTrack( - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags, - callback_t cbf, - void* user, - int notificationFrames) - : mStatus(NO_INIT) -{ - mStatus = set(streamType, sampleRate, format, channelCount, - frameCount, flags, cbf, user, notificationFrames, 0); -} - -AudioTrack::AudioTrack( - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - const sp& sharedBuffer, - uint32_t flags, - callback_t cbf, - void* user, - int notificationFrames) - : mStatus(NO_INIT) -{ - mStatus = set(streamType, sampleRate, format, channelCount, - 0, flags, cbf, user, notificationFrames, sharedBuffer); -} - -AudioTrack::~AudioTrack() -{ - LOGV_IF(mSharedBuffer != 0, "Destructor sharedBuffer: %p", mSharedBuffer->pointer()); - - if (mStatus == NO_ERROR) { - // Make sure that callback function exits in the case where - // it is looping on buffer full condition in obtainBuffer(). - // Otherwise the callback thread will never exit. - stop(); - if (mAudioTrackThread != 0) { - mCblk->cv.signal(); - mAudioTrackThread->requestExitAndWait(); - mAudioTrackThread.clear(); - } - mAudioTrack.clear(); - IPCThreadState::self()->flushCommands(); - } -} - -status_t AudioTrack::set( - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags, - callback_t cbf, - void* user, - int notificationFrames, - const sp& sharedBuffer, - bool threadCanCallJava) -{ - - LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size()); - - if (mAudioFlinger != 0) { - LOGE("Track already in use"); - return INVALID_OPERATION; - } - - const sp& audioFlinger = AudioSystem::get_audio_flinger(); - if (audioFlinger == 0) { - LOGE("Could not get audioflinger"); - return NO_INIT; - } - int afSampleRate; - if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { - return NO_INIT; - } - int afFrameCount; - if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) { - return NO_INIT; - } - uint32_t afLatency; - if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) { - return NO_INIT; - } - - // handle default values first. - if (streamType == AudioSystem::DEFAULT) { - streamType = AudioSystem::MUSIC; - } - if (sampleRate == 0) { - sampleRate = afSampleRate; - } - // these below should probably come from the audioFlinger too... - if (format == 0) { - format = AudioSystem::PCM_16_BIT; - } - if (channelCount == 0) { - channelCount = 2; - } - - // validate parameters - if (((format != AudioSystem::PCM_8_BIT) || sharedBuffer != 0) && - (format != AudioSystem::PCM_16_BIT)) { - LOGE("Invalid format"); - return BAD_VALUE; - } - if (channelCount != 1 && channelCount != 2) { - LOGE("Invalid channel number"); - return BAD_VALUE; - } - - // Ensure that buffer depth covers at least audio hardware latency - uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate); - // When playing from shared buffer, playback will start even if last audioflinger - // block is partly filled. - if (sharedBuffer != 0 && minBufCount > 1) { - minBufCount--; - } - - int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate; - - if (sharedBuffer == 0) { - if (frameCount == 0) { - frameCount = minFrameCount; - } - if (notificationFrames == 0) { - notificationFrames = frameCount/2; - } - // Make sure that application is notified with sufficient margin - // before underrun - if (notificationFrames > frameCount/2) { - notificationFrames = frameCount/2; - } - } else { - // Ensure that buffer alignment matches channelcount - if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) { - LOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount); - return BAD_VALUE; - } - frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t); - } - - if (frameCount < minFrameCount) { - LOGE("Invalid buffer size: minFrameCount %d, frameCount %d", minFrameCount, frameCount); - return BAD_VALUE; - } - - // create the track - status_t status; - sp track = audioFlinger->createTrack(getpid(), - streamType, sampleRate, format, channelCount, frameCount, flags, sharedBuffer, &status); - - if (track == 0) { - LOGE("AudioFlinger could not create track, status: %d", status); - return status; - } - sp cblk = track->getCblk(); - if (cblk == 0) { - LOGE("Could not get control block"); - return NO_INIT; - } - if (cbf != 0) { - mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava); - if (mAudioTrackThread == 0) { - LOGE("Could not create callback thread"); - return NO_INIT; - } - } - - mStatus = NO_ERROR; - - mAudioFlinger = audioFlinger; - mAudioTrack = track; - mCblkMemory = cblk; - mCblk = static_cast(cblk->pointer()); - mCblk->out = 1; - // Update buffer size in case it has been limited by AudioFlinger during track creation - mFrameCount = mCblk->frameCount; - if (sharedBuffer == 0) { - mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); - } else { - mCblk->buffers = sharedBuffer->pointer(); - // Force buffer full condition as data is already present in shared memory - mCblk->stepUser(mFrameCount); - } - mCblk->volume[0] = mCblk->volume[1] = 0x1000; - mVolume[LEFT] = 1.0f; - mVolume[RIGHT] = 1.0f; - mSampleRate = sampleRate; - mStreamType = streamType; - mFormat = format; - mChannelCount = channelCount; - mSharedBuffer = sharedBuffer; - mMuted = false; - mActive = 0; - mCbf = cbf; - mNotificationFrames = notificationFrames; - mRemainingFrames = notificationFrames; - mUserData = user; - mLatency = afLatency + (1000*mFrameCount) / mSampleRate; - mLoopCount = 0; - mMarkerPosition = 0; - mNewPosition = 0; - mUpdatePeriod = 0; - - return NO_ERROR; -} - -status_t AudioTrack::initCheck() const -{ - return mStatus; -} - -// ------------------------------------------------------------------------- - -uint32_t AudioTrack::latency() const -{ - return mLatency; -} - -int AudioTrack::streamType() const -{ - return mStreamType; -} - -uint32_t AudioTrack::sampleRate() const -{ - return mSampleRate; -} - -int AudioTrack::format() const -{ - return mFormat; -} - -int AudioTrack::channelCount() const -{ - return mChannelCount; -} - -uint32_t AudioTrack::frameCount() const -{ - return mFrameCount; -} - -int AudioTrack::frameSize() const -{ - return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t)); -} - -sp& AudioTrack::sharedBuffer() -{ - return mSharedBuffer; -} - -// ------------------------------------------------------------------------- - -void AudioTrack::start() -{ - sp t = mAudioTrackThread; - - LOGV("start"); - if (t != 0) { - if (t->exitPending()) { - if (t->requestExitAndWait() == WOULD_BLOCK) { - LOGE("AudioTrack::start called from thread"); - return; - } - } - t->mLock.lock(); - } - - if (android_atomic_or(1, &mActive) == 0) { - mNewPosition = mCblk->server + mUpdatePeriod; - mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS; - mCblk->waitTimeMs = 0; - if (t != 0) { - t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT); - } else { - setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT); - } - mAudioTrack->start(); - } - - if (t != 0) { - t->mLock.unlock(); - } -} - -void AudioTrack::stop() -{ - sp t = mAudioTrackThread; - - LOGV("stop"); - if (t != 0) { - t->mLock.lock(); - } - - if (android_atomic_and(~1, &mActive) == 1) { - mAudioTrack->stop(); - // Cancel loops (If we are in the middle of a loop, playback - // would not stop until loopCount reaches 0). - setLoop(0, 0, 0); - // Force flush if a shared buffer is used otherwise audioflinger - // will not stop before end of buffer is reached. - if (mSharedBuffer != 0) { - flush(); - } - if (t != 0) { - t->requestExit(); - } else { - setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL); - } - } - - if (t != 0) { - t->mLock.unlock(); - } -} - -bool AudioTrack::stopped() const -{ - return !mActive; -} - -void AudioTrack::flush() -{ - LOGV("flush"); - - if (!mActive) { - mCblk->lock.lock(); - mAudioTrack->flush(); - // Release AudioTrack callback thread in case it was waiting for new buffers - // in AudioTrack::obtainBuffer() - mCblk->cv.signal(); - mCblk->lock.unlock(); - } -} - -void AudioTrack::pause() -{ - LOGV("pause"); - if (android_atomic_and(~1, &mActive) == 1) { - mActive = 0; - mAudioTrack->pause(); - } -} - -void AudioTrack::mute(bool e) -{ - mAudioTrack->mute(e); - mMuted = e; -} - -bool AudioTrack::muted() const -{ - return mMuted; -} - -void AudioTrack::setVolume(float left, float right) -{ - mVolume[LEFT] = left; - mVolume[RIGHT] = right; - - // write must be atomic - mCblk->volumeLR = (int32_t(int16_t(left * 0x1000)) << 16) | int16_t(right * 0x1000); -} - -void AudioTrack::getVolume(float* left, float* right) -{ - *left = mVolume[LEFT]; - *right = mVolume[RIGHT]; -} - -void AudioTrack::setSampleRate(int rate) -{ - int afSamplingRate; - - if (AudioSystem::getOutputSamplingRate(&afSamplingRate, mStreamType) != NO_ERROR) { - return; - } - // Resampler implementation limits input sampling rate to 2 x output sampling rate. - if (rate > afSamplingRate*2) rate = afSamplingRate*2; - - if (rate > MAX_SAMPLE_RATE) rate = MAX_SAMPLE_RATE; - - mCblk->sampleRate = rate; -} - -uint32_t AudioTrack::getSampleRate() -{ - return uint32_t(mCblk->sampleRate); -} - -status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount) -{ - audio_track_cblk_t* cblk = mCblk; - - - Mutex::Autolock _l(cblk->lock); - - if (loopCount == 0) { - cblk->loopStart = UINT_MAX; - cblk->loopEnd = UINT_MAX; - cblk->loopCount = 0; - mLoopCount = 0; - return NO_ERROR; - } - - if (loopStart >= loopEnd || - loopEnd - loopStart > mFrameCount) { - LOGW("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %d", loopStart, loopEnd, loopCount, mFrameCount, cblk->user); - return BAD_VALUE; - } - // TODO handle shared buffer here: limit loop end to framecount - - cblk->loopStart = loopStart; - cblk->loopEnd = loopEnd; - cblk->loopCount = loopCount; - mLoopCount = loopCount; - - return NO_ERROR; -} - -status_t AudioTrack::getLoop(uint32_t *loopStart, uint32_t *loopEnd, int *loopCount) -{ - if (loopStart != 0) { - *loopStart = mCblk->loopStart; - } - if (loopEnd != 0) { - *loopEnd = mCblk->loopEnd; - } - if (loopCount != 0) { - if (mCblk->loopCount < 0) { - *loopCount = -1; - } else { - *loopCount = mCblk->loopCount; - } - } - - return NO_ERROR; -} - -status_t AudioTrack::setMarkerPosition(uint32_t marker) -{ - if (mCbf == 0) return INVALID_OPERATION; - - mMarkerPosition = marker; - - return NO_ERROR; -} - -status_t AudioTrack::getMarkerPosition(uint32_t *marker) -{ - if (marker == 0) return BAD_VALUE; - - *marker = mMarkerPosition; - - return NO_ERROR; -} - -status_t AudioTrack::setPositionUpdatePeriod(uint32_t updatePeriod) -{ - if (mCbf == 0) return INVALID_OPERATION; - - uint32_t curPosition; - getPosition(&curPosition); - mNewPosition = curPosition + updatePeriod; - mUpdatePeriod = updatePeriod; - - return NO_ERROR; -} - -status_t AudioTrack::getPositionUpdatePeriod(uint32_t *updatePeriod) -{ - if (updatePeriod == 0) return BAD_VALUE; - - *updatePeriod = mUpdatePeriod; - - return NO_ERROR; -} - -status_t AudioTrack::setPosition(uint32_t position) -{ - Mutex::Autolock _l(mCblk->lock); - - if (!stopped()) return INVALID_OPERATION; - - if (position > mCblk->user) return BAD_VALUE; - - mCblk->server = position; - mCblk->forceReady = 1; - - return NO_ERROR; -} - -status_t AudioTrack::getPosition(uint32_t *position) -{ - if (position == 0) return BAD_VALUE; - - *position = mCblk->server; - - return NO_ERROR; -} - -status_t AudioTrack::reload() -{ - if (!stopped()) return INVALID_OPERATION; - - flush(); - - mCblk->stepUser(mFrameCount); - - return NO_ERROR; -} - -// ------------------------------------------------------------------------- - -status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) -{ - int active; - int timeout = 0; - status_t result; - audio_track_cblk_t* cblk = mCblk; - uint32_t framesReq = audioBuffer->frameCount; - - audioBuffer->frameCount = 0; - audioBuffer->size = 0; - - uint32_t framesAvail = cblk->framesAvailable(); - - if (framesAvail == 0) { - Mutex::Autolock _l(cblk->lock); - goto start_loop_here; - while (framesAvail == 0) { - active = mActive; - if (UNLIKELY(!active)) { - LOGV("Not active and NO_MORE_BUFFERS"); - return NO_MORE_BUFFERS; - } - if (UNLIKELY(!waitCount)) - return WOULD_BLOCK; - timeout = 0; - result = cblk->cv.waitRelative(cblk->lock, milliseconds(WAIT_PERIOD_MS)); - if (__builtin_expect(result!=NO_ERROR, false)) { - cblk->waitTimeMs += WAIT_PERIOD_MS; - if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) { - // timing out when a loop has been set and we have already written upto loop end - // is a normal condition: no need to wake AudioFlinger up. - if (cblk->user < cblk->loopEnd) { - LOGW( "obtainBuffer timed out (is the CPU pegged?) " - "user=%08x, server=%08x", cblk->user, cblk->server); - mAudioFlinger->wakeUp(); - timeout = 1; - } - cblk->waitTimeMs = 0; - } - - if (--waitCount == 0) { - return TIMED_OUT; - } - } - // read the server count again - start_loop_here: - framesAvail = cblk->framesAvailable_l(); - } - } - - cblk->waitTimeMs = 0; - - if (framesReq > framesAvail) { - framesReq = framesAvail; - } - - uint32_t u = cblk->user; - uint32_t bufferEnd = cblk->userBase + cblk->frameCount; - - if (u + framesReq > bufferEnd) { - framesReq = bufferEnd - u; - } - - LOGW_IF(timeout, - "*** SERIOUS WARNING *** obtainBuffer() timed out " - "but didn't need to be locked. We recovered, but " - "this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server); - - audioBuffer->flags = mMuted ? Buffer::MUTE : 0; - audioBuffer->channelCount= mChannelCount; - audioBuffer->format = AudioSystem::PCM_16_BIT; - audioBuffer->frameCount = framesReq; - audioBuffer->size = framesReq*mChannelCount*sizeof(int16_t); - audioBuffer->raw = (int8_t *)cblk->buffer(u); - active = mActive; - return active ? status_t(NO_ERROR) : status_t(STOPPED); -} - -void AudioTrack::releaseBuffer(Buffer* audioBuffer) -{ - audio_track_cblk_t* cblk = mCblk; - cblk->stepUser(audioBuffer->frameCount); -} - -// ------------------------------------------------------------------------- - -ssize_t AudioTrack::write(const void* buffer, size_t userSize) -{ - - if (mSharedBuffer != 0) return INVALID_OPERATION; - - if (ssize_t(userSize) < 0) { - // sanity-check. user is most-likely passing an error code. - LOGE("AudioTrack::write(buffer=%p, size=%u (%d)", - buffer, userSize, userSize); - return BAD_VALUE; - } - - LOGV("write %d bytes, mActive=%d", userSize, mActive); - - ssize_t written = 0; - const int8_t *src = (const int8_t *)buffer; - Buffer audioBuffer; - - do { - audioBuffer.frameCount = userSize/mChannelCount; - if (mFormat == AudioSystem::PCM_16_BIT) { - audioBuffer.frameCount >>= 1; - } - // Calling obtainBuffer() with a negative wait count causes - // an (almost) infinite wait time. - status_t err = obtainBuffer(&audioBuffer, -1); - if (err < 0) { - // out of buffers, return #bytes written - if (err == status_t(NO_MORE_BUFFERS)) - break; - return ssize_t(err); - } - - size_t toWrite; - if (mFormat == AudioSystem::PCM_8_BIT) { - // Divide capacity by 2 to take expansion into account - toWrite = audioBuffer.size>>1; - // 8 to 16 bit conversion - int count = toWrite; - int16_t *dst = (int16_t *)(audioBuffer.i8); - while(count--) { - *dst++ = (int16_t)(*src++^0x80) << 8; - } - }else { - toWrite = audioBuffer.size; - memcpy(audioBuffer.i8, src, toWrite); - src += toWrite; - } - userSize -= toWrite; - written += toWrite; - - releaseBuffer(&audioBuffer); - } while (userSize); - - return written; -} - -// ------------------------------------------------------------------------- - -bool AudioTrack::processAudioBuffer(const sp& thread) -{ - Buffer audioBuffer; - uint32_t frames; - size_t writtenSize; - - // Manage underrun callback - if (mActive && (mCblk->framesReady() == 0)) { - LOGV("Underrun user: %x, server: %x, flowControlFlag %d", mCblk->user, mCblk->server, mCblk->flowControlFlag); - if (mCblk->flowControlFlag == 0) { - mCbf(EVENT_UNDERRUN, mUserData, 0); - if (mCblk->server == mCblk->frameCount) { - mCbf(EVENT_BUFFER_END, mUserData, 0); - } - mCblk->flowControlFlag = 1; - if (mSharedBuffer != 0) return false; - } - } - - // Manage loop end callback - while (mLoopCount > mCblk->loopCount) { - int loopCount = -1; - mLoopCount--; - if (mLoopCount >= 0) loopCount = mLoopCount; - - mCbf(EVENT_LOOP_END, mUserData, (void *)&loopCount); - } - - // Manage marker callback - if(mMarkerPosition > 0) { - if (mCblk->server >= mMarkerPosition) { - mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition); - mMarkerPosition = 0; - } - } - - // Manage new position callback - if(mUpdatePeriod > 0) { - while (mCblk->server >= mNewPosition) { - mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition); - mNewPosition += mUpdatePeriod; - } - } - - // If Shared buffer is used, no data is requested from client. - if (mSharedBuffer != 0) { - frames = 0; - } else { - frames = mRemainingFrames; - } - - do { - - audioBuffer.frameCount = frames; - - // Calling obtainBuffer() with a wait count of 1 - // limits wait time to WAIT_PERIOD_MS. This prevents from being - // stuck here not being able to handle timed events (position, markers, loops). - status_t err = obtainBuffer(&audioBuffer, 1); - if (err < NO_ERROR) { - if (err != TIMED_OUT) { - LOGE("Error obtaining an audio buffer, giving up."); - return false; - } - break; - } - if (err == status_t(STOPPED)) return false; - - // Divide buffer size by 2 to take into account the expansion - // due to 8 to 16 bit conversion: the callback must fill only half - // of the destination buffer - if (mFormat == AudioSystem::PCM_8_BIT) { - audioBuffer.size >>= 1; - } - - size_t reqSize = audioBuffer.size; - mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer); - writtenSize = audioBuffer.size; - - // Sanity check on returned size - if (ssize_t(writtenSize) <= 0) break; - if (writtenSize > reqSize) writtenSize = reqSize; - - if (mFormat == AudioSystem::PCM_8_BIT) { - // 8 to 16 bit conversion - const int8_t *src = audioBuffer.i8 + writtenSize-1; - int count = writtenSize; - int16_t *dst = audioBuffer.i16 + writtenSize-1; - while(count--) { - *dst-- = (int16_t)(*src--^0x80) << 8; - } - writtenSize <<= 1; - } - - audioBuffer.size = writtenSize; - audioBuffer.frameCount = writtenSize/mChannelCount/sizeof(int16_t); - frames -= audioBuffer.frameCount; - - releaseBuffer(&audioBuffer); - } - while (frames); - - if (frames == 0) { - mRemainingFrames = mNotificationFrames; - } else { - mRemainingFrames = frames; - } - return true; -} - -status_t AudioTrack::dump(int fd, const Vector& args) const -{ - - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - - result.append(" AudioTrack::dump\n"); - snprintf(buffer, 255, " stream type(%d), left - right volume(%f, %f)\n", mStreamType, mVolume[0], mVolume[1]); - result.append(buffer); - snprintf(buffer, 255, " format(%d), channel count(%d), frame count(%d)\n", mFormat, mChannelCount, mFrameCount); - result.append(buffer); - snprintf(buffer, 255, " sample rate(%d), status(%d), muted(%d)\n", mSampleRate, mStatus, mMuted); - result.append(buffer); - snprintf(buffer, 255, " active(%d), latency (%d)\n", mActive, mLatency); - result.append(buffer); - ::write(fd, result.string(), result.size()); - return NO_ERROR; -} - -// ========================================================================= - -AudioTrack::AudioTrackThread::AudioTrackThread(AudioTrack& receiver, bool bCanCallJava) - : Thread(bCanCallJava), mReceiver(receiver) -{ -} - -bool AudioTrack::AudioTrackThread::threadLoop() -{ - return mReceiver.processAudioBuffer(this); -} - -status_t AudioTrack::AudioTrackThread::readyToRun() -{ - return NO_ERROR; -} - -void AudioTrack::AudioTrackThread::onFirstRef() -{ -} - -// ========================================================================= - -audio_track_cblk_t::audio_track_cblk_t() - : user(0), server(0), userBase(0), serverBase(0), buffers(0), frameCount(0), - loopStart(UINT_MAX), loopEnd(UINT_MAX), loopCount(0), volumeLR(0), flowControlFlag(1), forceReady(0) -{ -} - -uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount) -{ - uint32_t u = this->user; - - u += frameCount; - // Ensure that user is never ahead of server for AudioRecord - if (out) { - // If stepServer() has been called once, switch to normal obtainBuffer() timeout period - if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS-1) { - bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; - } - } else if (u > this->server) { - LOGW("stepServer occured after track reset"); - u = this->server; - } - - if (u >= userBase + this->frameCount) { - userBase += this->frameCount; - } - - this->user = u; - - // Clear flow control error condition as new data has been written/read to/from buffer. - flowControlFlag = 0; - - return u; -} - -bool audio_track_cblk_t::stepServer(uint32_t frameCount) -{ - // the code below simulates lock-with-timeout - // we MUST do this to protect the AudioFlinger server - // as this lock is shared with the client. - status_t err; - - err = lock.tryLock(); - if (err == -EBUSY) { // just wait a bit - usleep(1000); - err = lock.tryLock(); - } - if (err != NO_ERROR) { - // probably, the client just died. - return false; - } - - uint32_t s = this->server; - - s += frameCount; - if (out) { - // Mark that we have read the first buffer so that next time stepUser() is called - // we switch to normal obtainBuffer() timeout period - if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) { - bufferTimeoutMs = MAX_RUN_TIMEOUT_MS - 1; - } - // It is possible that we receive a flush() - // while the mixer is processing a block: in this case, - // stepServer() is called After the flush() has reset u & s and - // we have s > u - if (s > this->user) { - LOGW("stepServer occured after track reset"); - s = this->user; - } - } - - if (s >= loopEnd) { - LOGW_IF(s > loopEnd, "stepServer: s %u > loopEnd %u", s, loopEnd); - s = loopStart; - if (--loopCount == 0) { - loopEnd = UINT_MAX; - loopStart = UINT_MAX; - } - } - if (s >= serverBase + this->frameCount) { - serverBase += this->frameCount; - } - - this->server = s; - - cv.signal(); - lock.unlock(); - return true; -} - -void* audio_track_cblk_t::buffer(uint32_t offset) const -{ - return (int16_t *)this->buffers + (offset-userBase)*this->channels; -} - -uint32_t audio_track_cblk_t::framesAvailable() -{ - Mutex::Autolock _l(lock); - return framesAvailable_l(); -} - -uint32_t audio_track_cblk_t::framesAvailable_l() -{ - uint32_t u = this->user; - uint32_t s = this->server; - - if (out) { - uint32_t limit = (s < loopStart) ? s : loopStart; - return limit + frameCount - u; - } else { - return frameCount + u - s; - } -} - -uint32_t audio_track_cblk_t::framesReady() -{ - uint32_t u = this->user; - uint32_t s = this->server; - - if (out) { - if (u < loopEnd) { - return u - s; - } else { - Mutex::Autolock _l(lock); - if (loopCount >= 0) { - return (loopEnd - loopStart)*loopCount + u - s; - } else { - return UINT_MAX; - } - } - } else { - return s - u; - } -} - -// ------------------------------------------------------------------------- - -}; // namespace android - diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp deleted file mode 100644 index 5cbb25c..0000000 --- a/media/libmedia/IAudioFlinger.cpp +++ /dev/null @@ -1,553 +0,0 @@ -/* //device/extlibs/pv/android/IAudioflinger.cpp -** -** Copyright 2007, 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_TAG "IAudioFlinger" -#include - -#include -#include - -#include - -#include - -namespace android { - -enum { - CREATE_TRACK = IBinder::FIRST_CALL_TRANSACTION, - OPEN_RECORD, - SAMPLE_RATE, - CHANNEL_COUNT, - FORMAT, - FRAME_COUNT, - LATENCY, - SET_MASTER_VOLUME, - SET_MASTER_MUTE, - MASTER_VOLUME, - MASTER_MUTE, - SET_STREAM_VOLUME, - SET_STREAM_MUTE, - STREAM_VOLUME, - STREAM_MUTE, - SET_MODE, - GET_MODE, - SET_ROUTING, - GET_ROUTING, - SET_MIC_MUTE, - GET_MIC_MUTE, - IS_MUSIC_ACTIVE, - SET_PARAMETER, - REGISTER_CLIENT, - GET_INPUTBUFFERSIZE, - WAKE_UP, - IS_A2DP_ENABLED -}; - -class BpAudioFlinger : public BpInterface -{ -public: - BpAudioFlinger(const sp& impl) - : BpInterface(impl) - { - } - - virtual sp createTrack( - pid_t pid, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags, - const sp& sharedBuffer, - status_t *status) - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeInt32(pid); - data.writeInt32(streamType); - data.writeInt32(sampleRate); - data.writeInt32(format); - data.writeInt32(channelCount); - data.writeInt32(frameCount); - data.writeInt32(flags); - data.writeStrongBinder(sharedBuffer->asBinder()); - status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply); - if (lStatus != NO_ERROR) { - LOGE("createTrack error: %s", strerror(-lStatus)); - } - lStatus = reply.readInt32(); - if (status) { - *status = lStatus; - } - return interface_cast(reply.readStrongBinder()); - } - - virtual sp openRecord( - pid_t pid, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - uint32_t flags, - status_t *status) - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeInt32(pid); - data.writeInt32(streamType); - data.writeInt32(sampleRate); - data.writeInt32(format); - data.writeInt32(channelCount); - data.writeInt32(frameCount); - data.writeInt32(flags); - remote()->transact(OPEN_RECORD, data, &reply); - status_t lStatus = reply.readInt32(); - if (status) { - *status = lStatus; - } - return interface_cast(reply.readStrongBinder()); - } - - virtual uint32_t sampleRate(int output) const - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeInt32(output); - remote()->transact(SAMPLE_RATE, data, &reply); - return reply.readInt32(); - } - - virtual int channelCount(int output) const - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeInt32(output); - remote()->transact(CHANNEL_COUNT, data, &reply); - return reply.readInt32(); - } - - virtual int format(int output) const - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeInt32(output); - remote()->transact(FORMAT, data, &reply); - return reply.readInt32(); - } - - virtual size_t frameCount(int output) const - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeInt32(output); - remote()->transact(FRAME_COUNT, data, &reply); - return reply.readInt32(); - } - - virtual uint32_t latency(int output) const - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeInt32(output); - remote()->transact(LATENCY, data, &reply); - return reply.readInt32(); - } - - virtual status_t setMasterVolume(float value) - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeFloat(value); - remote()->transact(SET_MASTER_VOLUME, data, &reply); - return reply.readInt32(); - } - - virtual status_t setMasterMute(bool muted) - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeInt32(muted); - remote()->transact(SET_MASTER_MUTE, data, &reply); - return reply.readInt32(); - } - - virtual float masterVolume() const - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - remote()->transact(MASTER_VOLUME, data, &reply); - return reply.readFloat(); - } - - virtual bool masterMute() const - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - remote()->transact(MASTER_MUTE, data, &reply); - return reply.readInt32(); - } - - virtual status_t setStreamVolume(int stream, float value) - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeInt32(stream); - data.writeFloat(value); - remote()->transact(SET_STREAM_VOLUME, data, &reply); - return reply.readInt32(); - } - - virtual status_t setStreamMute(int stream, bool muted) - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeInt32(stream); - data.writeInt32(muted); - remote()->transact(SET_STREAM_MUTE, data, &reply); - return reply.readInt32(); - } - - virtual float streamVolume(int stream) const - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeInt32(stream); - remote()->transact(STREAM_VOLUME, data, &reply); - return reply.readFloat(); - } - - virtual bool streamMute(int stream) const - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeInt32(stream); - remote()->transact(STREAM_MUTE, data, &reply); - return reply.readInt32(); - } - - virtual status_t setRouting(int mode, uint32_t routes, uint32_t mask) - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeInt32(mode); - data.writeInt32(routes); - data.writeInt32(mask); - remote()->transact(SET_ROUTING, data, &reply); - return reply.readInt32(); - } - - virtual uint32_t getRouting(int mode) const - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeInt32(mode); - remote()->transact(GET_ROUTING, data, &reply); - return reply.readInt32(); - } - - virtual status_t setMode(int mode) - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeInt32(mode); - remote()->transact(SET_MODE, data, &reply); - return reply.readInt32(); - } - - virtual int getMode() const - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - remote()->transact(GET_MODE, data, &reply); - return reply.readInt32(); - } - - virtual status_t setMicMute(bool state) - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeInt32(state); - remote()->transact(SET_MIC_MUTE, data, &reply); - return reply.readInt32(); - } - - virtual bool getMicMute() const - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - remote()->transact(GET_MIC_MUTE, data, &reply); - return reply.readInt32(); - } - - virtual bool isMusicActive() const - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - remote()->transact(IS_MUSIC_ACTIVE, data, &reply); - return reply.readInt32(); - } - - virtual status_t setParameter(const char* key, const char* value) - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeCString(key); - data.writeCString(value); - remote()->transact(SET_PARAMETER, data, &reply); - return reply.readInt32(); - } - - virtual void registerClient(const sp& client) - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeStrongBinder(client->asBinder()); - remote()->transact(REGISTER_CLIENT, data, &reply); - } - - virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount) - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - data.writeInt32(sampleRate); - data.writeInt32(format); - data.writeInt32(channelCount); - remote()->transact(GET_INPUTBUFFERSIZE, data, &reply); - return reply.readInt32(); - } - - virtual void wakeUp() - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - remote()->transact(WAKE_UP, data, &reply); - return; - } - - virtual bool isA2dpEnabled() const - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); - remote()->transact(IS_A2DP_ENABLED, data, &reply); - return (bool)reply.readInt32(); - } -}; - -IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger"); - -// ---------------------------------------------------------------------- - -#define CHECK_INTERFACE(interface, data, reply) \ - do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ - LOGW("Call incorrectly routed to " #interface); \ - return PERMISSION_DENIED; \ - } } while (0) - -status_t BnAudioFlinger::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case CREATE_TRACK: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - pid_t pid = data.readInt32(); - int streamType = data.readInt32(); - uint32_t sampleRate = data.readInt32(); - int format = data.readInt32(); - int channelCount = data.readInt32(); - size_t bufferCount = data.readInt32(); - uint32_t flags = data.readInt32(); - sp buffer = interface_cast(data.readStrongBinder()); - status_t status; - sp track = createTrack(pid, - streamType, sampleRate, format, - channelCount, bufferCount, flags, buffer, &status); - reply->writeInt32(status); - reply->writeStrongBinder(track->asBinder()); - return NO_ERROR; - } break; - case OPEN_RECORD: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - pid_t pid = data.readInt32(); - int streamType = data.readInt32(); - uint32_t sampleRate = data.readInt32(); - int format = data.readInt32(); - int channelCount = data.readInt32(); - size_t bufferCount = data.readInt32(); - uint32_t flags = data.readInt32(); - status_t status; - sp record = openRecord(pid, streamType, - sampleRate, format, channelCount, bufferCount, flags, &status); - reply->writeInt32(status); - reply->writeStrongBinder(record->asBinder()); - return NO_ERROR; - } break; - case SAMPLE_RATE: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - int output = data.readInt32(); - reply->writeInt32( sampleRate(output) ); - return NO_ERROR; - } break; - case CHANNEL_COUNT: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - int output = data.readInt32(); - reply->writeInt32( channelCount(output) ); - return NO_ERROR; - } break; - case FORMAT: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - int output = data.readInt32(); - reply->writeInt32( format(output) ); - return NO_ERROR; - } break; - case FRAME_COUNT: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - int output = data.readInt32(); - reply->writeInt32( frameCount(output) ); - return NO_ERROR; - } break; - case LATENCY: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - int output = data.readInt32(); - reply->writeInt32( latency(output) ); - return NO_ERROR; - } break; - case SET_MASTER_VOLUME: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - reply->writeInt32( setMasterVolume(data.readFloat()) ); - return NO_ERROR; - } break; - case SET_MASTER_MUTE: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - reply->writeInt32( setMasterMute(data.readInt32()) ); - return NO_ERROR; - } break; - case MASTER_VOLUME: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - reply->writeFloat( masterVolume() ); - return NO_ERROR; - } break; - case MASTER_MUTE: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - reply->writeInt32( masterMute() ); - return NO_ERROR; - } break; - case SET_STREAM_VOLUME: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - int stream = data.readInt32(); - reply->writeInt32( setStreamVolume(stream, data.readFloat()) ); - return NO_ERROR; - } break; - case SET_STREAM_MUTE: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - int stream = data.readInt32(); - reply->writeInt32( setStreamMute(stream, data.readInt32()) ); - return NO_ERROR; - } break; - case STREAM_VOLUME: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - int stream = data.readInt32(); - reply->writeFloat( streamVolume(stream) ); - return NO_ERROR; - } break; - case STREAM_MUTE: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - int stream = data.readInt32(); - reply->writeInt32( streamMute(stream) ); - return NO_ERROR; - } break; - case SET_ROUTING: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - int mode = data.readInt32(); - uint32_t routes = data.readInt32(); - uint32_t mask = data.readInt32(); - reply->writeInt32( setRouting(mode, routes, mask) ); - return NO_ERROR; - } break; - case GET_ROUTING: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - int mode = data.readInt32(); - reply->writeInt32( getRouting(mode) ); - return NO_ERROR; - } break; - case SET_MODE: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - int mode = data.readInt32(); - reply->writeInt32( setMode(mode) ); - return NO_ERROR; - } break; - case GET_MODE: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - reply->writeInt32( getMode() ); - return NO_ERROR; - } break; - case SET_MIC_MUTE: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - int state = data.readInt32(); - reply->writeInt32( setMicMute(state) ); - return NO_ERROR; - } break; - case GET_MIC_MUTE: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - reply->writeInt32( getMicMute() ); - return NO_ERROR; - } break; - case IS_MUSIC_ACTIVE: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - reply->writeInt32( isMusicActive() ); - return NO_ERROR; - } break; - case SET_PARAMETER: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - const char *key = data.readCString(); - const char *value = data.readCString(); - reply->writeInt32( setParameter(key, value) ); - return NO_ERROR; - } break; - case REGISTER_CLIENT: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - sp client = interface_cast(data.readStrongBinder()); - registerClient(client); - return NO_ERROR; - } break; - case GET_INPUTBUFFERSIZE: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - uint32_t sampleRate = data.readInt32(); - int format = data.readInt32(); - int channelCount = data.readInt32(); - reply->writeInt32( getInputBufferSize(sampleRate, format, channelCount) ); - return NO_ERROR; - } break; - case WAKE_UP: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - wakeUp(); - return NO_ERROR; - } break; - case IS_A2DP_ENABLED: { - CHECK_INTERFACE(IAudioFlinger, data, reply); - reply->writeInt32( (int)isA2dpEnabled() ); - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -// ---------------------------------------------------------------------------- - -}; // namespace android diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp deleted file mode 100644 index 5feb11f..0000000 --- a/media/libmedia/IAudioFlingerClient.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2009 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_TAG "IAudioFlingerClient" -#include - -#include -#include - -#include - -#include - -namespace android { - -enum { - AUDIO_OUTPUT_CHANGED = IBinder::FIRST_CALL_TRANSACTION -}; - -class BpAudioFlingerClient : public BpInterface -{ -public: - BpAudioFlingerClient(const sp& impl) - : BpInterface(impl) - { - } - - void a2dpEnabledChanged(bool enabled) - { - Parcel data, reply; - data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor()); - data.writeInt32((int)enabled); - remote()->transact(AUDIO_OUTPUT_CHANGED, data, &reply); - } -}; - -IMPLEMENT_META_INTERFACE(AudioFlingerClient, "android.media.IAudioFlingerClient"); - -// ---------------------------------------------------------------------- - -#define CHECK_INTERFACE(interface, data, reply) \ - do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ - LOGW("Call incorrectly routed to " #interface); \ - return PERMISSION_DENIED; \ - } } while (0) - -status_t BnAudioFlingerClient::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case AUDIO_OUTPUT_CHANGED: { - CHECK_INTERFACE(IAudioFlingerClient, data, reply); - bool enabled = (bool)data.readInt32(); - a2dpEnabledChanged(enabled); - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -// ---------------------------------------------------------------------------- - -}; // namespace android diff --git a/media/libmedia/IAudioRecord.cpp b/media/libmedia/IAudioRecord.cpp deleted file mode 100644 index 6e42dac..0000000 --- a/media/libmedia/IAudioRecord.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* -** -** Copyright 2007, 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. -*/ - -#include -#include - -#include - -#include - -namespace android { - -enum { - GET_CBLK = IBinder::FIRST_CALL_TRANSACTION, - START, - STOP -}; - -class BpAudioRecord : public BpInterface -{ -public: - BpAudioRecord(const sp& impl) - : BpInterface(impl) - { - } - - virtual status_t start() - { - Parcel data, reply; - data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor()); - remote()->transact(START, data, &reply); - return reply.readInt32(); - } - - virtual void stop() - { - Parcel data, reply; - data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor()); - remote()->transact(STOP, data, &reply); - } - - virtual sp getCblk() const - { - Parcel data, reply; - data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor()); - remote()->transact(GET_CBLK, data, &reply); - return interface_cast(reply.readStrongBinder()); - } -}; - -IMPLEMENT_META_INTERFACE(AudioRecord, "android.media.IAudioRecord"); - -// ---------------------------------------------------------------------- - -#define CHECK_INTERFACE(interface, data, reply) \ - do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ - LOGW("Call incorrectly routed to " #interface); \ - return PERMISSION_DENIED; \ - } } while (0) - -status_t BnAudioRecord::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case GET_CBLK: { - CHECK_INTERFACE(IAudioRecord, data, reply); - reply->writeStrongBinder(getCblk()->asBinder()); - return NO_ERROR; - } break; - case START: { - CHECK_INTERFACE(IAudioRecord, data, reply); - reply->writeInt32(start()); - return NO_ERROR; - } break; - case STOP: { - CHECK_INTERFACE(IAudioRecord, data, reply); - stop(); - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -}; // namespace android - diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp deleted file mode 100644 index abc202d..0000000 --- a/media/libmedia/IAudioTrack.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* //device/extlibs/pv/android/IAudioTrack.cpp -** -** Copyright 2007, 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. -*/ - -#include -#include - -#include - -#include - -namespace android { - -enum { - GET_CBLK = IBinder::FIRST_CALL_TRANSACTION, - START, - STOP, - FLUSH, - MUTE, - PAUSE -}; - -class BpAudioTrack : public BpInterface -{ -public: - BpAudioTrack(const sp& impl) - : BpInterface(impl) - { - } - - virtual status_t start() - { - Parcel data, reply; - data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); - remote()->transact(START, data, &reply); - return reply.readInt32(); - } - - virtual void stop() - { - Parcel data, reply; - data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); - remote()->transact(STOP, data, &reply); - } - - virtual void flush() - { - Parcel data, reply; - data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); - remote()->transact(FLUSH, data, &reply); - } - - virtual void mute(bool e) - { - Parcel data, reply; - data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); - data.writeInt32(e); - remote()->transact(MUTE, data, &reply); - } - - virtual void pause() - { - Parcel data, reply; - data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); - remote()->transact(PAUSE, data, &reply); - } - - virtual sp getCblk() const - { - Parcel data, reply; - data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); - remote()->transact(GET_CBLK, data, &reply); - return interface_cast(reply.readStrongBinder()); - } -}; - -IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack"); - -// ---------------------------------------------------------------------- - -#define CHECK_INTERFACE(interface, data, reply) \ - do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ - LOGW("Call incorrectly routed to " #interface); \ - return PERMISSION_DENIED; \ - } } while (0) - -status_t BnAudioTrack::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case GET_CBLK: { - CHECK_INTERFACE(IAudioTrack, data, reply); - reply->writeStrongBinder(getCblk()->asBinder()); - return NO_ERROR; - } break; - case START: { - CHECK_INTERFACE(IAudioTrack, data, reply); - reply->writeInt32(start()); - return NO_ERROR; - } break; - case STOP: { - CHECK_INTERFACE(IAudioTrack, data, reply); - stop(); - return NO_ERROR; - } break; - case FLUSH: { - CHECK_INTERFACE(IAudioTrack, data, reply); - flush(); - return NO_ERROR; - } break; - case MUTE: { - CHECK_INTERFACE(IAudioTrack, data, reply); - mute( data.readInt32() ); - return NO_ERROR; - } break; - case PAUSE: { - CHECK_INTERFACE(IAudioTrack, data, reply); - pause(); - return NO_ERROR; - } - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -}; // namespace android - diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp deleted file mode 100644 index 85b5944..0000000 --- a/media/libmedia/IMediaMetadataRetriever.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* -** -** 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. -*/ - -#include -#include -#include -#include -#include - -namespace android { - -enum { - DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, - SET_DATA_SOURCE_URL, - SET_DATA_SOURCE_FD, - SET_MODE, - GET_MODE, - CAPTURE_FRAME, - EXTARCT_ALBUM_ART, - EXTRACT_METADATA, -}; - -class BpMediaMetadataRetriever: public BpInterface -{ -public: - BpMediaMetadataRetriever(const sp& impl) - : BpInterface(impl) - { - } - - // disconnect from media metadata retriever service - void disconnect() - { - Parcel data, reply; - data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); - remote()->transact(DISCONNECT, data, &reply); - } - - status_t setDataSource(const char* srcUrl) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); - data.writeCString(srcUrl); - remote()->transact(SET_DATA_SOURCE_URL, data, &reply); - return reply.readInt32(); - } - - status_t setDataSource(int fd, int64_t offset, int64_t length) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); - data.writeFileDescriptor(fd); - data.writeInt64(offset); - data.writeInt64(length); - remote()->transact(SET_DATA_SOURCE_FD, data, &reply); - return reply.readInt32(); - } - - status_t setMode(int mode) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); - data.writeInt32(mode); - remote()->transact(SET_MODE, data, &reply); - return reply.readInt32(); - } - - status_t getMode(int* mode) const - { - Parcel data, reply; - data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); - remote()->transact(GET_MODE, data, &reply); - *mode = reply.readInt32(); - return reply.readInt32(); - } - - sp captureFrame() - { - Parcel data, reply; - data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); - remote()->transact(CAPTURE_FRAME, data, &reply); - status_t ret = reply.readInt32(); - if (ret != NO_ERROR) { - return NULL; - } - return interface_cast(reply.readStrongBinder()); - } - - sp extractAlbumArt() - { - Parcel data, reply; - data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); - remote()->transact(EXTARCT_ALBUM_ART, data, &reply); - status_t ret = reply.readInt32(); - if (ret != NO_ERROR) { - return NULL; - } - return interface_cast(reply.readStrongBinder()); - } - - const char* extractMetadata(int keyCode) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); - data.writeInt32(keyCode); - remote()->transact(EXTRACT_METADATA, data, &reply); - status_t ret = reply.readInt32(); - if (ret != NO_ERROR) { - return NULL; - } - return reply.readCString(); - } -}; - -IMPLEMENT_META_INTERFACE(MediaMetadataRetriever, "android.hardware.IMediaMetadataRetriever"); - -// ---------------------------------------------------------------------- - -#define CHECK_INTERFACE(interface, data, reply) \ - do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ - LOGW("Call incorrectly routed to " #interface); \ - return PERMISSION_DENIED; \ - } } while (0) - -status_t BnMediaMetadataRetriever::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch (code) { - case DISCONNECT: { - CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); - disconnect(); - return NO_ERROR; - } break; - case SET_DATA_SOURCE_URL: { - CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); - const char* srcUrl = data.readCString(); - reply->writeInt32(setDataSource(srcUrl)); - return NO_ERROR; - } break; - case SET_DATA_SOURCE_FD: { - CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); - int fd = dup(data.readFileDescriptor()); - int64_t offset = data.readInt64(); - int64_t length = data.readInt64(); - reply->writeInt32(setDataSource(fd, offset, length)); - return NO_ERROR; - } break; - case SET_MODE: { - CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); - int mode = data.readInt32(); - reply->writeInt32(setMode(mode)); - return NO_ERROR; - } break; - case GET_MODE: { - CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); - int mode; - status_t status = getMode(&mode); - reply->writeInt32(mode); - reply->writeInt32(status); - return NO_ERROR; - } break; - case CAPTURE_FRAME: { - CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); - sp bitmap = captureFrame(); - if (bitmap != 0) { // Don't send NULL across the binder interface - reply->writeInt32(NO_ERROR); - reply->writeStrongBinder(bitmap->asBinder()); - } else { - reply->writeInt32(UNKNOWN_ERROR); - } - return NO_ERROR; - } break; - case EXTARCT_ALBUM_ART: { - CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); - sp albumArt = extractAlbumArt(); - if (albumArt != 0) { // Don't send NULL across the binder interface - reply->writeInt32(NO_ERROR); - reply->writeStrongBinder(albumArt->asBinder()); - } else { - reply->writeInt32(UNKNOWN_ERROR); - } - return NO_ERROR; - } break; - case EXTRACT_METADATA: { - CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); - int keyCode = data.readInt32(); - const char* value = extractMetadata(keyCode); - if (value != NULL) { // Don't send NULL across the binder interface - reply->writeInt32(NO_ERROR); - reply->writeCString(value); - } else { - reply->writeInt32(UNKNOWN_ERROR); - } - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -// ---------------------------------------------------------------------------- - -}; // namespace android - diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp deleted file mode 100644 index f37519f..0000000 --- a/media/libmedia/IMediaPlayer.cpp +++ /dev/null @@ -1,275 +0,0 @@ -/* -** -** Copyright 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. -*/ - -#include -#include - -#include - -#include -#include - -namespace android { - -enum { - DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, - SET_VIDEO_SURFACE, - PREPARE_ASYNC, - START, - STOP, - IS_PLAYING, - PAUSE, - SEEK_TO, - GET_CURRENT_POSITION, - GET_DURATION, - RESET, - SET_AUDIO_STREAM_TYPE, - SET_LOOPING, - SET_VOLUME -}; - -class BpMediaPlayer: public BpInterface -{ -public: - BpMediaPlayer(const sp& impl) - : BpInterface(impl) - { - } - - // disconnect from media player service - void disconnect() - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); - remote()->transact(DISCONNECT, data, &reply); - } - - status_t setVideoSurface(const sp& surface) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); - data.writeStrongBinder(surface->asBinder()); - remote()->transact(SET_VIDEO_SURFACE, data, &reply); - return reply.readInt32(); - } - - status_t prepareAsync() - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); - remote()->transact(PREPARE_ASYNC, data, &reply); - return reply.readInt32(); - } - - status_t start() - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); - remote()->transact(START, data, &reply); - return reply.readInt32(); - } - - status_t stop() - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); - remote()->transact(STOP, data, &reply); - return reply.readInt32(); - } - - status_t isPlaying(bool* state) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); - remote()->transact(IS_PLAYING, data, &reply); - *state = reply.readInt32(); - return reply.readInt32(); - } - - status_t pause() - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); - remote()->transact(PAUSE, data, &reply); - return reply.readInt32(); - } - - status_t seekTo(int msec) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); - data.writeInt32(msec); - remote()->transact(SEEK_TO, data, &reply); - return reply.readInt32(); - } - - status_t getCurrentPosition(int* msec) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); - remote()->transact(GET_CURRENT_POSITION, data, &reply); - *msec = reply.readInt32(); - return reply.readInt32(); - } - - status_t getDuration(int* msec) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); - remote()->transact(GET_DURATION, data, &reply); - *msec = reply.readInt32(); - return reply.readInt32(); - } - - status_t reset() - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); - remote()->transact(RESET, data, &reply); - return reply.readInt32(); - } - - status_t setAudioStreamType(int type) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); - data.writeInt32(type); - remote()->transact(SET_AUDIO_STREAM_TYPE, data, &reply); - return reply.readInt32(); - } - - status_t setLooping(int loop) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); - data.writeInt32(loop); - remote()->transact(SET_LOOPING, data, &reply); - return reply.readInt32(); - } - - status_t setVolume(float leftVolume, float rightVolume) - { - Parcel data, reply; - data.writeFloat(leftVolume); - data.writeFloat(rightVolume); - remote()->transact(SET_VOLUME, data, &reply); - return reply.readInt32(); - } -}; - -IMPLEMENT_META_INTERFACE(MediaPlayer, "android.hardware.IMediaPlayer"); - -// ---------------------------------------------------------------------- - -#define CHECK_INTERFACE(interface, data, reply) \ - do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ - LOGW("Call incorrectly routed to " #interface); \ - return PERMISSION_DENIED; \ - } } while (0) - -status_t BnMediaPlayer::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case DISCONNECT: { - CHECK_INTERFACE(IMediaPlayer, data, reply); - disconnect(); - return NO_ERROR; - } break; - case SET_VIDEO_SURFACE: { - CHECK_INTERFACE(IMediaPlayer, data, reply); - sp surface = interface_cast(data.readStrongBinder()); - reply->writeInt32(setVideoSurface(surface)); - return NO_ERROR; - } break; - case PREPARE_ASYNC: { - CHECK_INTERFACE(IMediaPlayer, data, reply); - reply->writeInt32(prepareAsync()); - return NO_ERROR; - } break; - case START: { - CHECK_INTERFACE(IMediaPlayer, data, reply); - reply->writeInt32(start()); - return NO_ERROR; - } break; - case STOP: { - CHECK_INTERFACE(IMediaPlayer, data, reply); - reply->writeInt32(stop()); - return NO_ERROR; - } break; - case IS_PLAYING: { - CHECK_INTERFACE(IMediaPlayer, data, reply); - bool state; - status_t ret = isPlaying(&state); - reply->writeInt32(state); - reply->writeInt32(ret); - return NO_ERROR; - } break; - case PAUSE: { - CHECK_INTERFACE(IMediaPlayer, data, reply); - reply->writeInt32(pause()); - return NO_ERROR; - } break; - case SEEK_TO: { - CHECK_INTERFACE(IMediaPlayer, data, reply); - reply->writeInt32(seekTo(data.readInt32())); - return NO_ERROR; - } break; - case GET_CURRENT_POSITION: { - CHECK_INTERFACE(IMediaPlayer, data, reply); - int msec; - status_t ret = getCurrentPosition(&msec); - reply->writeInt32(msec); - reply->writeInt32(ret); - return NO_ERROR; - } break; - case GET_DURATION: { - CHECK_INTERFACE(IMediaPlayer, data, reply); - int msec; - status_t ret = getDuration(&msec); - reply->writeInt32(msec); - reply->writeInt32(ret); - return NO_ERROR; - } break; - case RESET: { - CHECK_INTERFACE(IMediaPlayer, data, reply); - reply->writeInt32(reset()); - return NO_ERROR; - } break; - case SET_AUDIO_STREAM_TYPE: { - CHECK_INTERFACE(IMediaPlayer, data, reply); - reply->writeInt32(setAudioStreamType(data.readInt32())); - return NO_ERROR; - } break; - case SET_LOOPING: { - CHECK_INTERFACE(IMediaPlayer, data, reply); - reply->writeInt32(setLooping(data.readInt32())); - return NO_ERROR; - } break; - case SET_VOLUME: { - reply->writeInt32(setVolume(data.readFloat(), data.readFloat())); - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -// ---------------------------------------------------------------------------- - -}; // namespace android - diff --git a/media/libmedia/IMediaPlayerClient.cpp b/media/libmedia/IMediaPlayerClient.cpp deleted file mode 100644 index 65022cd..0000000 --- a/media/libmedia/IMediaPlayerClient.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* -** -** Copyright 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. -*/ - -#include -#include -#include - -#include - -namespace android { - -enum { - NOTIFY = IBinder::FIRST_CALL_TRANSACTION, -}; - -class BpMediaPlayerClient: public BpInterface -{ -public: - BpMediaPlayerClient(const sp& impl) - : BpInterface(impl) - { - } - - virtual void notify(int msg, int ext1, int ext2) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayerClient::getInterfaceDescriptor()); - data.writeInt32(msg); - data.writeInt32(ext1); - data.writeInt32(ext2); - remote()->transact(NOTIFY, data, &reply, IBinder::FLAG_ONEWAY); - } -}; - -IMPLEMENT_META_INTERFACE(MediaPlayerClient, "android.hardware.IMediaPlayerClient"); - -// ---------------------------------------------------------------------- - -#define CHECK_INTERFACE(interface, data, reply) \ - do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ - LOGW("Call incorrectly routed to " #interface); \ - return PERMISSION_DENIED; \ - } } while (0) - -status_t BnMediaPlayerClient::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case NOTIFY: { - CHECK_INTERFACE(IMediaPlayerClient, data, reply); - int msg = data.readInt32(); - int ext1 = data.readInt32(); - int ext2 = data.readInt32(); - notify(msg, ext1, ext2); - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -}; // namespace android - diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp deleted file mode 100644 index 370e3fb..0000000 --- a/media/libmedia/IMediaPlayerService.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/* -** -** Copyright 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. -*/ - -#include -#include -#include - -#include -#include -#include - -namespace android { - -enum { - CREATE_URL = IBinder::FIRST_CALL_TRANSACTION, - CREATE_FD, - DECODE_URL, - DECODE_FD, - CREATE_MEDIA_RECORDER, - CREATE_METADATA_RETRIEVER, -}; - -class BpMediaPlayerService: public BpInterface -{ -public: - BpMediaPlayerService(const sp& impl) - : BpInterface(impl) - { - } - - virtual sp createMetadataRetriever(pid_t pid) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); - data.writeInt32(pid); - remote()->transact(CREATE_METADATA_RETRIEVER, data, &reply); - return interface_cast(reply.readStrongBinder()); - } - - virtual sp create(pid_t pid, const sp& client, const char* url) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); - data.writeInt32(pid); - data.writeStrongBinder(client->asBinder()); - data.writeCString(url); - remote()->transact(CREATE_URL, data, &reply); - return interface_cast(reply.readStrongBinder()); - } - - virtual sp createMediaRecorder(pid_t pid) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); - data.writeInt32(pid); - remote()->transact(CREATE_MEDIA_RECORDER, data, &reply); - return interface_cast(reply.readStrongBinder()); - } - - virtual sp create(pid_t pid, const sp& client, int fd, int64_t offset, int64_t length) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); - data.writeInt32(pid); - data.writeStrongBinder(client->asBinder()); - data.writeFileDescriptor(fd); - data.writeInt64(offset); - data.writeInt64(length); - remote()->transact(CREATE_FD, data, &reply); - return interface_cast(reply.readStrongBinder()); - } - - virtual sp decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); - data.writeCString(url); - remote()->transact(DECODE_URL, data, &reply); - *pSampleRate = uint32_t(reply.readInt32()); - *pNumChannels = reply.readInt32(); - *pFormat = reply.readInt32(); - return interface_cast(reply.readStrongBinder()); - } - - virtual sp decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) - { - Parcel data, reply; - data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); - data.writeFileDescriptor(fd); - data.writeInt64(offset); - data.writeInt64(length); - remote()->transact(DECODE_FD, data, &reply); - *pSampleRate = uint32_t(reply.readInt32()); - *pNumChannels = reply.readInt32(); - *pFormat = reply.readInt32(); - return interface_cast(reply.readStrongBinder()); - } -}; - -IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.hardware.IMediaPlayerService"); - -// ---------------------------------------------------------------------- - -#define CHECK_INTERFACE(interface, data, reply) \ - do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ - LOGW("Call incorrectly routed to " #interface); \ - return PERMISSION_DENIED; \ - } } while (0) - -status_t BnMediaPlayerService::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case CREATE_URL: { - CHECK_INTERFACE(IMediaPlayerService, data, reply); - pid_t pid = data.readInt32(); - sp client = interface_cast(data.readStrongBinder()); - const char* url = data.readCString(); - sp player = create(pid, client, url); - reply->writeStrongBinder(player->asBinder()); - return NO_ERROR; - } break; - case CREATE_FD: { - CHECK_INTERFACE(IMediaPlayerService, data, reply); - pid_t pid = data.readInt32(); - sp client = interface_cast(data.readStrongBinder()); - int fd = dup(data.readFileDescriptor()); - int64_t offset = data.readInt64(); - int64_t length = data.readInt64(); - sp player = create(pid, client, fd, offset, length); - reply->writeStrongBinder(player->asBinder()); - return NO_ERROR; - } break; - case DECODE_URL: { - CHECK_INTERFACE(IMediaPlayerService, data, reply); - const char* url = data.readCString(); - uint32_t sampleRate; - int numChannels; - int format; - sp player = decode(url, &sampleRate, &numChannels, &format); - reply->writeInt32(sampleRate); - reply->writeInt32(numChannels); - reply->writeInt32(format); - reply->writeStrongBinder(player->asBinder()); - return NO_ERROR; - } break; - case DECODE_FD: { - CHECK_INTERFACE(IMediaPlayerService, data, reply); - int fd = dup(data.readFileDescriptor()); - int64_t offset = data.readInt64(); - int64_t length = data.readInt64(); - uint32_t sampleRate; - int numChannels; - int format; - sp player = decode(fd, offset, length, &sampleRate, &numChannels, &format); - reply->writeInt32(sampleRate); - reply->writeInt32(numChannels); - reply->writeInt32(format); - reply->writeStrongBinder(player->asBinder()); - return NO_ERROR; - } break; - case CREATE_MEDIA_RECORDER: { - CHECK_INTERFACE(IMediaPlayerService, data, reply); - pid_t pid = data.readInt32(); - sp recorder = createMediaRecorder(pid); - reply->writeStrongBinder(recorder->asBinder()); - return NO_ERROR; - } break; - case CREATE_METADATA_RETRIEVER: { - CHECK_INTERFACE(IMediaPlayerService, data, reply); - pid_t pid = data.readInt32(); - sp retriever = createMetadataRetriever(pid); - reply->writeStrongBinder(retriever->asBinder()); - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -// ---------------------------------------------------------------------------- - -}; // namespace android - diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp deleted file mode 100644 index 507d03e..0000000 --- a/media/libmedia/IMediaRecorder.cpp +++ /dev/null @@ -1,397 +0,0 @@ -/* - ** - ** 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 "IMediaRecorder" -#include -#include -#include -#include -#include - -namespace android { - -enum { - RELEASE = IBinder::FIRST_CALL_TRANSACTION, - INIT, - CLOSE, - RESET, - STOP, - START, - PREPARE, - GET_MAX_AMPLITUDE, - SET_VIDEO_SOURCE, - SET_AUDIO_SOURCE, - SET_OUTPUT_FORMAT, - SET_VIDEO_ENCODER, - SET_AUDIO_ENCODER, - SET_OUTPUT_FILE_PATH, - SET_OUTPUT_FILE_FD, - SET_VIDEO_SIZE, - SET_VIDEO_FRAMERATE, - SET_PREVIEW_SURFACE, - SET_CAMERA -}; - -class BpMediaRecorder: public BpInterface -{ -public: - BpMediaRecorder(const sp& impl) - : BpInterface(impl) - { - } - - status_t setCamera(const sp& camera) - { - LOGV("setCamera(%p)", camera.get()); - Parcel data, reply; - data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - data.writeStrongBinder(camera->asBinder()); - remote()->transact(SET_CAMERA, data, &reply); - return reply.readInt32(); - } - - status_t setPreviewSurface(const sp& surface) - { - LOGV("setPreviewSurface(%p)", surface.get()); - Parcel data, reply; - data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - data.writeStrongBinder(surface->asBinder()); - remote()->transact(SET_PREVIEW_SURFACE, data, &reply); - return reply.readInt32(); - } - - status_t init() - { - LOGV("init"); - Parcel data, reply; - data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - remote()->transact(INIT, data, &reply); - return reply.readInt32(); - } - - status_t setVideoSource(int vs) - { - LOGV("setVideoSource(%d)", vs); - Parcel data, reply; - data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - data.writeInt32(vs); - remote()->transact(SET_VIDEO_SOURCE, data, &reply); - return reply.readInt32(); - } - - status_t setAudioSource(int as) - { - LOGV("setAudioSource(%d)", as); - Parcel data, reply; - data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - data.writeInt32(as); - remote()->transact(SET_AUDIO_SOURCE, data, &reply); - return reply.readInt32(); - } - - status_t setOutputFormat(int of) - { - LOGV("setOutputFormat(%d)", of); - Parcel data, reply; - data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - data.writeInt32(of); - remote()->transact(SET_OUTPUT_FORMAT, data, &reply); - return reply.readInt32(); - } - - status_t setVideoEncoder(int ve) - { - LOGV("setVideoEncoder(%d)", ve); - Parcel data, reply; - data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - data.writeInt32(ve); - remote()->transact(SET_VIDEO_ENCODER, data, &reply); - return reply.readInt32(); - } - - status_t setAudioEncoder(int ae) - { - LOGV("setAudioEncoder(%d)", ae); - Parcel data, reply; - data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - data.writeInt32(ae); - remote()->transact(SET_AUDIO_ENCODER, data, &reply); - return reply.readInt32(); - } - - status_t setOutputFile(const char* path) - { - LOGV("setOutputFile(%s)", path); - Parcel data, reply; - data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - data.writeCString(path); - remote()->transact(SET_OUTPUT_FILE_PATH, data, &reply); - return reply.readInt32(); - } - - status_t setOutputFile(int fd, int64_t offset, int64_t length) { - LOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length); - Parcel data, reply; - data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - data.writeFileDescriptor(fd); - data.writeInt64(offset); - data.writeInt64(length); - remote()->transact(SET_OUTPUT_FILE_FD, data, &reply); - return reply.readInt32(); - } - - status_t setVideoSize(int width, int height) - { - LOGV("setVideoSize(%dx%d)", width, height); - Parcel data, reply; - data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - data.writeInt32(width); - data.writeInt32(height); - remote()->transact(SET_VIDEO_SIZE, data, &reply); - return reply.readInt32(); - } - - status_t setVideoFrameRate(int frames_per_second) - { - LOGV("setVideoFrameRate(%d)", frames_per_second); - Parcel data, reply; - data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - data.writeInt32(frames_per_second); - remote()->transact(SET_VIDEO_FRAMERATE, data, &reply); - return reply.readInt32(); - } - - status_t prepare() - { - LOGV("prepare"); - Parcel data, reply; - data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - remote()->transact(PREPARE, data, &reply); - return reply.readInt32(); - } - - status_t getMaxAmplitude(int* max) - { - LOGV("getMaxAmplitude"); - Parcel data, reply; - data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - remote()->transact(GET_MAX_AMPLITUDE, data, &reply); - *max = reply.readInt32(); - return reply.readInt32(); - } - - status_t start() - { - LOGV("start"); - Parcel data, reply; - data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - remote()->transact(START, data, &reply); - return reply.readInt32(); - } - - status_t stop() - { - LOGV("stop"); - Parcel data, reply; - data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - remote()->transact(STOP, data, &reply); - return reply.readInt32(); - } - - status_t reset() - { - LOGV("reset"); - Parcel data, reply; - data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - remote()->transact(RESET, data, &reply); - return reply.readInt32(); - } - - status_t close() - { - LOGV("close"); - Parcel data, reply; - data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - remote()->transact(CLOSE, data, &reply); - return reply.readInt32(); - } - - status_t release() - { - LOGV("release"); - Parcel data, reply; - data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); - remote()->transact(RELEASE, data, &reply); - return reply.readInt32(); - } -}; - -IMPLEMENT_META_INTERFACE(MediaRecorder, "android.hardware.IMediaRecorder"); - -// ---------------------------------------------------------------------- - -#define CHECK_INTERFACE(interface, data, reply) \ - do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ - LOGW("Call incorrectly routed to " #interface); \ - return PERMISSION_DENIED; \ - } } while (0) - -status_t BnMediaRecorder::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case RELEASE: { - LOGV("RELEASE"); - CHECK_INTERFACE(IMediaRecorder, data, reply); - reply->writeInt32(release()); - return NO_ERROR; - } break; - case INIT: { - LOGV("INIT"); - CHECK_INTERFACE(IMediaRecorder, data, reply); - reply->writeInt32(init()); - return NO_ERROR; - } break; - case CLOSE: { - LOGV("CLOSE"); - CHECK_INTERFACE(IMediaRecorder, data, reply); - reply->writeInt32(close()); - return NO_ERROR; - } break; - case RESET: { - LOGV("RESET"); - CHECK_INTERFACE(IMediaRecorder, data, reply); - reply->writeInt32(reset()); - return NO_ERROR; - } break; - case STOP: { - LOGV("STOP"); - CHECK_INTERFACE(IMediaRecorder, data, reply); - reply->writeInt32(stop()); - return NO_ERROR; - } break; - case START: { - LOGV("START"); - CHECK_INTERFACE(IMediaRecorder, data, reply); - reply->writeInt32(start()); - return NO_ERROR; - } break; - case PREPARE: { - LOGV("PREPARE"); - CHECK_INTERFACE(IMediaRecorder, data, reply); - reply->writeInt32(prepare()); - return NO_ERROR; - } break; - case GET_MAX_AMPLITUDE: { - LOGV("GET_MAX_AMPLITUDE"); - CHECK_INTERFACE(IMediaRecorder, data, reply); - int max = 0; - status_t ret = getMaxAmplitude(&max); - reply->writeInt32(max); - reply->writeInt32(ret); - return NO_ERROR; - } break; - case SET_VIDEO_SOURCE: { - LOGV("SET_VIDEO_SOURCE"); - CHECK_INTERFACE(IMediaRecorder, data, reply); - int vs = data.readInt32(); - reply->writeInt32(setVideoSource(vs)); - return NO_ERROR; - } break; - case SET_AUDIO_SOURCE: { - LOGV("SET_AUDIO_SOURCE"); - CHECK_INTERFACE(IMediaRecorder, data, reply); - int as = data.readInt32(); - reply->writeInt32(setAudioSource(as)); - return NO_ERROR; - } break; - case SET_OUTPUT_FORMAT: { - LOGV("SET_OUTPUT_FORMAT"); - CHECK_INTERFACE(IMediaRecorder, data, reply); - int of = data.readInt32(); - reply->writeInt32(setOutputFormat(of)); - return NO_ERROR; - } break; - case SET_VIDEO_ENCODER: { - LOGV("SET_VIDEO_ENCODER"); - CHECK_INTERFACE(IMediaRecorder, data, reply); - int ve = data.readInt32(); - reply->writeInt32(setVideoEncoder(ve)); - return NO_ERROR; - } break; - case SET_AUDIO_ENCODER: { - LOGV("SET_AUDIO_ENCODER"); - CHECK_INTERFACE(IMediaRecorder, data, reply); - int ae = data.readInt32(); - reply->writeInt32(setAudioEncoder(ae)); - return NO_ERROR; - - } break; - case SET_OUTPUT_FILE_PATH: { - LOGV("SET_OUTPUT_FILE_PATH"); - CHECK_INTERFACE(IMediaRecorder, data, reply); - const char* path = data.readCString(); - reply->writeInt32(setOutputFile(path)); - return NO_ERROR; - } break; - case SET_OUTPUT_FILE_FD: { - LOGV("SET_OUTPUT_FILE_FD"); - CHECK_INTERFACE(IMediaRecorder, data, reply); - int fd = dup(data.readFileDescriptor()); - int64_t offset = data.readInt64(); - int64_t length = data.readInt64(); - reply->writeInt32(setOutputFile(fd, offset, length)); - return NO_ERROR; - } break; - case SET_VIDEO_SIZE: { - LOGV("SET_VIDEO_SIZE"); - CHECK_INTERFACE(IMediaRecorder, data, reply); - int width = data.readInt32(); - int height = data.readInt32(); - reply->writeInt32(setVideoSize(width, height)); - return NO_ERROR; - } break; - case SET_VIDEO_FRAMERATE: { - LOGV("SET_VIDEO_FRAMERATE"); - CHECK_INTERFACE(IMediaRecorder, data, reply); - int frames_per_second = data.readInt32(); - reply->writeInt32(setVideoFrameRate(frames_per_second)); - return NO_ERROR; - } break; - case SET_PREVIEW_SURFACE: { - LOGV("SET_PREVIEW_SURFACE"); - CHECK_INTERFACE(IMediaRecorder, data, reply); - sp surface = interface_cast(data.readStrongBinder()); - reply->writeInt32(setPreviewSurface(surface)); - return NO_ERROR; - } break; - case SET_CAMERA: { - LOGV("SET_CAMERA"); - CHECK_INTERFACE(IMediaRecorder, data, reply); - sp camera = interface_cast(data.readStrongBinder()); - reply->writeInt32(setCamera(camera)); - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - -// ---------------------------------------------------------------------------- - -}; // namespace android diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp deleted file mode 100644 index 2c62104..0000000 --- a/media/libmedia/JetPlayer.cpp +++ /dev/null @@ -1,489 +0,0 @@ -/* - * 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 "JetPlayer-C" - -#include -#include - -#include - - -#ifdef HAVE_GETTID -static pid_t myTid() { return gettid(); } -#else -static pid_t myTid() { return getpid(); } -#endif - - -namespace android -{ - -static const int MIX_NUM_BUFFERS = 4; -static const S_EAS_LIB_CONFIG* pLibConfig = NULL; - -//------------------------------------------------------------------------------------------------- -JetPlayer::JetPlayer(jobject javaJetPlayer, int maxTracks, int trackBufferSize) : - mEventCallback(NULL), - mJavaJetPlayerRef(javaJetPlayer), - mTid(-1), - mRender(false), - mPaused(false), - mMaxTracks(maxTracks), - mEasData(NULL), - mEasJetFileLoc(NULL), - mAudioTrack(NULL), - mTrackBufferSize(trackBufferSize) -{ - LOGV("JetPlayer constructor"); - mPreviousJetStatus.currentUserID = -1; - mPreviousJetStatus.segmentRepeatCount = -1; - mPreviousJetStatus.numQueuedSegments = -1; - mPreviousJetStatus.paused = true; -} - -//------------------------------------------------------------------------------------------------- -JetPlayer::~JetPlayer() -{ - LOGV("~JetPlayer"); - release(); - -} - -//------------------------------------------------------------------------------------------------- -int JetPlayer::init() -{ - //Mutex::Autolock lock(&mMutex); - - EAS_RESULT result; - - // retrieve the EAS library settings - if (pLibConfig == NULL) - pLibConfig = EAS_Config(); - if (pLibConfig == NULL) { - LOGE("JetPlayer::init(): EAS library configuration could not be retrieved, aborting."); - return EAS_FAILURE; - } - - // init the EAS library - result = EAS_Init(&mEasData); - if( result != EAS_SUCCESS) { - LOGE("JetPlayer::init(): Error initializing Sonivox EAS library, aborting."); - mState = EAS_STATE_ERROR; - return result; - } - // init the JET library with the default app event controller range - result = JET_Init(mEasData, NULL, sizeof(S_JET_CONFIG)); - if( result != EAS_SUCCESS) { - LOGE("JetPlayer::init(): Error initializing JET library, aborting."); - mState = EAS_STATE_ERROR; - return result; - } - - // create the output AudioTrack - mAudioTrack = new AudioTrack(); - mAudioTrack->set(AudioSystem::MUSIC, //TODO parametrize this - pLibConfig->sampleRate, - 1, // format = PCM 16bits per sample, - pLibConfig->numChannels, - mTrackBufferSize, - 0); - - // create render and playback thread - { - Mutex::Autolock l(mMutex); - LOGV("JetPlayer::init(): trying to start render thread"); - createThreadEtc(renderThread, this, "jetRenderThread", ANDROID_PRIORITY_AUDIO); - mCondition.wait(mMutex); - } - if (mTid > 0) { - // render thread started, we're ready - LOGV("JetPlayer::init(): render thread(%d) successfully started.", mTid); - mState = EAS_STATE_READY; - } else { - LOGE("JetPlayer::init(): failed to start render thread."); - mState = EAS_STATE_ERROR; - return EAS_FAILURE; - } - - return EAS_SUCCESS; -} - -void JetPlayer::setEventCallback(jetevent_callback eventCallback) -{ - Mutex::Autolock l(mMutex); - mEventCallback = eventCallback; -} - -//------------------------------------------------------------------------------------------------- -int JetPlayer::release() -{ - LOGV("JetPlayer::release()"); - Mutex::Autolock lock(mMutex); - mPaused = true; - mRender = false; - if (mEasData) { - JET_Pause(mEasData); - JET_CloseFile(mEasData); - JET_Shutdown(mEasData); - EAS_Shutdown(mEasData); - } - if (mEasJetFileLoc) { - free(mEasJetFileLoc); - mEasJetFileLoc = NULL; - } - if (mAudioTrack) { - mAudioTrack->stop(); - mAudioTrack->flush(); - delete mAudioTrack; - mAudioTrack = NULL; - } - if (mAudioBuffer) { - delete mAudioBuffer; - mAudioBuffer = NULL; - } - mEasData = NULL; - - return EAS_SUCCESS; -} - - -//------------------------------------------------------------------------------------------------- -int JetPlayer::renderThread(void* p) { - - return ((JetPlayer*)p)->render(); -} - -//------------------------------------------------------------------------------------------------- -int JetPlayer::render() { - EAS_RESULT result = EAS_FAILURE; - EAS_I32 count; - int temp; - bool audioStarted = false; - - LOGV("JetPlayer::render(): entering"); - - // allocate render buffer - mAudioBuffer = - new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * MIX_NUM_BUFFERS]; - if (!mAudioBuffer) { - LOGE("JetPlayer::render(): mAudioBuffer allocate failed"); - goto threadExit; - } - - // signal main thread that we started - { - Mutex::Autolock l(mMutex); - mTid = myTid(); - LOGV("JetPlayer::render(): render thread(%d) signal", mTid); - mCondition.signal(); - } - - while (1) { - mMutex.lock(); // [[[[[[[[ LOCK --------------------------------------- - - // nothing to render, wait for client thread to wake us up - while (!mRender) - { - LOGV("JetPlayer::render(): signal wait"); - if (audioStarted) { - mAudioTrack->pause(); - // we have to restart the playback once we start rendering again - audioStarted = false; - } - mCondition.wait(mMutex); - LOGV("JetPlayer::render(): signal rx'd"); - } - - // render midi data into the input buffer - int num_output = 0; - EAS_PCM* p = mAudioBuffer; - for (int i = 0; i < MIX_NUM_BUFFERS; i++) { - result = EAS_Render(mEasData, p, pLibConfig->mixBufferSize, &count); - if (result != EAS_SUCCESS) { - LOGE("JetPlayer::render(): EAS_Render returned error %ld", result); - } - p += count * pLibConfig->numChannels; - num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM); - - // send events that were generated (if any) to the event callback - fireEventsFromJetQueue(); - } - - // update playback state - //LOGV("JetPlayer::render(): updating state"); - JET_Status(mEasData, &mJetStatus); - fireUpdateOnStatusChange(); - mPaused = mJetStatus.paused; - - mMutex.unlock(); // UNLOCK ]]]]]]]] ----------------------------------- - - // check audio output track - if (mAudioTrack == NULL) { - LOGE("JetPlayer::render(): output AudioTrack was not created"); - goto threadExit; - } - - // Write data to the audio hardware - //LOGV("JetPlayer::render(): writing to audio output"); - if ((temp = mAudioTrack->write(mAudioBuffer, num_output)) < 0) { - LOGE("JetPlayer::render(): Error in writing:%d",temp); - return temp; - } - - // start audio output if necessary - if (!audioStarted) { - LOGV("JetPlayer::render(): starting audio playback"); - mAudioTrack->start(); - audioStarted = true; - } - - }//while (1) - -threadExit: - mAudioTrack->flush(); - if (mAudioBuffer) { - delete [] mAudioBuffer; - mAudioBuffer = NULL; - } - mMutex.lock(); - mTid = -1; - mCondition.signal(); - mMutex.unlock(); - return result; -} - - -//------------------------------------------------------------------------------------------------- -// fire up an update if any of the status fields has changed -// precondition: mMutex locked -void JetPlayer::fireUpdateOnStatusChange() -{ - if( (mJetStatus.currentUserID != mPreviousJetStatus.currentUserID) - ||(mJetStatus.segmentRepeatCount != mPreviousJetStatus.segmentRepeatCount) ) { - if(mEventCallback) { - mEventCallback( - JetPlayer::JET_USERID_UPDATE, - mJetStatus.currentUserID, - mJetStatus.segmentRepeatCount, - mJavaJetPlayerRef); - } - mPreviousJetStatus.currentUserID = mJetStatus.currentUserID; - mPreviousJetStatus.segmentRepeatCount = mJetStatus.segmentRepeatCount; - } - - if(mJetStatus.numQueuedSegments != mPreviousJetStatus.numQueuedSegments) { - if(mEventCallback) { - mEventCallback( - JetPlayer::JET_NUMQUEUEDSEGMENT_UPDATE, - mJetStatus.numQueuedSegments, - -1, - mJavaJetPlayerRef); - } - mPreviousJetStatus.numQueuedSegments = mJetStatus.numQueuedSegments; - } - - if(mJetStatus.paused != mPreviousJetStatus.paused) { - if(mEventCallback) { - mEventCallback(JetPlayer::JET_PAUSE_UPDATE, - mJetStatus.paused, - -1, - mJavaJetPlayerRef); - } - mPreviousJetStatus.paused = mJetStatus.paused; - } - -} - - -//------------------------------------------------------------------------------------------------- -// fire up all the JET events in the JET engine queue (until the queue is empty) -// precondition: mMutex locked -void JetPlayer::fireEventsFromJetQueue() -{ - if(!mEventCallback) { - // no callback, just empty the event queue - while (JET_GetEvent(mEasData, NULL, NULL)) { } - return; - } - - EAS_U32 rawEvent; - while (JET_GetEvent(mEasData, &rawEvent, NULL)) { - mEventCallback( - JetPlayer::JET_EVENT, - rawEvent, - -1, - mJavaJetPlayerRef); - } -} - - -//------------------------------------------------------------------------------------------------- -int JetPlayer::loadFromFile(const char* path) -{ - LOGV("JetPlayer::loadFromFile(): path=%s", path); - - Mutex::Autolock lock(mMutex); - - mEasJetFileLoc = (EAS_FILE_LOCATOR) malloc(sizeof(EAS_FILE)); - memset(mJetFilePath, 0, 256); - strncpy(mJetFilePath, path, strlen(path)); - mEasJetFileLoc->path = mJetFilePath; - - mEasJetFileLoc->fd = 0; - mEasJetFileLoc->length = 0; - mEasJetFileLoc->offset = 0; - - EAS_RESULT result = JET_OpenFile(mEasData, mEasJetFileLoc); - if(result != EAS_SUCCESS) - mState = EAS_STATE_ERROR; - else - mState = EAS_STATE_OPEN; - return( result ); -} - - -//------------------------------------------------------------------------------------------------- -int JetPlayer::loadFromFD(const int fd, const long long offset, const long long length) -{ - LOGV("JetPlayer::loadFromFD(): fd=%d offset=%lld length=%lld", fd, offset, length); - - Mutex::Autolock lock(mMutex); - - mEasJetFileLoc = (EAS_FILE_LOCATOR) malloc(sizeof(EAS_FILE)); - mEasJetFileLoc->fd = fd; - mEasJetFileLoc->offset = offset; - mEasJetFileLoc->length = length; - mEasJetFileLoc->path = NULL; - - EAS_RESULT result = JET_OpenFile(mEasData, mEasJetFileLoc); - if(result != EAS_SUCCESS) - mState = EAS_STATE_ERROR; - else - mState = EAS_STATE_OPEN; - return( result ); -} - - -//------------------------------------------------------------------------------------------------- -int JetPlayer::closeFile() -{ - Mutex::Autolock lock(mMutex); - return JET_CloseFile(mEasData); -} - - -//------------------------------------------------------------------------------------------------- -int JetPlayer::play() -{ - LOGV("JetPlayer::play(): entering"); - Mutex::Autolock lock(mMutex); - - EAS_RESULT result = JET_Play(mEasData); - - mPaused = false; - mRender = true; - - JET_Status(mEasData, &mJetStatus); - this->dumpJetStatus(&mJetStatus); - - fireUpdateOnStatusChange(); - - // wake up render thread - LOGV("JetPlayer::play(): wakeup render thread"); - mCondition.signal(); - - return result; -} - -//------------------------------------------------------------------------------------------------- -int JetPlayer::pause() -{ - Mutex::Autolock lock(mMutex); - mPaused = true; - EAS_RESULT result = JET_Pause(mEasData); - - mRender = false; - - JET_Status(mEasData, &mJetStatus); - this->dumpJetStatus(&mJetStatus); - fireUpdateOnStatusChange(); - - - return result; -} - - -//------------------------------------------------------------------------------------------------- -int JetPlayer::queueSegment(int segmentNum, int libNum, int repeatCount, int transpose, - EAS_U32 muteFlags, EAS_U8 userID) -{ - LOGV("JetPlayer::queueSegment segmentNum=%d, libNum=%d, repeatCount=%d, transpose=%d", - segmentNum, libNum, repeatCount, transpose); - Mutex::Autolock lock(mMutex); - return JET_QueueSegment(mEasData, segmentNum, libNum, repeatCount, transpose, muteFlags, userID); -} - -//------------------------------------------------------------------------------------------------- -int JetPlayer::setMuteFlags(EAS_U32 muteFlags, bool sync) -{ - Mutex::Autolock lock(mMutex); - return JET_SetMuteFlags(mEasData, muteFlags, sync); -} - -//------------------------------------------------------------------------------------------------- -int JetPlayer::setMuteFlag(int trackNum, bool muteFlag, bool sync) -{ - Mutex::Autolock lock(mMutex); - return JET_SetMuteFlag(mEasData, trackNum, muteFlag, sync); -} - -//------------------------------------------------------------------------------------------------- -int JetPlayer::triggerClip(int clipId) -{ - LOGV("JetPlayer::triggerClip clipId=%d", clipId); - Mutex::Autolock lock(mMutex); - return JET_TriggerClip(mEasData, clipId); -} - -//------------------------------------------------------------------------------------------------- -int JetPlayer::clearQueue() -{ - LOGV("JetPlayer::clearQueue"); - Mutex::Autolock lock(mMutex); - return JET_Clear_Queue(mEasData); -} - -//------------------------------------------------------------------------------------------------- -void JetPlayer::dump() -{ - LOGE("JetPlayer dump: JET file=%s", mEasJetFileLoc->path); -} - -void JetPlayer::dumpJetStatus(S_JET_STATUS* pJetStatus) -{ - if(pJetStatus!=NULL) - LOGV(">> current JET player status: userID=%d segmentRepeatCount=%d numQueuedSegments=%d paused=%d", - pJetStatus->currentUserID, pJetStatus->segmentRepeatCount, - pJetStatus->numQueuedSegments, pJetStatus->paused); - else - LOGE(">> JET player status is NULL"); -} - - -} // end namespace android - diff --git a/media/libmedia/MODULE_LICENSE_APACHE2 b/media/libmedia/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29..0000000 diff --git a/media/libmedia/NOTICE b/media/libmedia/NOTICE deleted file mode 100644 index c5b1efa..0000000 --- a/media/libmedia/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-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. - - 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. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp deleted file mode 100644 index 5416629..0000000 --- a/media/libmedia/ToneGenerator.cpp +++ /dev/null @@ -1,730 +0,0 @@ -/* - * 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 "ToneGenerator" -#include - -#include -#include -#include -#include -#include -#include -#include "media/ToneGenerator.h" - -namespace android { - -// Descriptors for all available tones (See ToneGenerator::ToneDescriptor class declaration for details) -const ToneGenerator::ToneDescriptor - ToneGenerator::toneDescriptors[NUM_TONES] = { - // waveFreq[] segments[] repeatCnt - { { 1336, 941, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_0 - { { 1209, 697, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_1 - { { 1336, 697, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_2 - { { 1477, 697, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_3 - { { 1209, 770, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_4 - { { 1336, 770, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_5 - { { 1477, 770, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_6 - { { 1209, 852, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_7 - { { 1336, 852, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_8 - { { 1477, 852, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_9 - { { 1209, 941, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_S - { { 1477, 941, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_P - { { 1633, 697, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_A - { { 1633, 770, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_B - { { 1633, 852, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_C - { { 1633, 941, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_D - { { 425, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_DIAL - { { 425, 0 }, { 500, 500, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_BUSY - { { 425, 0 }, { 200, 200, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_CONGESTION - { { 425, 0 }, { 200, 0 }, 0 }, // TONE_SUP_RADIO_ACK - { { 425, 0 }, { 200, 200, 0 }, 2 }, // TONE_SUP_RADIO_NOTAVAIL - { { 950, 1400, 1800, 0 }, { 330, 1000, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_ERROR - { { 425, 0 }, { 200, 600, 200, 3000, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_CALL_WAITING - { { 425, 0 }, { 1000, 4000, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_RINGTONE - { { 400, 1200, 0 }, { 40, 0 }, 0 }, // TONE_PROP_BEEP - { { 1200, 0 }, { 100, 100, 0 }, 1 }, // TONE_PROP_ACK - { { 300, 400, 500, 0 }, { 400, 0 }, 0 }, // TONE_PROP_NACK - { { 400, 1200, 0 }, { 200, 0 }, 0 }, // TONE_PROP_PROMPT - { { 400, 1200, 0 }, { 40, 200, 40, 0 }, 0 } // TONE_PROP_BEEP2 - }; - -//////////////////////////////////////////////////////////////////////////////// -// ToneGenerator class Implementation -//////////////////////////////////////////////////////////////////////////////// - - -//---------------------------------- public methods ---------------------------- - - -//////////////////////////////////////////////////////////////////////////////// -// -// Method: ToneGenerator::ToneGenerator() -// -// Description: Constructor. Initializes the tone sequencer, intantiates required sine wave -// generators, instantiates output audio track. -// -// Input: -// toneType: Type of tone generated (values in enum tone_type) -// streamType: Type of stream used for tone playback (enum AudioTrack::stream_type) -// volume: volume applied to tone (0.0 to 1.0) -// -// Output: -// none -// -//////////////////////////////////////////////////////////////////////////////// -ToneGenerator::ToneGenerator(int streamType, float volume) { - - LOGV("ToneGenerator constructor: streamType=%d, volume=%f\n", streamType, volume); - - mState = TONE_IDLE; - - if (AudioSystem::getOutputSamplingRate(&mSamplingRate, streamType) != NO_ERROR) { - LOGE("Unable to marshal AudioFlinger"); - return; - } - mStreamType = streamType; - mVolume = volume; - mpAudioTrack = 0; - mpToneDesc = 0; - mpNewToneDesc = 0; - // Generate tone by chunks of 20 ms to keep cadencing precision - mProcessSize = (mSamplingRate * 20) / 1000; - - if (initAudioTrack()) { - LOGV("ToneGenerator INIT OK, time: %d\n", (unsigned int)(systemTime()/1000000)); - } else { - LOGV("!!!ToneGenerator INIT FAILED!!!\n"); - } -} - - - - -//////////////////////////////////////////////////////////////////////////////// -// -// Method: ToneGenerator::~ToneGenerator() -// -// Description: Destructor. Stop sound playback and delete audio track if -// needed and delete sine wave generators. -// -// Input: -// none -// -// Output: -// none -// -//////////////////////////////////////////////////////////////////////////////// -ToneGenerator::~ToneGenerator() { - LOGV("ToneGenerator destructor\n"); - - if (mpAudioTrack) { - stopTone(); - LOGV("Delete Track: %p\n", mpAudioTrack); - delete mpAudioTrack; - } -} - -//////////////////////////////////////////////////////////////////////////////// -// -// Method: ToneGenerator::startTone() -// -// Description: Starts tone playback. -// -// Input: -// none -// -// Output: -// none -// -//////////////////////////////////////////////////////////////////////////////// -bool ToneGenerator::startTone(int toneType) { - bool lResult = false; - - if (toneType >= NUM_TONES) - return lResult; - - if (mState == TONE_IDLE) { - LOGV("startTone: try to re-init AudioTrack"); - if (!initAudioTrack()) { - return lResult; - } - } - - LOGV("startTone\n"); - - mLock.lock(); - - // Get descriptor for requested tone - mpNewToneDesc = &toneDescriptors[toneType]; - - if (mState == TONE_INIT) { - if (prepareWave()) { - LOGV("Immediate start, time %d\n", (unsigned int)(systemTime()/1000000)); - lResult = true; - mState = TONE_STARTING; - mLock.unlock(); - mpAudioTrack->start(); - mLock.lock(); - if (mState == TONE_STARTING) { - LOGV("Wait for start callback"); - if (mWaitCbkCond.waitRelative(mLock, seconds(1)) != NO_ERROR) { - LOGE("--- Immediate start timed out"); - mState = TONE_IDLE; - lResult = false; - } - } - } else { - mState == TONE_IDLE; - } - } else { - LOGV("Delayed start\n"); - - mState = TONE_RESTARTING; - if (mWaitCbkCond.waitRelative(mLock, seconds(1)) == NO_ERROR) { - if (mState != TONE_IDLE) { - lResult = true; - } - LOGV("cond received"); - } else { - LOGE("--- Delayed start timed out"); - mState = TONE_IDLE; - } - } - mLock.unlock(); - - LOGV_IF(lResult, "Tone started, time %d\n", (unsigned int)(systemTime()/1000000)); - LOGW_IF(!lResult, "Tone start failed!!!, time %d\n", (unsigned int)(systemTime()/1000000)); - - return lResult; -} - -//////////////////////////////////////////////////////////////////////////////// -// -// Method: ToneGenerator::stopTone() -// -// Description: Stops tone playback. -// -// Input: -// none -// -// Output: -// none -// -//////////////////////////////////////////////////////////////////////////////// -void ToneGenerator::stopTone() { - LOGV("stopTone"); - - mLock.lock(); - if (mState == TONE_PLAYING || mState == TONE_STARTING || mState == TONE_RESTARTING) { - mState = TONE_STOPPING; - LOGV("waiting cond"); - status_t lStatus = mWaitCbkCond.waitRelative(mLock, seconds(1)); - if (lStatus == NO_ERROR) { - LOGV("track stop complete, time %d", (unsigned int)(systemTime()/1000000)); - } else { - LOGE("--- Stop timed out"); - mState = TONE_IDLE; - mpAudioTrack->stop(); - } - } - - clearWaveGens(); - - mLock.unlock(); -} - -//---------------------------------- private methods --------------------------- - - - - -//////////////////////////////////////////////////////////////////////////////// -// -// Method: ToneGenerator::initAudioTrack() -// -// Description: Allocates and configures AudioTrack used for PCM output. -// -// Input: -// none -// -// Output: -// none -// -//////////////////////////////////////////////////////////////////////////////// -bool ToneGenerator::initAudioTrack() { - - if (mpAudioTrack) { - delete mpAudioTrack; - mpAudioTrack = 0; - } - - // Open audio track in mono, PCM 16bit, default sampling rate, default buffer size - mpAudioTrack - = new AudioTrack(mStreamType, 0, AudioSystem::PCM_16_BIT, 1, 0, 0, audioCallback, this, 0); - - if (mpAudioTrack == 0) { - LOGE("AudioTrack allocation failed"); - goto initAudioTrack_exit; - } - LOGV("Create Track: %p\n", mpAudioTrack); - - if (mpAudioTrack->initCheck() != NO_ERROR) { - LOGE("AudioTrack->initCheck failed"); - goto initAudioTrack_exit; - } - - mpAudioTrack->setVolume(mVolume, mVolume); - - mState = TONE_INIT; - - return true; - -initAudioTrack_exit: - - // Cleanup - if (mpAudioTrack) { - LOGV("Delete Track I: %p\n", mpAudioTrack); - delete mpAudioTrack; - mpAudioTrack = 0; - } - - return false; -} - - -//////////////////////////////////////////////////////////////////////////////// -// -// Method: ToneGenerator::audioCallback() -// -// Description: AudioTrack callback implementation. Generates a block of -// PCM samples -// and manages tone generator sequencer: tones pulses, tone duration... -// -// Input: -// user reference (pointer to our ToneGenerator) -// info audio buffer descriptor -// -// Output: -// returned value: always true. -// -//////////////////////////////////////////////////////////////////////////////// -void ToneGenerator::audioCallback(int event, void* user, void *info) { - - if (event != AudioTrack::EVENT_MORE_DATA) return; - - const AudioTrack::Buffer *buffer = static_cast(info); - ToneGenerator *lpToneGen = static_cast(user); - short *lpOut = buffer->i16; - unsigned int lNumSmp = buffer->size/sizeof(short); - - if (buffer->size == 0) return; - - - // Clear output buffer: WaveGenerator accumulates into lpOut buffer - memset(lpOut, 0, buffer->size); - - while (lNumSmp) { - unsigned int lReqSmp = lNumSmp < lpToneGen->mProcessSize*2 ? lNumSmp : lpToneGen->mProcessSize; - unsigned int lGenSmp; - unsigned int lWaveCmd = WaveGenerator::WAVEGEN_CONT; - bool lSignal = false; - - lpToneGen->mLock.lock(); - - // Update pcm frame count and end time (current time at the end of this process) - lpToneGen->mTotalSmp += lReqSmp; - - // Update tone gen state machine and select wave gen command - switch (lpToneGen->mState) { - case TONE_PLAYING: - lWaveCmd = WaveGenerator::WAVEGEN_CONT; - break; - case TONE_STARTING: - LOGV("Starting Cbk"); - - lWaveCmd = WaveGenerator::WAVEGEN_START; - break; - case TONE_STOPPING: - case TONE_RESTARTING: - LOGV("Stop/restart Cbk"); - - lWaveCmd = WaveGenerator::WAVEGEN_STOP; - lpToneGen->mNextSegSmp = TONEGEN_INF; // forced to skip state machine management below - break; - default: - LOGV("Extra Cbk"); - goto audioCallback_EndLoop; - } - - - // Exit if tone sequence is over - if (lpToneGen->mpToneDesc->segments[lpToneGen->mCurSegment] == 0) { - if (lpToneGen->mState == TONE_PLAYING) { - lpToneGen->mState = TONE_STOPPING; - } - goto audioCallback_EndLoop; - } - - if (lpToneGen->mTotalSmp > lpToneGen->mNextSegSmp) { - // Time to go to next sequence segment - - LOGV("End Segment, time: %d\n", (unsigned int)(systemTime()/1000000)); - - lGenSmp = lReqSmp; - - if (lpToneGen->mCurSegment & 0x0001) { - // If odd segment, OFF -> ON transition : reset wave generator - lWaveCmd = WaveGenerator::WAVEGEN_START; - - LOGV("OFF->ON, lGenSmp: %d, lReqSmp: %d\n", lGenSmp, lReqSmp); - } else { - // If even segment, ON -> OFF transition : ramp volume down - lWaveCmd = WaveGenerator::WAVEGEN_STOP; - - LOGV("ON->OFF, lGenSmp: %d, lReqSmp: %d\n", lGenSmp, lReqSmp); - } - - // Pre increment segment index and handle loop if last segment reached - if (lpToneGen->mpToneDesc->segments[++lpToneGen->mCurSegment] == 0) { - LOGV("Last Seg: %d\n", lpToneGen->mCurSegment); - - // Pre increment loop count and restart if total count not reached. Stop sequence otherwise - if (++lpToneGen->mCurCount <= lpToneGen->mpToneDesc->repeatCnt) { - LOGV("Repeating Count: %d\n", lpToneGen->mCurCount); - - lpToneGen->mCurSegment = 0; - - LOGV("New segment %d, Next Time: %d\n", lpToneGen->mCurSegment, - (lpToneGen->mNextSegSmp*1000)/lpToneGen->mSamplingRate); - - } else { - LOGV("End repeat, time: %d\n", (unsigned int)(systemTime()/1000000)); - - // Cancel OFF->ON transition in case previous segment tone state was OFF - if (!(lpToneGen->mCurSegment & 0x0001)) { - lGenSmp = 0; - } - } - } else { - LOGV("New segment %d, Next Time: %d\n", lpToneGen->mCurSegment, - (lpToneGen->mNextSegSmp*1000)/lpToneGen->mSamplingRate); - } - - // Update next segment transition position. No harm to do it also for last segment as lpToneGen->mNextSegSmp won't be used any more - lpToneGen->mNextSegSmp - += (lpToneGen->mpToneDesc->segments[lpToneGen->mCurSegment] * lpToneGen->mSamplingRate) / 1000; - - } else { - // Inside a segment keep tone ON or OFF - if (lpToneGen->mCurSegment & 0x0001) { - lGenSmp = 0; // If odd segment, tone is currently OFF - } else { - lGenSmp = lReqSmp; // If event segment, tone is currently ON - } - } - - if (lGenSmp) { - // If samples must be generated, call all active wave generators and acumulate waves in lpOut - unsigned int lWaveIdx; - - for (lWaveIdx = 0; lWaveIdx < (unsigned int)lpToneGen->mWaveGens.size(); lWaveIdx++) { - WaveGenerator *lpWaveGen = lpToneGen->mWaveGens[lWaveIdx]; - lpWaveGen->getSamples(lpOut, lGenSmp, lWaveCmd); - } - } - - lNumSmp -= lReqSmp; - lpOut += lReqSmp; - -audioCallback_EndLoop: - - switch (lpToneGen->mState) { - case TONE_RESTARTING: - LOGV("Cbk restarting track\n"); - if (lpToneGen->prepareWave()) { - lpToneGen->mState = TONE_STARTING; - } else { - LOGW("Cbk restarting prepareWave() failed\n"); - lpToneGen->mState = TONE_IDLE; - lpToneGen->mpAudioTrack->stop(); - // Force loop exit - lNumSmp = 0; - } - lSignal = true; - break; - case TONE_STOPPING: - lpToneGen->mState = TONE_INIT; - LOGV("Cbk Stopping track\n"); - lSignal = true; - lpToneGen->mpAudioTrack->stop(); - - // Force loop exit - lNumSmp = 0; - break; - case TONE_STARTING: - LOGV("Cbk starting track\n"); - lpToneGen->mState = TONE_PLAYING; - lSignal = true; - break; - default: - break; - } - - if (lSignal) - lpToneGen->mWaitCbkCond.signal(); - lpToneGen->mLock.unlock(); - } -} - - -//////////////////////////////////////////////////////////////////////////////// -// -// Method: ToneGenerator::prepareWave() -// -// Description: Prepare wave generators and reset tone sequencer state machine. -// mpNewToneDesc must have been initialized befoire calling this function. -// Input: -// none -// -// Output: -// returned value: true if wave generators have been created, false otherwise -// -//////////////////////////////////////////////////////////////////////////////// -bool ToneGenerator::prepareWave() { - unsigned int lCnt = 0; - unsigned int lNumWaves; - - if (!mpNewToneDesc) { - return false; - } - // Remove existing wave generators if any - clearWaveGens(); - - mpToneDesc = mpNewToneDesc; - - // Get total number of sine waves: needed to adapt sine wave gain. - lNumWaves = numWaves(); - - // Instantiate as many wave generators as listed in descriptor - while (lCnt < lNumWaves) { - ToneGenerator::WaveGenerator *lpWaveGen = - new ToneGenerator::WaveGenerator((unsigned short)mSamplingRate, - mpToneDesc->waveFreq[lCnt], - TONEGEN_GAIN/lNumWaves); - if (lpWaveGen == 0) { - goto prepareWave_exit; - } - - mWaveGens.push(lpWaveGen); - LOGV("Create sine: %d\n", mpToneDesc->waveFreq[lCnt]); - lCnt++; - } - - // Initialize tone sequencer - mTotalSmp = 0; - mCurSegment = 0; - mCurCount = 0; - mNextSegSmp = (mpToneDesc->segments[0] * mSamplingRate) / 1000; - - return true; - -prepareWave_exit: - - clearWaveGens(); - - return false; -} - - -//////////////////////////////////////////////////////////////////////////////// -// -// Method: ToneGenerator::numWaves() -// -// Description: Count number of sine waves needed to generate tone (e.g 2 for DTMF). -// -// Input: -// none -// -// Output: -// returned value: nummber of sine waves -// -//////////////////////////////////////////////////////////////////////////////// -unsigned int ToneGenerator::numWaves() { - unsigned int lCnt = 0; - - while (mpToneDesc->waveFreq[lCnt]) { - lCnt++; - } - - return lCnt; -} - - -//////////////////////////////////////////////////////////////////////////////// -// -// Method: ToneGenerator::clearWaveGens() -// -// Description: Removes all wave generators. -// -// Input: -// none -// -// Output: -// none -// -//////////////////////////////////////////////////////////////////////////////// -void ToneGenerator::clearWaveGens() { - LOGV("Clearing mWaveGens:"); - - while (!mWaveGens.isEmpty()) { - delete mWaveGens.top(); - mWaveGens.pop(); - } -} - - -//////////////////////////////////////////////////////////////////////////////// -// WaveGenerator::WaveGenerator class Implementation -//////////////////////////////////////////////////////////////////////////////// - -//---------------------------------- public methods ---------------------------- - -//////////////////////////////////////////////////////////////////////////////// -// -// Method: WaveGenerator::WaveGenerator() -// -// Description: Constructor. -// -// Input: -// samplingRate: Output sampling rate in Hz -// frequency: Frequency of the sine wave to generate in Hz -// volume: volume (0.0 to 1.0) -// -// Output: -// none -// -//////////////////////////////////////////////////////////////////////////////// -ToneGenerator::WaveGenerator::WaveGenerator(unsigned short samplingRate, - unsigned short frequency, float volume) { - double d0; - double F_div_Fs; // frequency / samplingRate - - F_div_Fs = frequency / (double)samplingRate; - d0 = - (float)GEN_AMP * sin(2 * M_PI * F_div_Fs); - mS2_0 = (short)d0; - mS1 = 0; - mS2 = mS2_0; - - mAmplitude_Q15 = (short)(32767. * 32767. * volume / GEN_AMP); - // take some margin for amplitude fluctuation - if (mAmplitude_Q15 > 32500) - mAmplitude_Q15 = 32500; - - d0 = 32768.0 * cos(2 * M_PI * F_div_Fs); // Q14*2*cos() - if (d0 > 32767) - d0 = 32767; - mA1_Q14 = (short) d0; - - LOGV("WaveGenerator init, mA1_Q14: %d, mS2_0: %d, mAmplitude_Q15: %d\n", - mA1_Q14, mS2_0, mAmplitude_Q15); -} - -//////////////////////////////////////////////////////////////////////////////// -// -// Method: WaveGenerator::~WaveGenerator() -// -// Description: Destructor. -// -// Input: -// none -// -// Output: -// none -// -//////////////////////////////////////////////////////////////////////////////// -ToneGenerator::WaveGenerator::~WaveGenerator() { -} - -//////////////////////////////////////////////////////////////////////////////// -// -// Method: WaveGenerator::getSamples() -// -// Description: Generates count samples of a sine wave and accumulates -// result in outBuffer. -// -// Input: -// outBuffer: Output buffer where to accumulate samples. -// count: number of samples to produce. -// command: special action requested (see enum gen_command). -// -// Output: -// none -// -//////////////////////////////////////////////////////////////////////////////// -void ToneGenerator::WaveGenerator::getSamples(short *outBuffer, - unsigned int count, unsigned int command) { - long lS1, lS2; - long lA1, lAmplitude; - long Sample; // current sample - - // init local - if (command == WAVEGEN_START) { - lS1 = (long)0; - lS2 = (long)mS2_0; - } else { - lS1 = (long)mS1; - lS2 = (long)mS2; - } - lA1 = (long)mA1_Q14; - lAmplitude = (long)mAmplitude_Q15; - - if (command == WAVEGEN_STOP) { - lAmplitude <<= 16; - if (count == 0) { - return; - } - long dec = lAmplitude/count; - // loop generation - while (count--) { - Sample = ((lA1 * lS1) >> S_Q14) - lS2; - // shift delay - lS2 = lS1; - lS1 = Sample; - Sample = ((lAmplitude>>16) * Sample) >> S_Q15; - *(outBuffer++) += (short)Sample; // put result in buffer - lAmplitude -= dec; - } - } else { - // loop generation - while (count--) { - Sample = ((lA1 * lS1) >> S_Q14) - lS2; - // shift delay - lS2 = lS1; - lS1 = Sample; - Sample = (lAmplitude * Sample) >> S_Q15; - *(outBuffer++) += (short)Sample; // put result in buffer - } - } - - // save status - mS1 = (short)lS1; - mS2 = (short)lS2; -} - -} // end namespace android - diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp deleted file mode 100644 index 09afc6c..0000000 --- a/media/libmedia/mediametadataretriever.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/* -** -** Copyright 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 "MediaMetadataRetriever" - -#include -#include -#include -#include -#include -#include - -namespace android { - -// client singleton for binder interface to service -Mutex MediaMetadataRetriever::sServiceLock; -sp MediaMetadataRetriever::sService; -sp MediaMetadataRetriever::sDeathNotifier; - -const sp& MediaMetadataRetriever::getService() -{ - Mutex::Autolock lock(sServiceLock); - if (sService.get() == 0) { - sp sm = defaultServiceManager(); - sp binder; - do { - binder = sm->getService(String16("media.player")); - if (binder != 0) { - break; - } - LOGW("MediaPlayerService not published, waiting..."); - usleep(500000); // 0.5 s - } while(true); - if (sDeathNotifier == NULL) { - sDeathNotifier = new DeathNotifier(); - } - binder->linkToDeath(sDeathNotifier); - sService = interface_cast(binder); - } - LOGE_IF(sService == 0, "no MediaPlayerService!?"); - return sService; -} - -MediaMetadataRetriever::MediaMetadataRetriever() -{ - LOGV("constructor"); - const sp& service(getService()); - if (service == 0) { - LOGE("failed to obtain MediaMetadataRetrieverService"); - return; - } - sp retriever(service->createMetadataRetriever(getpid())); - if (retriever == 0) { - LOGE("failed to create IMediaMetadataRetriever object from server"); - } - mRetriever = retriever; -} - -MediaMetadataRetriever::~MediaMetadataRetriever() -{ - LOGV("destructor"); - disconnect(); - IPCThreadState::self()->flushCommands(); -} - -void MediaMetadataRetriever::disconnect() -{ - LOGV("disconnect"); - sp retriever; - { - Mutex::Autolock _l(mLock); - retriever = mRetriever; - mRetriever.clear(); - } - if (retriever != 0) { - retriever->disconnect(); - } -} - -status_t MediaMetadataRetriever::setDataSource(const char* srcUrl) -{ - LOGV("setDataSource"); - if (mRetriever == 0) { - LOGE("retriever is not initialized"); - return INVALID_OPERATION; - } - if (srcUrl == NULL) { - LOGE("data source is a null pointer"); - return UNKNOWN_ERROR; - } - LOGV("data source (%s)", srcUrl); - return mRetriever->setDataSource(srcUrl); -} - -status_t MediaMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length) -{ - LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length); - if (mRetriever == 0) { - LOGE("retriever is not initialized"); - return INVALID_OPERATION; - } - if (fd < 0 || offset < 0 || length < 0) { - LOGE("Invalid negative argument"); - return UNKNOWN_ERROR; - } - return mRetriever->setDataSource(fd, offset, length); -} - -status_t MediaMetadataRetriever::setMode(int mode) -{ - LOGV("setMode(%d)", mode); - if (mRetriever == 0) { - LOGE("retriever is not initialized"); - return INVALID_OPERATION; - } - return mRetriever->setMode(mode); -} - -status_t MediaMetadataRetriever::getMode(int* mode) -{ - LOGV("getMode"); - if (mRetriever == 0) { - LOGE("retriever is not initialized"); - return INVALID_OPERATION; - } - return mRetriever->getMode(mode); -} - -sp MediaMetadataRetriever::captureFrame() -{ - LOGV("captureFrame"); - if (mRetriever == 0) { - LOGE("retriever is not initialized"); - return NULL; - } - return mRetriever->captureFrame(); -} - -const char* MediaMetadataRetriever::extractMetadata(int keyCode) -{ - LOGV("extractMetadata(%d)", keyCode); - if (mRetriever == 0) { - LOGE("retriever is not initialized"); - return NULL; - } - return mRetriever->extractMetadata(keyCode); -} - -sp MediaMetadataRetriever::extractAlbumArt() -{ - LOGV("extractAlbumArt"); - if (mRetriever == 0) { - LOGE("retriever is not initialized"); - return NULL; - } - return mRetriever->extractAlbumArt(); -} - -void MediaMetadataRetriever::DeathNotifier::binderDied(const wp& who) { - Mutex::Autolock lock(MediaMetadataRetriever::sServiceLock); - MediaMetadataRetriever::sService.clear(); - LOGW("MediaMetadataRetriever server died!"); -} - -MediaMetadataRetriever::DeathNotifier::~DeathNotifier() -{ - Mutex::Autolock lock(sServiceLock); - if (sService != 0) { - sService->asBinder()->unlinkToDeath(this); - } -} - -}; // namespace android diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp deleted file mode 100644 index bd8579c..0000000 --- a/media/libmedia/mediaplayer.cpp +++ /dev/null @@ -1,624 +0,0 @@ -/* mediaplayer.cpp -** -** Copyright 2006, 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 "MediaPlayer" -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include - -namespace android { - -// client singleton for binder interface to service -Mutex MediaPlayer::sServiceLock; -sp MediaPlayer::sMediaPlayerService; -sp MediaPlayer::sDeathNotifier; -SortedVector< wp > MediaPlayer::sObitRecipients; - -// establish binder interface to service -const sp& MediaPlayer::getMediaPlayerService() -{ - Mutex::Autolock _l(sServiceLock); - if (sMediaPlayerService.get() == 0) { - sp sm = defaultServiceManager(); - sp binder; - do { - binder = sm->getService(String16("media.player")); - if (binder != 0) - break; - LOGW("MediaPlayerService not published, waiting..."); - usleep(500000); // 0.5 s - } while(true); - if (sDeathNotifier == NULL) { - sDeathNotifier = new DeathNotifier(); - } - binder->linkToDeath(sDeathNotifier); - sMediaPlayerService = interface_cast(binder); - } - LOGE_IF(sMediaPlayerService==0, "no MediaPlayerService!?"); - return sMediaPlayerService; -} - -void MediaPlayer::addObitRecipient(const wp& recipient) -{ - Mutex::Autolock _l(sServiceLock); - sObitRecipients.add(recipient); -} - -void MediaPlayer::removeObitRecipient(const wp& recipient) -{ - Mutex::Autolock _l(sServiceLock); - sObitRecipients.remove(recipient); -} - -MediaPlayer::MediaPlayer() -{ - LOGV("constructor"); - mListener = NULL; - mCookie = NULL; - mDuration = -1; - mStreamType = AudioSystem::MUSIC; - mCurrentPosition = -1; - mSeekPosition = -1; - mCurrentState = MEDIA_PLAYER_IDLE; - mPrepareSync = false; - mPrepareStatus = NO_ERROR; - mLoop = false; - mLeftVolume = mRightVolume = 1.0; - mVideoWidth = mVideoHeight = 0; -} - -void MediaPlayer::onFirstRef() -{ - addObitRecipient(this); -} - -MediaPlayer::~MediaPlayer() -{ - LOGV("destructor"); - removeObitRecipient(this); - disconnect(); - IPCThreadState::self()->flushCommands(); -} - -void MediaPlayer::disconnect() -{ - LOGV("disconnect"); - sp p; - { - Mutex::Autolock _l(mLock); - p = mPlayer; - mPlayer.clear(); - } - - if (p != 0) { - p->disconnect(); - } -} - -// always call with lock held -void MediaPlayer::clear_l() -{ - mDuration = -1; - mCurrentPosition = -1; - mSeekPosition = -1; - mVideoWidth = mVideoHeight = 0; -} - -status_t MediaPlayer::setListener(const sp& listener) -{ - LOGV("setListener"); - Mutex::Autolock _l(mLock); - mListener = listener; - return NO_ERROR; -} - - -status_t MediaPlayer::setDataSource(const sp& player) -{ - status_t err = UNKNOWN_ERROR; - sp p; - { // scope for the lock - Mutex::Autolock _l(mLock); - - if ( !( mCurrentState & ( MEDIA_PLAYER_IDLE | MEDIA_PLAYER_STATE_ERROR ) ) ) { - LOGE("setDataSource called in state %d", mCurrentState); - return INVALID_OPERATION; - } - - clear_l(); - p = mPlayer; - mPlayer = player; - if (player != 0) { - mCurrentState = MEDIA_PLAYER_INITIALIZED; - err = NO_ERROR; - } else { - LOGE("Unable to to create media player"); - } - } - - if (p != 0) { - p->disconnect(); - } - - return err; -} - -status_t MediaPlayer::setDataSource(const char *url) -{ - LOGV("setDataSource(%s)", url); - status_t err = BAD_VALUE; - if (url != NULL) { - const sp& service(getMediaPlayerService()); - if (service != 0) { - sp player(service->create(getpid(), this, url)); - err = setDataSource(player); - } - } - return err; -} - -status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length) -{ - LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length); - status_t err = UNKNOWN_ERROR; - const sp& service(getMediaPlayerService()); - if (service != 0) { - sp player(service->create(getpid(), this, fd, offset, length)); - err = setDataSource(player); - } - return err; -} - -status_t MediaPlayer::setVideoSurface(const sp& surface) -{ - LOGV("setVideoSurface"); - Mutex::Autolock _l(mLock); - if (mPlayer == 0) return NO_INIT; - return mPlayer->setVideoSurface(surface->getISurface()); -} - -// must call with lock held -status_t MediaPlayer::prepareAsync_l() -{ - if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) { - mPlayer->setAudioStreamType(mStreamType); - mCurrentState = MEDIA_PLAYER_PREPARING; - return mPlayer->prepareAsync(); - } - LOGE("prepareAsync called in state %d", mCurrentState); - return INVALID_OPERATION; -} - -status_t MediaPlayer::prepare() -{ - LOGV("prepare"); - Mutex::Autolock _l(mLock); - if (mPrepareSync) return -EALREADY; - mPrepareSync = true; - status_t ret = prepareAsync_l(); - if (ret != NO_ERROR) return ret; - - if (mPrepareSync) { - mSignal.wait(mLock); // wait for prepare done - mPrepareSync = false; - } - LOGV("prepare complete - status=%d", mPrepareStatus); - return mPrepareStatus; -} - -status_t MediaPlayer::prepareAsync() -{ - LOGV("prepareAsync"); - Mutex::Autolock _l(mLock); - return prepareAsync_l(); -} - -status_t MediaPlayer::start() -{ - LOGV("start"); - Mutex::Autolock _l(mLock); - if (mCurrentState & MEDIA_PLAYER_STARTED) - return NO_ERROR; - if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED | - MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) { - mPlayer->setLooping(mLoop); - mPlayer->setVolume(mLeftVolume, mRightVolume); - mCurrentState = MEDIA_PLAYER_STARTED; - status_t ret = mPlayer->start(); - if (ret != NO_ERROR) { - mCurrentState = MEDIA_PLAYER_STATE_ERROR; - } else { - if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) { - LOGV("playback completed immediately following start()"); - } - } - return ret; - } - LOGE("start called in state %d", mCurrentState); - return INVALID_OPERATION; -} - -status_t MediaPlayer::stop() -{ - LOGV("stop"); - Mutex::Autolock _l(mLock); - if (mCurrentState & MEDIA_PLAYER_STOPPED) return NO_ERROR; - if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | - MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) ) { - status_t ret = mPlayer->stop(); - if (ret != NO_ERROR) { - mCurrentState = MEDIA_PLAYER_STATE_ERROR; - } else { - mCurrentState = MEDIA_PLAYER_STOPPED; - } - return ret; - } - LOGE("stop called in state %d", mCurrentState); - return INVALID_OPERATION; -} - -status_t MediaPlayer::pause() -{ - LOGV("pause"); - Mutex::Autolock _l(mLock); - if (mCurrentState & MEDIA_PLAYER_PAUSED) - return NO_ERROR; - if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER_STARTED)) { - status_t ret = mPlayer->pause(); - if (ret != NO_ERROR) { - mCurrentState = MEDIA_PLAYER_STATE_ERROR; - } else { - mCurrentState = MEDIA_PLAYER_PAUSED; - } - return ret; - } - LOGE("pause called in state %d", mCurrentState); - return INVALID_OPERATION; -} - -bool MediaPlayer::isPlaying() -{ - Mutex::Autolock _l(mLock); - if (mPlayer != 0) { - bool temp = false; - mPlayer->isPlaying(&temp); - LOGV("isPlaying: %d", temp); - if ((mCurrentState & MEDIA_PLAYER_STARTED) && ! temp) { - LOGE("internal/external state mismatch corrected"); - mCurrentState = MEDIA_PLAYER_PAUSED; - } - return temp; - } - LOGV("isPlaying: no active player"); - return false; -} - -status_t MediaPlayer::getVideoWidth(int *w) -{ - LOGV("getVideoWidth"); - Mutex::Autolock _l(mLock); - if (mPlayer == 0) return INVALID_OPERATION; - *w = mVideoWidth; - return NO_ERROR; -} - -status_t MediaPlayer::getVideoHeight(int *h) -{ - LOGV("getVideoHeight"); - Mutex::Autolock _l(mLock); - if (mPlayer == 0) return INVALID_OPERATION; - *h = mVideoHeight; - return NO_ERROR; -} - -status_t MediaPlayer::getCurrentPosition(int *msec) -{ - LOGV("getCurrentPosition"); - Mutex::Autolock _l(mLock); - if (mPlayer != 0) { - if (mCurrentPosition >= 0) { - LOGV("Using cached seek position: %d", mCurrentPosition); - *msec = mCurrentPosition; - return NO_ERROR; - } - return mPlayer->getCurrentPosition(msec); - } - return INVALID_OPERATION; -} - -status_t MediaPlayer::getDuration_l(int *msec) -{ - LOGV("getDuration"); - bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE)); - if (mPlayer != 0 && isValidState) { - status_t ret = NO_ERROR; - if (mDuration <= 0) - ret = mPlayer->getDuration(&mDuration); - if (msec) - *msec = mDuration; - return ret; - } - LOGE("Attempt to call getDuration without a valid mediaplayer"); - return INVALID_OPERATION; -} - -status_t MediaPlayer::getDuration(int *msec) -{ - Mutex::Autolock _l(mLock); - return getDuration_l(msec); -} - -status_t MediaPlayer::seekTo_l(int msec) -{ - LOGV("seekTo %d", msec); - if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) { - if ( msec < 0 ) { - LOGW("Attempt to seek to invalid position: %d", msec); - msec = 0; - } else if ((mDuration > 0) && (msec > mDuration)) { - LOGW("Attempt to seek to past end of file: request = %d, EOF = %d", msec, mDuration); - msec = mDuration; - } - // cache duration - mCurrentPosition = msec; - if (mSeekPosition < 0) { - getDuration_l(NULL); - mSeekPosition = msec; - return mPlayer->seekTo(msec); - } - else { - LOGV("Seek in progress - queue up seekTo[%d]", msec); - return NO_ERROR; - } - } - LOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(), mCurrentState); - return INVALID_OPERATION; -} - -status_t MediaPlayer::seekTo(int msec) -{ - Mutex::Autolock _l(mLock); - return seekTo_l(msec); -} - -status_t MediaPlayer::reset() -{ - LOGV("reset"); - Mutex::Autolock _l(mLock); - mLoop = false; - if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR; - mPrepareSync = false; - if (mPlayer != 0) { - status_t ret = mPlayer->reset(); - if (ret != NO_ERROR) { - LOGE("reset() failed with return code (%d)", ret); - mCurrentState = MEDIA_PLAYER_STATE_ERROR; - } else { - mCurrentState = MEDIA_PLAYER_IDLE; - } - return ret; - } - clear_l(); - return NO_ERROR; -} - -status_t MediaPlayer::setAudioStreamType(int type) -{ - LOGV("MediaPlayer::setAudioStreamType"); - Mutex::Autolock _l(mLock); - if (mStreamType == type) return NO_ERROR; - if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | - MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) { - // Can't change the stream type after prepare - LOGE("setAudioStream called in state %d", mCurrentState); - return INVALID_OPERATION; - } - // cache - mStreamType = type; - return OK; -} - -status_t MediaPlayer::setLooping(int loop) -{ - LOGV("MediaPlayer::setLooping"); - Mutex::Autolock _l(mLock); - mLoop = (loop != 0); - if (mPlayer != 0) { - return mPlayer->setLooping(loop); - } - return OK; -} - -bool MediaPlayer::isLooping() { - LOGV("isLooping"); - Mutex::Autolock _l(mLock); - if (mPlayer != 0) { - return mLoop; - } - LOGV("isLooping: no active player"); - return false; -} - -status_t MediaPlayer::setVolume(float leftVolume, float rightVolume) -{ - LOGV("MediaPlayer::setVolume(%f, %f)", leftVolume, rightVolume); - Mutex::Autolock _l(mLock); - mLeftVolume = leftVolume; - mRightVolume = rightVolume; - if (mPlayer != 0) { - return mPlayer->setVolume(leftVolume, rightVolume); - } - return OK; -} - -void MediaPlayer::notify(int msg, int ext1, int ext2) -{ - LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2); - bool send = true; - - // TODO: In the future, we might be on the same thread if the app is - // running in the same process as the media server. In that case, - // this will deadlock. - mLock.lock(); - if (mPlayer == 0) { - LOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2); - mLock.unlock(); // release the lock when done. - return; - } - - switch (msg) { - case MEDIA_NOP: // interface test message - break; - case MEDIA_PREPARED: - LOGV("prepared"); - mCurrentState = MEDIA_PLAYER_PREPARED; - if (mPrepareSync) { - LOGV("signal application thread"); - mPrepareSync = false; - mPrepareStatus = NO_ERROR; - mSignal.signal(); - } - break; - case MEDIA_PLAYBACK_COMPLETE: - LOGV("playback complete"); - if (!mLoop) { - mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE; - } - break; - case MEDIA_ERROR: - // Always log errors - LOGE("error (%d, %d)", ext1, ext2); - mCurrentState = MEDIA_PLAYER_STATE_ERROR; - if (mPrepareSync) - { - LOGV("signal application thread"); - mPrepareSync = false; - mPrepareStatus = ext1; - mSignal.signal(); - send = false; - } - break; - case MEDIA_SEEK_COMPLETE: - LOGV("Received seek complete"); - if (mSeekPosition != mCurrentPosition) { - LOGV("Executing queued seekTo(%d)", mSeekPosition); - mSeekPosition = -1; - seekTo_l(mCurrentPosition); - } - else { - LOGV("All seeks complete - return to regularly scheduled program"); - mCurrentPosition = mSeekPosition = -1; - } - break; - case MEDIA_BUFFERING_UPDATE: - LOGV("buffering %d", ext1); - break; - case MEDIA_SET_VIDEO_SIZE: - LOGV("New video size %d x %d", ext1, ext2); - mVideoWidth = ext1; - mVideoHeight = ext2; - break; - default: - LOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2); - break; - } - - sp listener = mListener; - mLock.unlock(); - - // this prevents re-entrant calls into client code - if ((listener != 0) && send) { - Mutex::Autolock _l(mNotifyLock); - LOGV("callback application"); - listener->notify(msg, ext1, ext2); - LOGV("back from callback"); - } -} - -void MediaPlayer::DeathNotifier::binderDied(const wp& who) { - LOGW("MediaPlayer server died!"); - - // Need to do this with the lock held - SortedVector< wp > list; - { - Mutex::Autolock _l(MediaPlayer::sServiceLock); - MediaPlayer::sMediaPlayerService.clear(); - list = sObitRecipients; - } - - // Notify application when media server dies. - // Don't hold the static lock during callback in case app - // makes a call that needs the lock. - size_t count = list.size(); - for (size_t iter = 0; iter < count; ++iter) { - sp player = list[iter].promote(); - if ((player != 0) && (player->mPlayer != 0)) { - player->notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0); - } - } -} - -MediaPlayer::DeathNotifier::~DeathNotifier() -{ - Mutex::Autolock _l(sServiceLock); - sObitRecipients.clear(); - if (sMediaPlayerService != 0) { - sMediaPlayerService->asBinder()->unlinkToDeath(this); - } -} - -/*static*/ sp MediaPlayer::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) -{ - LOGV("decode(%s)", url); - sp p; - const sp& service = getMediaPlayerService(); - if (service != 0) { - p = sMediaPlayerService->decode(url, pSampleRate, pNumChannels, pFormat); - } else { - LOGE("Unable to locate media service"); - } - return p; - -} - -/*static*/ sp MediaPlayer::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 p; - const sp& service = getMediaPlayerService(); - if (service != 0) { - p = sMediaPlayerService->decode(fd, offset, length, pSampleRate, pNumChannels, pFormat); - } else { - LOGE("Unable to locate media service"); - } - return p; - -} - -}; // namespace android diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp deleted file mode 100644 index 4ab26ac..0000000 --- a/media/libmedia/mediarecorder.cpp +++ /dev/null @@ -1,542 +0,0 @@ -/* - ** - ** 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 "MediaRecorder" -#include -#include -#include -#include -#include -#include - -namespace android { - -status_t MediaRecorder::setCamera(const sp& camera) -{ - LOGV("setCamera(%p)", camera.get()); - if(mMediaRecorder == NULL) { - LOGE("media recorder is not initialized yet"); - return INVALID_OPERATION; - } - if (!(mCurrentState & MEDIA_RECORDER_IDLE)) { - LOGE("setCamera called in an invalid state(%d)", mCurrentState); - return INVALID_OPERATION; - } - - status_t ret = mMediaRecorder->setCamera(camera); - if (OK != ret) { - LOGV("setCamera failed: %d", ret); - mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; - } - return ret; -} - -status_t MediaRecorder::setPreviewSurface(const sp& surface) -{ - LOGV("setPreviewSurface(%p)", surface.get()); - if(mMediaRecorder == NULL) { - LOGE("media recorder is not initialized yet"); - return INVALID_OPERATION; - } - if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { - LOGE("setPreviewSurface called in an invalid state(%d)", mCurrentState); - return INVALID_OPERATION; - } - - status_t ret = mMediaRecorder->setPreviewSurface(surface->getISurface()); - if (OK != ret) { - LOGV("setPreviewSurface failed: %d", ret); - mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; - } - return ret; -} - -status_t MediaRecorder::init() -{ - LOGV("init"); - if(mMediaRecorder == NULL) { - LOGE("media recorder is not initialized yet"); - return INVALID_OPERATION; - } - if (!(mCurrentState & MEDIA_RECORDER_IDLE)) { - LOGE("init called in an invalid state(%d)", mCurrentState); - return INVALID_OPERATION; - } - - status_t ret = mMediaRecorder->init(); - if (OK != ret) { - LOGV("init failed: %d", ret); - mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; - } - mCurrentState = MEDIA_RECORDER_INITIALIZED; - return ret; -} - -status_t MediaRecorder::setVideoSource(int vs) -{ - LOGV("setVideoSource(%d)", vs); - if(mMediaRecorder == NULL) { - LOGE("media recorder is not initialized yet"); - return INVALID_OPERATION; - } - if (mIsVideoSourceSet) { - LOGE("video source has already been set"); - return INVALID_OPERATION; - } - if (mCurrentState & MEDIA_RECORDER_IDLE) { - LOGV("Call init() since the media recorder is not initialized yet"); - status_t ret = init(); - if (OK != ret) { - return ret; - } - } - if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { - LOGE("setVideoSource called in an invalid state(%d)", mCurrentState); - return INVALID_OPERATION; - } - - status_t ret = mMediaRecorder->setVideoSource(vs); - if (OK != ret) { - LOGV("setVideoSource failed: %d", ret); - mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; - } - mIsVideoSourceSet = true; - return ret; -} - -status_t MediaRecorder::setAudioSource(int as) -{ - LOGV("setAudioSource(%d)", as); - if(mMediaRecorder == NULL) { - LOGE("media recorder is not initialized yet"); - return INVALID_OPERATION; - } - if (mCurrentState & MEDIA_RECORDER_IDLE) { - LOGV("Call init() since the media recorder is not initialized yet"); - status_t ret = init(); - if (OK != ret) { - return ret; - } - } - if (mIsAudioSourceSet) { - LOGE("audio source has already been set"); - return INVALID_OPERATION; - } - if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { - LOGE("setAudioSource called in an invalid state(%d)", mCurrentState); - return INVALID_OPERATION; - } - - status_t ret = mMediaRecorder->setAudioSource(as); - if (OK != ret) { - LOGV("setAudioSource failed: %d", ret); - mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; - } - mIsAudioSourceSet = true; - return ret; -} - -status_t MediaRecorder::setOutputFormat(int of) -{ - LOGV("setOutputFormat(%d)", of); - if(mMediaRecorder == NULL) { - LOGE("media recorder is not initialized yet"); - return INVALID_OPERATION; - } - if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { - LOGE("setOutputFormat called in an invalid state: %d", mCurrentState); - return INVALID_OPERATION; - } - - status_t ret = mMediaRecorder->setOutputFormat(of); - if (OK != ret) { - LOGE("setOutputFormat failed: %d", ret); - mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; - } - mCurrentState = MEDIA_RECORDER_DATASOURCE_CONFIGURED; - return ret; -} - -status_t MediaRecorder::setVideoEncoder(int ve) -{ - LOGV("setVideoEncoder(%d)", ve); - if(mMediaRecorder == NULL) { - LOGE("media recorder is not initialized yet"); - return INVALID_OPERATION; - } - if (mIsVideoEncoderSet) { - LOGE("video encoder has already been set"); - return INVALID_OPERATION; - } - if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { - LOGE("setVideoEncoder called in an invalid state(%d)", mCurrentState); - return INVALID_OPERATION; - } - - status_t ret = mMediaRecorder->setVideoEncoder(ve); - if (OK != ret) { - LOGV("setVideoEncoder failed: %d", ret); - mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; - } - mIsVideoEncoderSet = true; - return ret; -} - -status_t MediaRecorder::setAudioEncoder(int ae) -{ - LOGV("setAudioEncoder(%d)", ae); - if(mMediaRecorder == NULL) { - LOGE("media recorder is not initialized yet"); - return INVALID_OPERATION; - } - if (mIsAudioEncoderSet) { - LOGE("audio encoder has already been set"); - return INVALID_OPERATION; - } - if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { - LOGE("setAudioEncoder called in an invalid state(%d)", mCurrentState); - return INVALID_OPERATION; - } - - status_t ret = mMediaRecorder->setAudioEncoder(ae); - if (OK != ret) { - LOGV("setAudioEncoder failed: %d", ret); - mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; - } - mIsAudioEncoderSet = true; - return ret; -} - -status_t MediaRecorder::setOutputFile(const char* path) -{ - LOGV("setOutputFile(%s)", path); - if(mMediaRecorder == NULL) { - LOGE("media recorder is not initialized yet"); - return INVALID_OPERATION; - } - if (mIsOutputFileSet) { - LOGE("output file has already been set"); - return INVALID_OPERATION; - } - if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { - LOGE("setOutputFile called in an invalid state(%d)", mCurrentState); - return INVALID_OPERATION; - } - - status_t ret = mMediaRecorder->setOutputFile(path); - if (OK != ret) { - LOGV("setOutputFile failed: %d", ret); - mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; - } - mIsOutputFileSet = true; - return ret; -} - -status_t MediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length) -{ - LOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length); - if(mMediaRecorder == NULL) { - LOGE("media recorder is not initialized yet"); - return INVALID_OPERATION; - } - if (mIsOutputFileSet) { - LOGE("output file has already been set"); - return INVALID_OPERATION; - } - if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { - LOGE("setOutputFile called in an invalid state(%d)", mCurrentState); - return INVALID_OPERATION; - } - - status_t ret = mMediaRecorder->setOutputFile(fd, offset, length); - if (OK != ret) { - LOGV("setOutputFile failed: %d", ret); - mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; - } - mIsOutputFileSet = true; - return ret; -} - -status_t MediaRecorder::setVideoSize(int width, int height) -{ - LOGV("setVideoSize(%d, %d)", width, height); - if(mMediaRecorder == NULL) { - LOGE("media recorder is not initialized yet"); - return INVALID_OPERATION; - } - if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { - LOGE("setVideoSize called in an invalid state: %d", mCurrentState); - return INVALID_OPERATION; - } - - status_t ret = mMediaRecorder->setVideoSize(width, height); - if (OK != ret) { - LOGE("setVideoSize failed: %d", ret); - mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; - } - return ret; -} - -status_t MediaRecorder::setVideoFrameRate(int frames_per_second) -{ - LOGV("setVideoFrameRate(%d)", frames_per_second); - if(mMediaRecorder == NULL) { - LOGE("media recorder is not initialized yet"); - return INVALID_OPERATION; - } - if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { - LOGE("setVideoFrameRate called in an invalid state: %d", mCurrentState); - return INVALID_OPERATION; - } - - status_t ret = mMediaRecorder->setVideoFrameRate(frames_per_second); - if (OK != ret) { - LOGE("setVideoFrameRate failed: %d", ret); - mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; - } - return ret; -} - -status_t MediaRecorder::prepare() -{ - LOGV("prepare"); - if(mMediaRecorder == NULL) { - LOGE("media recorder is not initialized yet"); - return INVALID_OPERATION; - } - if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { - LOGE("prepare called in an invalid state: %d", mCurrentState); - return INVALID_OPERATION; - } - - status_t ret = mMediaRecorder->prepare(); - if (OK != ret) { - LOGE("prepare failed: %d", ret); - mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; - } - mCurrentState = MEDIA_RECORDER_PREPARED; - return ret; -} - -status_t MediaRecorder::getMaxAmplitude(int* max) -{ - LOGV("getMaxAmplitude"); - if(mMediaRecorder == NULL) { - LOGE("media recorder is not initialized yet"); - return INVALID_OPERATION; - } - if (mCurrentState & MEDIA_RECORDER_ERROR) { - LOGE("getMaxAmplitude called in an invalid state: %d", mCurrentState); - return INVALID_OPERATION; - } - - status_t ret = mMediaRecorder->getMaxAmplitude(max); - if (OK != ret) { - LOGE("getMaxAmplitude failed: %d", ret); - mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; - } - return ret; -} - -status_t MediaRecorder::start() -{ - LOGV("start"); - if (mMediaRecorder == NULL) { - LOGE("media recorder is not initialized yet"); - return INVALID_OPERATION; - } - if (!(mCurrentState & MEDIA_RECORDER_PREPARED)) { - LOGE("start called in an invalid state: %d", mCurrentState); - return INVALID_OPERATION; - } - - status_t ret = mMediaRecorder->start(); - if (OK != ret) { - LOGE("start failed: %d", ret); - mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; - } - mCurrentState = MEDIA_RECORDER_RECORDING; - return ret; -} - -status_t MediaRecorder::stop() -{ - LOGV("stop"); - if (mMediaRecorder == NULL) { - LOGE("media recorder is not initialized yet"); - return INVALID_OPERATION; - } - if (!(mCurrentState & MEDIA_RECORDER_RECORDING)) { - LOGE("stop called in an invalid state: %d", mCurrentState); - return INVALID_OPERATION; - } - - status_t ret = mMediaRecorder->stop(); - if (OK != ret) { - LOGE("stop failed: %d", ret); - mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; - } - mCurrentState = MEDIA_RECORDER_IDLE; - return ret; -} - -// Reset should be OK in any state -status_t MediaRecorder::reset() -{ - LOGV("reset"); - if (mMediaRecorder == NULL) { - LOGE("media recorder is not initialized yet"); - return INVALID_OPERATION; - } - - doCleanUp(); - status_t ret = UNKNOWN_ERROR; - switch(mCurrentState) { - case MEDIA_RECORDER_IDLE: - ret = OK; - break; - - case MEDIA_RECORDER_RECORDING: - case MEDIA_RECORDER_DATASOURCE_CONFIGURED: - case MEDIA_RECORDER_PREPARED: - case MEDIA_RECORDER_ERROR: { - ret = doReset(); - if (OK != ret) { - return ret; // No need to continue - } - } // Intentional fall through - case MEDIA_RECORDER_INITIALIZED: - ret = close(); - break; - - default: { - LOGE("Unexpected non-existing state: %d", mCurrentState); - break; - } - } - return ret; -} - -status_t MediaRecorder::close() -{ - LOGV("close"); - if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { - LOGE("close called in an invalid state: %d", mCurrentState); - return INVALID_OPERATION; - } - status_t ret = mMediaRecorder->close(); - if (OK != ret) { - LOGE("close failed: %d", ret); - mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; - } else { - mCurrentState = MEDIA_RECORDER_IDLE; - } - return ret; -} - -status_t MediaRecorder::doReset() -{ - LOGV("doReset"); - status_t ret = mMediaRecorder->reset(); - if (OK != ret) { - LOGE("doReset failed: %d", ret); - mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; - } else { - mCurrentState = MEDIA_RECORDER_INITIALIZED; - } - return ret; -} - -void MediaRecorder::doCleanUp() -{ - LOGV("doCleanUp"); - mIsAudioSourceSet = false; - mIsVideoSourceSet = false; - mIsAudioEncoderSet = false; - mIsVideoEncoderSet = false; - mIsOutputFileSet = false; -} - -// Release should be OK in any state -status_t MediaRecorder::release() -{ - LOGV("release"); - if (mMediaRecorder != NULL) { - return mMediaRecorder->release(); - } - return INVALID_OPERATION; -} - -MediaRecorder::MediaRecorder() -{ - LOGV("constructor"); - sp sm = defaultServiceManager(); - sp binder; - - do { - binder = sm->getService(String16("media.player")); - if (binder != NULL) { - break; - } - LOGW("MediaPlayerService not published, waiting..."); - usleep(500000); // 0.5 s - } while(true); - - sp service = interface_cast(binder); - if (service != NULL) { - mMediaRecorder = service->createMediaRecorder(getpid()); - } - if (mMediaRecorder != NULL) { - mCurrentState = MEDIA_RECORDER_IDLE; - } - doCleanUp(); -} - -status_t MediaRecorder::initCheck() -{ - return mMediaRecorder != 0 ? NO_ERROR : NO_INIT; -} - -MediaRecorder::~MediaRecorder() -{ - LOGV("destructor"); - if (mMediaRecorder != NULL) { - mMediaRecorder.clear(); - } -} - -}; // namespace android - diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk deleted file mode 100644 index f710921..0000000 --- a/media/libmediaplayerservice/Android.mk +++ /dev/null @@ -1,36 +0,0 @@ -LOCAL_PATH:= $(call my-dir) - -# -# libmediaplayerservice -# - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - MediaRecorderClient.cpp \ - MediaPlayerService.cpp \ - MetadataRetrieverClient.cpp \ - VorbisPlayer.cpp \ - MidiFile.cpp - -ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true) -LOCAL_LDLIBS += -ldl -lpthread -endif - -LOCAL_SHARED_LIBRARIES := \ - libcutils \ - libutils \ - libvorbisidec \ - libsonivox \ - libopencoreplayer \ - libopencoreauthor \ - libmedia \ - libandroid_runtime - -LOCAL_C_INCLUDES := external/tremor/Tremor \ - $(call include-path-for, graphics corecg) - -LOCAL_MODULE:= libmediaplayerservice - -include $(BUILD_SHARED_LIBRARY) - diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp deleted file mode 100644 index 97e3536..0000000 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ /dev/null @@ -1,1063 +0,0 @@ -/* -** -** Copyright 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. -*/ - -// Proxy for media player implementations - -//#define LOG_NDEBUG 0 -#define LOG_TAG "MediaPlayerService" -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "MediaRecorderClient.h" -#include "MediaPlayerService.h" -#include "MetadataRetrieverClient.h" - -#include "MidiFile.h" -#include "VorbisPlayer.h" -#include - -/* desktop Linux needs a little help with gettid() */ -#if defined(HAVE_GETTID) && !defined(HAVE_ANDROID_OS) -#define __KERNEL__ -# include -#ifdef _syscall0 -_syscall0(pid_t,gettid) -#else -pid_t gettid() { return syscall(__NR_gettid);} -#endif -#undef __KERNEL__ -#endif - - -namespace android { - -// TODO: Temp hack until we can register players -typedef struct { - const char *extension; - const player_type playertype; -} extmap; -extmap FILE_EXTS [] = { - {".mid", SONIVOX_PLAYER}, - {".midi", SONIVOX_PLAYER}, - {".smf", SONIVOX_PLAYER}, - {".xmf", SONIVOX_PLAYER}, - {".imy", SONIVOX_PLAYER}, - {".rtttl", SONIVOX_PLAYER}, - {".rtx", SONIVOX_PLAYER}, - {".ota", SONIVOX_PLAYER}, - {".ogg", VORBIS_PLAYER}, - {".oga", VORBIS_PLAYER}, -}; - -// 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; - -void MediaPlayerService::instantiate() { - defaultServiceManager()->addService( - String16("media.player"), new MediaPlayerService()); -} - -MediaPlayerService::MediaPlayerService() -{ - LOGV("MediaPlayerService created"); - mNextConnId = 1; -} - -MediaPlayerService::~MediaPlayerService() -{ - LOGV("MediaPlayerService destroyed"); -} - -sp MediaPlayerService::createMediaRecorder(pid_t pid) -{ - sp recorder = new MediaRecorderClient(pid); - LOGV("Create new media recorder client from pid %d", pid); - return recorder; -} - -sp MediaPlayerService::createMetadataRetriever(pid_t pid) -{ - sp retriever = new MetadataRetrieverClient(pid); - LOGV("Create new media retriever from pid %d", pid); - return retriever; -} - -sp MediaPlayerService::create(pid_t pid, const sp& client, const char* url) -{ - int32_t connId = android_atomic_inc(&mNextConnId); - sp c = new Client(this, pid, connId, client); - LOGV("Create new client(%d) from pid %d, url=%s, connId=%d", connId, pid, url, connId); - if (NO_ERROR != c->setDataSource(url)) - { - c.clear(); - return c; - } - wp w = c; - Mutex::Autolock lock(mLock); - mClients.add(w); - return c; -} - -sp MediaPlayerService::create(pid_t pid, const sp& client, - int fd, int64_t offset, int64_t length) -{ - int32_t connId = android_atomic_inc(&mNextConnId); - sp c = new Client(this, pid, connId, client); - LOGV("Create new client(%d) from pid %d, fd=%d, offset=%lld, length=%lld", - connId, pid, fd, offset, length); - if (NO_ERROR != c->setDataSource(fd, offset, length)) { - c.clear(); - } else { - wp w = c; - Mutex::Autolock lock(mLock); - mClients.add(w); - } - ::close(fd); - return c; -} - -status_t MediaPlayerService::AudioCache::dump(int fd, const Vector& args) const -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - - result.append(" AudioCache\n"); - if (mHeap != 0) { - snprintf(buffer, 255, " heap base(%p), size(%d), flags(%d), device(%s)\n", - mHeap->getBase(), mHeap->getSize(), mHeap->getFlags(), mHeap->getDevice()); - result.append(buffer); - } - 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"); - result.append(buffer); - ::write(fd, result.string(), result.size()); - return NO_ERROR; -} - -status_t MediaPlayerService::AudioOutput::dump(int fd, const Vector& args) const -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - - result.append(" AudioOutput\n"); - 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)\n", - mMsecsPerFrame, mLatency); - result.append(buffer); - ::write(fd, result.string(), result.size()); - if (mTrack != 0) { - mTrack->dump(fd, args); - } - return NO_ERROR; -} - -status_t MediaPlayerService::Client::dump(int fd, const Vector& args) const -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - result.append(" Client\n"); - snprintf(buffer, 255, " pid(%d), connId(%d), status(%d), looping(%s)\n", - mPid, mConnId, mStatus, mLoop?"true": "false"); - result.append(buffer); - write(fd, result.string(), result.size()); - if (mAudioOutput != 0) { - mAudioOutput->dump(fd, args); - } - write(fd, "\n", 1); - return NO_ERROR; -} - -static int myTid() { -#ifdef HAVE_GETTID - return gettid(); -#else - return getpid(); -#endif -} - -status_t MediaPlayerService::dump(int fd, const Vector& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - if (checkCallingPermission(String16("android.permission.DUMP")) == false) { - snprintf(buffer, SIZE, "Permission Denial: " - "can't dump MediaPlayerService from pid=%d, uid=%d\n", - IPCThreadState::self()->getCallingPid(), - IPCThreadState::self()->getCallingUid()); - result.append(buffer); - } else { - Mutex::Autolock lock(mLock); - for (int i = 0, n = mClients.size(); i < n; ++i) { - sp c = mClients[i].promote(); - if (c != 0) c->dump(fd, args); - } - result.append(" Files opened and/or mapped:\n"); - snprintf(buffer, SIZE, "/proc/%d/maps", myTid()); - FILE *f = fopen(buffer, "r"); - if (f) { - while (!feof(f)) { - fgets(buffer, SIZE, f); - if (strstr(buffer, " /sdcard/") || - strstr(buffer, " /system/sounds/") || - strstr(buffer, " /system/media/")) { - result.append(" "); - result.append(buffer); - } - } - fclose(f); - } else { - result.append("couldn't open "); - result.append(buffer); - result.append("\n"); - } - - snprintf(buffer, SIZE, "/proc/%d/fd", myTid()); - DIR *d = opendir(buffer); - if (d) { - struct dirent *ent; - while((ent = readdir(d)) != NULL) { - 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) { - if ((s.st_mode & S_IFMT) == S_IFLNK) { - char linkto[256]; - int len = readlink(buffer, linkto, sizeof(linkto)); - if(len > 0) { - if(len > 255) { - linkto[252] = '.'; - linkto[253] = '.'; - linkto[254] = '.'; - linkto[255] = 0; - } else { - linkto[len] = 0; - } - if (strstr(linkto, "/sdcard/") == linkto || - strstr(linkto, "/system/sounds/") == linkto || - strstr(linkto, "/system/media/") == linkto) { - result.append(" "); - result.append(buffer); - result.append(" -> "); - result.append(linkto); - result.append("\n"); - } - } - } else { - result.append(" unexpected type for "); - result.append(buffer); - result.append("\n"); - } - } - } - } - closedir(d); - } else { - result.append("couldn't open "); - result.append(buffer); - result.append("\n"); - } - } - write(fd, result.string(), result.size()); - return NO_ERROR; -} - -void MediaPlayerService::removeClient(wp client) -{ - Mutex::Autolock lock(mLock); - mClients.remove(client); -} - -MediaPlayerService::Client::Client(const sp& service, pid_t pid, - int32_t connId, const sp& client) -{ - LOGV("Client(%d) constructor", connId); - mPid = pid; - mConnId = connId; - mService = service; - mClient = client; - mLoop = false; - mStatus = NO_INIT; -#if CALLBACK_ANTAGONIZER - LOGD("create Antagonizer"); - mAntagonizer = new Antagonizer(notify, this); -#endif -} - -MediaPlayerService::Client::~Client() -{ - LOGV("Client(%d) destructor pid = %d", mConnId, mPid); - mAudioOutput.clear(); - wp client(this); - disconnect(); - mService->removeClient(client); -} - -void MediaPlayerService::Client::disconnect() -{ - LOGV("disconnect(%d) from pid %d", mConnId, mPid); - // grab local reference and clear main reference to prevent future - // access to object - sp p; - { - Mutex::Autolock l(mLock); - p = mPlayer; - } - mPlayer.clear(); - - // clear the notification to prevent callbacks to dead client - // and reset the player. We assume the player will serialize - // access to itself if necessary. - if (p != 0) { - p->setNotifyCallback(0, 0); -#if CALLBACK_ANTAGONIZER - LOGD("kill Antagonizer"); - mAntagonizer->kill(); -#endif - p->reset(); - } - - IPCThreadState::self()->flushCommands(); -} - -static player_type getPlayerType(int fd, int64_t offset, int64_t length) -{ - char buf[20]; - lseek(fd, offset, SEEK_SET); - read(fd, buf, sizeof(buf)); - lseek(fd, offset, SEEK_SET); - - long ident = *((long*)buf); - - // Ogg vorbis? - if (ident == 0x5367674f) // 'OggS' - return VORBIS_PLAYER; - - // Some kind of MIDI? - EAS_DATA_HANDLE easdata; - if (EAS_Init(&easdata) == EAS_SUCCESS) { - EAS_FILE locator; - locator.path = NULL; - locator.fd = fd; - locator.offset = offset; - locator.length = length; - EAS_HANDLE eashandle; - if (EAS_OpenFile(easdata, &locator, &eashandle) == EAS_SUCCESS) { - EAS_CloseFile(easdata, eashandle); - EAS_Shutdown(easdata); - return SONIVOX_PLAYER; - } - EAS_Shutdown(easdata); - } - - // Fall through to PV - return PV_PLAYER; -} - -static player_type getPlayerType(const char* url) -{ - - // use MidiFile for MIDI extensions - int lenURL = strlen(url); - for (int i = 0; i < NELEM(FILE_EXTS); ++i) { - int len = strlen(FILE_EXTS[i].extension); - int start = lenURL - len; - if (start > 0) { - if (!strncmp(url + start, FILE_EXTS[i].extension, len)) { - return FILE_EXTS[i].playertype; - } - } - } - - // Fall through to PV - return PV_PLAYER; -} - -static sp createPlayer(player_type playerType, void* cookie, - notify_callback_f notifyFunc) -{ - sp p; - switch (playerType) { - case PV_PLAYER: - LOGV(" create PVPlayer"); - p = new PVPlayer(); - break; - case SONIVOX_PLAYER: - LOGV(" create MidiFile"); - p = new MidiFile(); - break; - case VORBIS_PLAYER: - LOGV(" create VorbisPlayer"); - p = new VorbisPlayer(); - break; - } - if (p != NULL) { - if (p->initCheck() == NO_ERROR) { - p->setNotifyCallback(cookie, notifyFunc); - } else { - p.clear(); - } - } - if (p == NULL) { - LOGE("Failed to create player object"); - } - return p; -} - -sp MediaPlayerService::Client::createPlayer(player_type playerType) -{ - // determine if we have the right player type - sp p = mPlayer; - if ((p != NULL) && (p->playerType() != playerType)) { - LOGV("delete player"); - p.clear(); - } - if (p == NULL) { - p = android::createPlayer(playerType, this, notify); - } - return p; -} - -status_t MediaPlayerService::Client::setDataSource(const char *url) -{ - LOGV("setDataSource(%s)", url); - if (url == NULL) - return UNKNOWN_ERROR; - - if (strncmp(url, "content://", 10) == 0) { - // get a filedescriptor for the content Uri and - // pass it to the setDataSource(fd) method - - String16 url16(url); - int fd = android::openContentProviderFile(url16); - if (fd < 0) - { - LOGE("Couldn't open fd for %s", url); - return UNKNOWN_ERROR; - } - setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus - close(fd); - return mStatus; - } else { - player_type playerType = getPlayerType(url); - LOGV("player type = %d", playerType); - - // create the right type of player - sp p = createPlayer(playerType); - if (p == NULL) return NO_INIT; - - if (!p->hardwareOutput()) { - mAudioOutput = new AudioOutput(); - static_cast(p.get())->setAudioSink(mAudioOutput); - } - - // now set data source - LOGV(" setDataSource"); - mStatus = p->setDataSource(url); - if (mStatus == NO_ERROR) mPlayer = p; - return mStatus; - } -} - -status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length) -{ - LOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length); - 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 error"); - ::close(fd); - return UNKNOWN_ERROR; - } - if (offset + length > sb.st_size) { - length = sb.st_size - offset; - LOGV("calculated length = %lld", length); - } - - player_type playerType = getPlayerType(fd, offset, length); - LOGV("player type = %d", playerType); - - // create the right type of player - sp p = createPlayer(playerType); - if (p == NULL) return NO_INIT; - - if (!p->hardwareOutput()) { - mAudioOutput = new AudioOutput(); - static_cast(p.get())->setAudioSink(mAudioOutput); - } - - // now set data source - mStatus = p->setDataSource(fd, offset, length); - if (mStatus == NO_ERROR) mPlayer = p; - return mStatus; -} - -status_t MediaPlayerService::Client::setVideoSurface(const sp& surface) -{ - LOGV("[%d] setVideoSurface(%p)", mConnId, surface.get()); - sp p = getPlayer(); - if (p == 0) return UNKNOWN_ERROR; - return p->setVideoSurface(surface); -} - -status_t MediaPlayerService::Client::prepareAsync() -{ - LOGV("[%d] prepareAsync", mConnId); - sp p = getPlayer(); - if (p == 0) return UNKNOWN_ERROR; - status_t ret = p->prepareAsync(); -#if CALLBACK_ANTAGONIZER - LOGD("start Antagonizer"); - if (ret == NO_ERROR) mAntagonizer->start(); -#endif - return ret; -} - -status_t MediaPlayerService::Client::start() -{ - LOGV("[%d] start", mConnId); - sp p = getPlayer(); - if (p == 0) return UNKNOWN_ERROR; - p->setLooping(mLoop); - return p->start(); -} - -status_t MediaPlayerService::Client::stop() -{ - LOGV("[%d] stop", mConnId); - sp p = getPlayer(); - if (p == 0) return UNKNOWN_ERROR; - return p->stop(); -} - -status_t MediaPlayerService::Client::pause() -{ - LOGV("[%d] pause", mConnId); - sp p = getPlayer(); - if (p == 0) return UNKNOWN_ERROR; - return p->pause(); -} - -status_t MediaPlayerService::Client::isPlaying(bool* state) -{ - *state = false; - sp p = getPlayer(); - if (p == 0) return UNKNOWN_ERROR; - *state = p->isPlaying(); - LOGV("[%d] isPlaying: %d", mConnId, *state); - return NO_ERROR; -} - -status_t MediaPlayerService::Client::getCurrentPosition(int *msec) -{ - LOGV("getCurrentPosition"); - sp p = getPlayer(); - if (p == 0) return UNKNOWN_ERROR; - status_t ret = p->getCurrentPosition(msec); - if (ret == NO_ERROR) { - LOGV("[%d] getCurrentPosition = %d", mConnId, *msec); - } else { - LOGE("getCurrentPosition returned %d", ret); - } - return ret; -} - -status_t MediaPlayerService::Client::getDuration(int *msec) -{ - LOGV("getDuration"); - sp p = getPlayer(); - if (p == 0) return UNKNOWN_ERROR; - status_t ret = p->getDuration(msec); - if (ret == NO_ERROR) { - LOGV("[%d] getDuration = %d", mConnId, *msec); - } else { - LOGE("getDuration returned %d", ret); - } - return ret; -} - -status_t MediaPlayerService::Client::seekTo(int msec) -{ - LOGV("[%d] seekTo(%d)", mConnId, msec); - sp p = getPlayer(); - if (p == 0) return UNKNOWN_ERROR; - return p->seekTo(msec); -} - -status_t MediaPlayerService::Client::reset() -{ - LOGV("[%d] reset", mConnId); - sp p = getPlayer(); - if (p == 0) return UNKNOWN_ERROR; - return p->reset(); -} - -status_t MediaPlayerService::Client::setAudioStreamType(int type) -{ - LOGV("[%d] setAudioStreamType(%d)", mConnId, type); - // TODO: for hardware output, call player instead - Mutex::Autolock l(mLock); - if (mAudioOutput != 0) mAudioOutput->setAudioStreamType(type); - return NO_ERROR; -} - -status_t MediaPlayerService::Client::setLooping(int loop) -{ - LOGV("[%d] setLooping(%d)", mConnId, loop); - mLoop = loop; - sp p = getPlayer(); - if (p != 0) return p->setLooping(loop); - return NO_ERROR; -} - -status_t MediaPlayerService::Client::setVolume(float leftVolume, float rightVolume) -{ - LOGV("[%d] setVolume(%f, %f)", mConnId, leftVolume, rightVolume); - // TODO: for hardware output, call player instead - Mutex::Autolock l(mLock); - if (mAudioOutput != 0) mAudioOutput->setVolume(leftVolume, rightVolume); - return NO_ERROR; -} - -void MediaPlayerService::Client::notify(void* cookie, int msg, int ext1, int ext2) -{ - Client* client = static_cast(cookie); - LOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, cookie, msg, ext1, ext2); - client->mClient->notify(msg, ext1, ext2); -} - -#if CALLBACK_ANTAGONIZER -const int Antagonizer::interval = 10000; // 10 msecs - -Antagonizer::Antagonizer(notify_callback_f cb, void* client) : - mExit(false), mActive(false), mClient(client), mCb(cb) -{ - createThread(callbackThread, this); -} - -void Antagonizer::kill() -{ - Mutex::Autolock _l(mLock); - mActive = false; - mExit = true; - mCondition.wait(mLock); -} - -int Antagonizer::callbackThread(void* user) -{ - LOGD("Antagonizer started"); - Antagonizer* p = reinterpret_cast(user); - while (!p->mExit) { - if (p->mActive) { - LOGV("send event"); - p->mCb(p->mClient, 0, 0, 0); - } - usleep(interval); - } - Mutex::Autolock _l(p->mLock); - p->mCondition.signal(); - LOGD("Antagonizer stopped"); - return 0; -} -#endif - -static size_t kDefaultHeapSize = 1024 * 1024; // 1MB - -sp MediaPlayerService::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) -{ - LOGV("decode(%s)", url); - sp mem; - sp player; - - // Protect our precious, precious DRMd ringtones by only allowing - // decoding of http, but not filesystem paths or content Uris. - // If the application wants to decode those, it should open a - // filedescriptor for them and use that. - if (url != NULL && strncmp(url, "http://", 7) != 0) { - LOGD("Can't decode %s by path, use filedescriptor instead", url); - return mem; - } - - player_type playerType = getPlayerType(url); - LOGV("player type = %d", playerType); - - // create the right type of player - sp cache = new AudioCache(url); - player = android::createPlayer(playerType, cache.get(), cache->notify); - if (player == NULL) goto Exit; - if (player->hardwareOutput()) goto Exit; - - static_cast(player.get())->setAudioSink(cache); - - // set data source - if (player->setDataSource(url) != NO_ERROR) goto Exit; - - LOGV("prepare"); - player->prepareAsync(); - - LOGV("wait for prepare"); - if (cache->wait() != NO_ERROR) goto Exit; - - LOGV("start"); - player->start(); - - LOGV("wait for playback complete"); - if (cache->wait() != NO_ERROR) goto Exit; - - mem = new MemoryBase(cache->getHeap(), 0, cache->size()); - *pSampleRate = cache->sampleRate(); - *pNumChannels = cache->channelCount(); - *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 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 mem; - sp player; - - player_type playerType = getPlayerType(fd, offset, length); - LOGV("player type = %d", playerType); - - // create the right type of player - sp cache = new AudioCache("decode_fd"); - player = android::createPlayer(playerType, cache.get(), cache->notify); - if (player == NULL) goto Exit; - if (player->hardwareOutput()) goto Exit; - - static_cast(player.get())->setAudioSink(cache); - - // set data source - if (player->setDataSource(fd, offset, length) != NO_ERROR) goto Exit; - - LOGV("prepare"); - player->prepareAsync(); - - LOGV("wait for prepare"); - if (cache->wait() != NO_ERROR) goto Exit; - - LOGV("start"); - player->start(); - - LOGV("wait for playback complete"); - if (cache->wait() != NO_ERROR) goto Exit; - - mem = new MemoryBase(cache->getHeap(), 0, cache->size()); - *pSampleRate = cache->sampleRate(); - *pNumChannels = cache->channelCount(); - *pFormat = cache->format(); - LOGV("return memory @ %p, sampleRate=%u, channelCount = %d, format = %d", mem->pointer(), *pSampleRate, *pNumChannels, *pFormat); - -Exit: - if (player != 0) player->reset(); - ::close(fd); - return mem; -} - -#undef LOG_TAG -#define LOG_TAG "AudioSink" -MediaPlayerService::AudioOutput::AudioOutput() -{ - mTrack = 0; - mStreamType = AudioSystem::MUSIC; - mLeftVolume = 1.0; - mRightVolume = 1.0; - mLatency = 0; - mMsecsPerFrame = 0; - setMinBufferCount(); -} - -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() * frameSize(); -} - -ssize_t MediaPlayerService::AudioOutput::frameCount() const -{ - if (mTrack == 0) return NO_INIT; - return mTrack->frameCount(); -} - -ssize_t MediaPlayerService::AudioOutput::channelCount() const -{ - if (mTrack == 0) return NO_INIT; - return mTrack->channelCount(); -} - -ssize_t MediaPlayerService::AudioOutput::frameSize() const -{ - if (mTrack == 0) return NO_INIT; - return mTrack->frameSize(); -} - -uint32_t MediaPlayerService::AudioOutput::latency () const -{ - return mLatency; -} - -float MediaPlayerService::AudioOutput::msecsPerFrame() const -{ - return mMsecsPerFrame; -} - -status_t MediaPlayerService::AudioOutput::open(uint32_t sampleRate, int channelCount, int format, int 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; - - if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) { - return NO_INIT; - } - if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) { - return NO_INIT; - } - - frameCount = (sampleRate*afFrameCount*bufferCount)/afSampleRate; - AudioTrack *t = new AudioTrack(mStreamType, sampleRate, format, channelCount, frameCount); - if ((t == 0) || (t->initCheck() != NO_ERROR)) { - LOGE("Unable to create audio track"); - delete t; - return NO_INIT; - } - - LOGV("setVolume"); - t->setVolume(mLeftVolume, mRightVolume); - mMsecsPerFrame = 1.e3 / (float) sampleRate; - mLatency = t->latency() + kAudioVideoDelayMs; - mTrack = t; - return NO_ERROR; -} - -void MediaPlayerService::AudioOutput::start() -{ - LOGV("start"); - if (mTrack) { - mTrack->setVolume(mLeftVolume, mRightVolume); - mTrack->start(); - } -} - -ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size) -{ - //LOGV("write(%p, %u)", buffer, size); - if (mTrack) return mTrack->write(buffer, size); - return NO_INIT; -} - -void MediaPlayerService::AudioOutput::stop() -{ - LOGV("stop"); - if (mTrack) mTrack->stop(); -} - -void MediaPlayerService::AudioOutput::flush() -{ - LOGV("flush"); - if (mTrack) mTrack->flush(); -} - -void MediaPlayerService::AudioOutput::pause() -{ - LOGV("pause"); - if (mTrack) mTrack->pause(); -} - -void MediaPlayerService::AudioOutput::close() -{ - LOGV("close"); - delete mTrack; - mTrack = 0; -} - -void MediaPlayerService::AudioOutput::setVolume(float left, float right) -{ - LOGV("setVolume(%f, %f)", left, right); - mLeftVolume = left; - mRightVolume = right; - if (mTrack) { - mTrack->setVolume(left, right); - } -} - -#undef LOG_TAG -#define LOG_TAG "AudioCache" -MediaPlayerService::AudioCache::AudioCache(const char* name) : - mChannelCount(0), mFrameCount(1024), mSampleRate(0), mSize(0), - mError(NO_ERROR), mCommandComplete(false) -{ - // create ashmem heap - mHeap = new MemoryHeapBase(kDefaultHeapSize, 0, name); -} - -uint32_t MediaPlayerService::AudioCache::latency () const -{ - return 0; -} - -float MediaPlayerService::AudioCache::msecsPerFrame() const -{ - return mMsecsPerFrame; -} - -status_t MediaPlayerService::AudioCache::open(uint32_t sampleRate, int channelCount, int format, int bufferCount) -{ - 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; -} - -ssize_t MediaPlayerService::AudioCache::write(const void* buffer, size_t size) -{ - LOGV("write(%p, %u)", buffer, size); - if ((buffer == 0) || (size == 0)) return size; - - uint8_t* p = static_cast(mHeap->getBase()); - 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; -} - -// call with lock held -status_t MediaPlayerService::AudioCache::wait() -{ - Mutex::Autolock lock(mLock); - if (!mCommandComplete) { - mSignal.wait(mLock); - } - mCommandComplete = false; - - if (mError == NO_ERROR) { - LOGV("wait - success"); - } else { - LOGV("wait - error"); - } - return mError; -} - -void MediaPlayerService::AudioCache::notify(void* cookie, int msg, int ext1, int ext2) -{ - LOGV("notify(%p, %d, %d, %d)", cookie, msg, ext1, ext2); - AudioCache* p = static_cast(cookie); - - // ignore buffering messages - if (msg == MEDIA_BUFFERING_UPDATE) return; - - // set error condition - if (msg == MEDIA_ERROR) { - LOGE("Error %d, %d occurred", ext1, ext2); - p->mError = ext1; - } - - // wake up thread - LOGV("wakeup thread"); - p->mCommandComplete = true; - p->mSignal.signal(); -} - -}; // namespace android diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h deleted file mode 100644 index f138886..0000000 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ /dev/null @@ -1,238 +0,0 @@ -/* -** -** Copyright 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_MEDIAPLAYERSERVICE_H -#define ANDROID_MEDIAPLAYERSERVICE_H - -#include -#include -#include - -#include -#include - -namespace android { - -class IMediaRecorder; -class IMediaMetadataRetriever; - -#define CALLBACK_ANTAGONIZER 0 -#if CALLBACK_ANTAGONIZER -class Antagonizer { -public: - Antagonizer(notify_callback_f cb, void* client); - void start() { mActive = true; } - void stop() { mActive = false; } - void kill(); -private: - static const int interval; - Antagonizer(); - static int callbackThread(void* cookie); - Mutex mLock; - Condition mCondition; - bool mExit; - bool mActive; - void* mClient; - notify_callback_f mCb; -}; -#endif - -class MediaPlayerService : public BnMediaPlayerService -{ - class Client; - - class AudioOutput : public MediaPlayerBase::AudioSink - { - public: - AudioOutput(); - virtual ~AudioOutput(); - - virtual bool ready() const { return mTrack != NULL; } - virtual bool realtime() const { return true; } - virtual ssize_t bufferSize() const; - virtual ssize_t frameCount() const; - virtual ssize_t channelCount() const; - virtual ssize_t frameSize() const; - virtual uint32_t latency() const; - virtual float msecsPerFrame() const; - 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(); - virtual void flush(); - virtual void pause(); - virtual void close(); - void setAudioStreamType(int streamType) { mStreamType = streamType; } - void setVolume(float left, float right); - virtual status_t dump(int fd, const Vector& 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; - - // 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 - { - public: - AudioCache(const char* name); - virtual ~AudioCache() {} - - virtual bool ready() const { return (mChannelCount > 0) && (mHeap->getHeapID() > 0); } - virtual bool realtime() const { return false; } - virtual ssize_t bufferSize() const { return frameSize() * mFrameCount; } - virtual ssize_t frameCount() const { return mFrameCount; } - 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 format, int bufferCount=1); - virtual void start() {} - virtual ssize_t write(const void* buffer, size_t size); - virtual void stop() {} - virtual void flush() {} - virtual void pause() {} - virtual void close() {} - 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(); - - sp getHeap() const { return mHeap; } - - static void notify(void* cookie, int msg, int ext1, int ext2); - virtual status_t dump(int fd, const Vector& args) const; - - private: - AudioCache(); - - Mutex mLock; - Condition mSignal; - sp mHeap; - float mMsecsPerFrame; - uint16_t mChannelCount; - uint16_t mFormat; - ssize_t mFrameCount; - uint32_t mSampleRate; - uint32_t mSize; - int mError; - bool mCommandComplete; - }; - -public: - static void instantiate(); - - // IMediaPlayerService interface - virtual sp createMediaRecorder(pid_t pid); - virtual sp createMetadataRetriever(pid_t pid); - - // House keeping for media player clients - virtual sp create(pid_t pid, const sp& client, const char* url); - virtual sp create(pid_t pid, const sp& client, int fd, int64_t offset, int64_t length); - virtual sp decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat); - virtual sp decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat); - - virtual status_t dump(int fd, const Vector& args); - - void removeClient(wp client); - -private: - - class Client : public BnMediaPlayer { - - // IMediaPlayer interface - virtual void disconnect(); - virtual status_t setVideoSurface(const sp& surface); - virtual status_t prepareAsync(); - virtual status_t start(); - virtual status_t stop(); - virtual status_t pause(); - virtual status_t isPlaying(bool* state); - virtual status_t seekTo(int msec); - virtual status_t getCurrentPosition(int* msec); - virtual status_t getDuration(int* msec); - virtual status_t reset(); - virtual status_t setAudioStreamType(int type); - virtual status_t setLooping(int loop); - virtual status_t setVolume(float leftVolume, float rightVolume); - - sp createPlayer(player_type playerType); - status_t setDataSource(const char *url); - status_t setDataSource(int fd, int64_t offset, int64_t length); - static void notify(void* cookie, int msg, int ext1, int ext2); - - pid_t pid() const { return mPid; } - virtual status_t dump(int fd, const Vector& args) const; - - private: - friend class MediaPlayerService; - Client( const sp& service, - pid_t pid, - int32_t connId, - const sp& client); - Client(); - virtual ~Client(); - - void deletePlayer(); - - sp getPlayer() const { Mutex::Autolock lock(mLock); return mPlayer; } - - mutable Mutex mLock; - sp mPlayer; - sp mService; - sp mClient; - sp mAudioOutput; - pid_t mPid; - status_t mStatus; - bool mLoop; - int32_t mConnId; -#if CALLBACK_ANTAGONIZER - Antagonizer* mAntagonizer; -#endif - }; - -// ---------------------------------------------------------------------------- - - MediaPlayerService(); - virtual ~MediaPlayerService(); - - mutable Mutex mLock; - SortedVector< wp > mClients; - int32_t mNextConnId; -}; - -// ---------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_MEDIAPLAYERSERVICE_H - diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp deleted file mode 100644 index e8ba17f..0000000 --- a/media/libmediaplayerservice/MediaRecorderClient.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/* - ** 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "MediaRecorderClient.h" - -namespace android { - -status_t MediaRecorderClient::setCamera(const sp& 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& 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::setOutputFile(int fd, int64_t offset, int64_t length) -{ - LOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length); - Mutex::Autolock lock(mLock); - if (mRecorder == NULL) { - LOGE("recorder is not initialized"); - return NO_INIT; - } - return mRecorder->setOutputFile(fd, offset, length); -} - -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 deleted file mode 100644 index 2b80c10..0000000 --- a/media/libmediaplayerservice/MediaRecorderClient.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - ** - ** 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 - -namespace android { - -class PVMediaRecorder; -class ISurface; - -class MediaRecorderClient : public BnMediaRecorder -{ -public: - virtual status_t setCamera(const sp& camera); - virtual status_t setPreviewSurface(const sp& 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 setOutputFile(int fd, int64_t offset, int64_t length); - 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 deleted file mode 100644 index a320bd5..0000000 --- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/* -** -** 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 - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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& 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 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(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 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(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 deleted file mode 100644 index ce29c98..0000000 --- a/media/libmediaplayerservice/MetadataRetrieverClient.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -** -** 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 -#include -#include - -#include - - -namespace android { - -class IMediaPlayerService; -class MemoryDealer; - -class MetadataRetrieverClient : public BnMediaMetadataRetriever -{ -public: - MetadataRetrieverClient(const sp& 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 captureFrame(); - virtual sp extractAlbumArt(); - virtual const char* extractMetadata(int keyCode); - - virtual status_t dump(int fd, const Vector& args) const; - -private: - friend class MediaPlayerService; - - explicit MetadataRetrieverClient(pid_t pid); - virtual ~MetadataRetrieverClient(); - - mutable Mutex mLock; - sp mRetriever; - pid_t mPid; - - // Keep the shared memory copy of album art and capture frame (for thumbnail) - sp mAlbumArtDealer; - sp mThumbnailDealer; - sp mAlbumArt; - sp mThumbnail; -}; - -}; // namespace android - -#endif // ANDROID_MEDIAMETADATARETRIEVERSERVICE_H - diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp deleted file mode 100644 index d03caa5..0000000 --- a/media/libmediaplayerservice/MidiFile.cpp +++ /dev/null @@ -1,558 +0,0 @@ -/* MidiFile.cpp -** -** Copyright 2007, 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 "MidiFile" -#include "utils/Log.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "MidiFile.h" - -#ifdef HAVE_GETTID -static pid_t myTid() { return gettid(); } -#else -static pid_t myTid() { return getpid(); } -#endif - -// ---------------------------------------------------------------------------- - -namespace android { - -// ---------------------------------------------------------------------------- - -// The midi engine buffers are a bit small (128 frames), so we batch them up -static const int NUM_BUFFERS = 4; - -// TODO: Determine appropriate return codes -static status_t ERROR_NOT_OPEN = -1; -static status_t ERROR_OPEN_FAILED = -2; -static status_t ERROR_EAS_FAILURE = -3; -static status_t ERROR_ALLOCATE_FAILED = -4; - -static const S_EAS_LIB_CONFIG* pLibConfig = NULL; - -MidiFile::MidiFile() : - mEasData(NULL), mEasHandle(NULL), mAudioBuffer(NULL), - mPlayTime(-1), mDuration(-1), mState(EAS_STATE_ERROR), - mStreamType(AudioSystem::MUSIC), mLoop(false), mExit(false), - mPaused(false), mRender(false), mTid(-1) -{ - LOGV("constructor"); - - mFileLocator.path = NULL; - mFileLocator.fd = -1; - mFileLocator.offset = 0; - mFileLocator.length = 0; - - // get the library configuration and do sanity check - if (pLibConfig == NULL) - pLibConfig = EAS_Config(); - if ((pLibConfig == NULL) || (LIB_VERSION != pLibConfig->libVersion)) { - LOGE("EAS library/header mismatch"); - goto Failed; - } - - // initialize EAS library - if (EAS_Init(&mEasData) != EAS_SUCCESS) { - LOGE("EAS_Init failed"); - goto Failed; - } - - // select reverb preset and enable - EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_PRESET, EAS_PARAM_REVERB_CHAMBER); - EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_BYPASS, EAS_FALSE); - - // create playback thread - { - Mutex::Autolock l(mMutex); - createThreadEtc(renderThread, this, "midithread"); - mCondition.wait(mMutex); - LOGV("thread started"); - } - - // indicate success - if (mTid > 0) { - LOGV(" render thread(%d) started", mTid); - mState = EAS_STATE_READY; - } - -Failed: - return; -} - -status_t MidiFile::initCheck() -{ - if (mState == EAS_STATE_ERROR) return ERROR_EAS_FAILURE; - return NO_ERROR; -} - -MidiFile::~MidiFile() { - LOGV("MidiFile destructor"); - release(); -} - -status_t MidiFile::setDataSource(const char* path) -{ - LOGV("MidiFile::setDataSource url=%s", path); - Mutex::Autolock lock(mMutex); - - // file still open? - if (mEasHandle) { - reset_nosync(); - } - - // open file and set paused state - mFileLocator.path = strdup(path); - mFileLocator.fd = -1; - mFileLocator.offset = 0; - mFileLocator.length = 0; - EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle); - if (result == EAS_SUCCESS) { - updateState(); - } - - if (result != EAS_SUCCESS) { - LOGE("EAS_OpenFile failed: [%d]", (int)result); - mState = EAS_STATE_ERROR; - return ERROR_OPEN_FAILED; - } - - mState = EAS_STATE_OPEN; - mPlayTime = 0; - return NO_ERROR; -} - -status_t MidiFile::setDataSource(int fd, int64_t offset, int64_t length) -{ - LOGV("MidiFile::setDataSource fd=%d", fd); - Mutex::Autolock lock(mMutex); - - // file still open? - if (mEasHandle) { - reset_nosync(); - } - - // open file and set paused state - mFileLocator.fd = dup(fd); - mFileLocator.offset = offset; - mFileLocator.length = length; - EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle); - updateState(); - - if (result != EAS_SUCCESS) { - LOGE("EAS_OpenFile failed: [%d]", (int)result); - mState = EAS_STATE_ERROR; - return ERROR_OPEN_FAILED; - } - - mState = EAS_STATE_OPEN; - mPlayTime = 0; - return NO_ERROR; -} - -status_t MidiFile::prepare() -{ - LOGV("MidiFile::prepare"); - Mutex::Autolock lock(mMutex); - if (!mEasHandle) { - return ERROR_NOT_OPEN; - } - EAS_RESULT result; - if ((result = EAS_Prepare(mEasData, mEasHandle)) != EAS_SUCCESS) { - LOGE("EAS_Prepare failed: [%ld]", result); - return ERROR_EAS_FAILURE; - } - updateState(); - return NO_ERROR; -} - -status_t MidiFile::prepareAsync() -{ - LOGV("MidiFile::prepareAsync"); - status_t ret = prepare(); - - // don't hold lock during callback - if (ret == NO_ERROR) { - sendEvent(MEDIA_PREPARED); - } else { - sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ret); - } - return ret; -} - -status_t MidiFile::start() -{ - LOGV("MidiFile::start"); - Mutex::Autolock lock(mMutex); - if (!mEasHandle) { - return ERROR_NOT_OPEN; - } - - // resuming after pause? - if (mPaused) { - if (EAS_Resume(mEasData, mEasHandle) != EAS_SUCCESS) { - return ERROR_EAS_FAILURE; - } - mPaused = false; - updateState(); - } - - mRender = true; - - // wake up render thread - LOGV(" wakeup render thread"); - mCondition.signal(); - return NO_ERROR; -} - -status_t MidiFile::stop() -{ - LOGV("MidiFile::stop"); - Mutex::Autolock lock(mMutex); - if (!mEasHandle) { - return ERROR_NOT_OPEN; - } - if (!mPaused && (mState != EAS_STATE_STOPPED)) { - EAS_RESULT result = EAS_Pause(mEasData, mEasHandle); - if (result != EAS_SUCCESS) { - LOGE("EAS_Pause returned error %ld", result); - return ERROR_EAS_FAILURE; - } - } - mPaused = false; - return NO_ERROR; -} - -status_t MidiFile::seekTo(int position) -{ - LOGV("MidiFile::seekTo %d", position); - // hold lock during EAS calls - { - Mutex::Autolock lock(mMutex); - if (!mEasHandle) { - return ERROR_NOT_OPEN; - } - EAS_RESULT result; - if ((result = EAS_Locate(mEasData, mEasHandle, position, false)) - != EAS_SUCCESS) - { - LOGE("EAS_Locate returned %ld", result); - return ERROR_EAS_FAILURE; - } - EAS_GetLocation(mEasData, mEasHandle, &mPlayTime); - } - sendEvent(MEDIA_SEEK_COMPLETE); - return NO_ERROR; -} - -status_t MidiFile::pause() -{ - LOGV("MidiFile::pause"); - Mutex::Autolock lock(mMutex); - if (!mEasHandle) { - return ERROR_NOT_OPEN; - } - if ((mState == EAS_STATE_PAUSING) || (mState == EAS_STATE_PAUSED)) return NO_ERROR; - if (EAS_Pause(mEasData, mEasHandle) != EAS_SUCCESS) { - return ERROR_EAS_FAILURE; - } - mPaused = true; - return NO_ERROR; -} - -bool MidiFile::isPlaying() -{ - LOGV("MidiFile::isPlaying, mState=%d", int(mState)); - if (!mEasHandle || mPaused) return false; - return (mState == EAS_STATE_PLAY); -} - -status_t MidiFile::getCurrentPosition(int* position) -{ - LOGV("MidiFile::getCurrentPosition"); - if (!mEasHandle) { - LOGE("getCurrentPosition(): file not open"); - return ERROR_NOT_OPEN; - } - if (mPlayTime < 0) { - LOGE("getCurrentPosition(): mPlayTime = %ld", mPlayTime); - return ERROR_EAS_FAILURE; - } - *position = mPlayTime; - return NO_ERROR; -} - -status_t MidiFile::getDuration(int* duration) -{ - - LOGV("MidiFile::getDuration"); - { - Mutex::Autolock lock(mMutex); - if (!mEasHandle) return ERROR_NOT_OPEN; - *duration = mDuration; - } - - // if no duration cached, get the duration - // don't need a lock here because we spin up a new engine - if (*duration < 0) { - EAS_I32 temp; - EAS_DATA_HANDLE easData = NULL; - EAS_HANDLE easHandle = NULL; - EAS_RESULT result = EAS_Init(&easData); - if (result == EAS_SUCCESS) { - result = EAS_OpenFile(easData, &mFileLocator, &easHandle); - } - if (result == EAS_SUCCESS) { - result = EAS_Prepare(easData, easHandle); - } - if (result == EAS_SUCCESS) { - result = EAS_ParseMetaData(easData, easHandle, &temp); - } - if (easHandle) { - EAS_CloseFile(easData, easHandle); - } - if (easData) { - EAS_Shutdown(easData); - } - - if (result != EAS_SUCCESS) { - return ERROR_EAS_FAILURE; - } - - // cache successful result - mDuration = *duration = int(temp); - } - - return NO_ERROR; -} - -status_t MidiFile::release() -{ - LOGV("MidiFile::release"); - Mutex::Autolock l(mMutex); - reset_nosync(); - - // wait for render thread to exit - mExit = true; - mCondition.signal(); - - // wait for thread to exit - if (mAudioBuffer) { - mCondition.wait(mMutex); - } - - // release resources - if (mEasData) { - EAS_Shutdown(mEasData); - mEasData = NULL; - } - return NO_ERROR; -} - -status_t MidiFile::reset() -{ - LOGV("MidiFile::reset"); - Mutex::Autolock lock(mMutex); - return reset_nosync(); -} - -// call only with mutex held -status_t MidiFile::reset_nosync() -{ - LOGV("MidiFile::reset_nosync"); - // close file - if (mEasHandle) { - EAS_CloseFile(mEasData, mEasHandle); - mEasHandle = NULL; - } - if (mFileLocator.path) { - free((void*)mFileLocator.path); - mFileLocator.path = NULL; - } - if (mFileLocator.fd >= 0) { - close(mFileLocator.fd); - } - mFileLocator.fd = -1; - mFileLocator.offset = 0; - mFileLocator.length = 0; - - mPlayTime = -1; - mDuration = -1; - mLoop = false; - mPaused = false; - mRender = false; - return NO_ERROR; -} - -status_t MidiFile::setLooping(int loop) -{ - LOGV("MidiFile::setLooping"); - Mutex::Autolock lock(mMutex); - if (!mEasHandle) { - return ERROR_NOT_OPEN; - } - loop = loop ? -1 : 0; - if (EAS_SetRepeat(mEasData, mEasHandle, loop) != EAS_SUCCESS) { - return ERROR_EAS_FAILURE; - } - return NO_ERROR; -} - -status_t MidiFile::createOutputTrack() { - if (mAudioSink->open(pLibConfig->sampleRate, pLibConfig->numChannels, AudioSystem::PCM_16_BIT, 2) != NO_ERROR) { - LOGE("mAudioSink open failed"); - return ERROR_OPEN_FAILED; - } - return NO_ERROR; -} - -int MidiFile::renderThread(void* p) { - - return ((MidiFile*)p)->render(); -} - -int MidiFile::render() { - EAS_RESULT result = EAS_FAILURE; - EAS_I32 count; - int temp; - bool audioStarted = false; - - LOGV("MidiFile::render"); - - // allocate render buffer - mAudioBuffer = new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * NUM_BUFFERS]; - if (!mAudioBuffer) { - LOGE("mAudioBuffer allocate failed"); - goto threadExit; - } - - // signal main thread that we started - { - Mutex::Autolock l(mMutex); - mTid = myTid(); - LOGV("render thread(%d) signal", mTid); - mCondition.signal(); - } - - while (1) { - mMutex.lock(); - - // nothing to render, wait for client thread to wake us up - while (!mRender && !mExit) - { - LOGV("MidiFile::render - signal wait"); - mCondition.wait(mMutex); - LOGV("MidiFile::render - signal rx'd"); - } - if (mExit) { - mMutex.unlock(); - break; - } - - // render midi data into the input buffer - //LOGV("MidiFile::render - rendering audio"); - int num_output = 0; - EAS_PCM* p = mAudioBuffer; - for (int i = 0; i < NUM_BUFFERS; i++) { - result = EAS_Render(mEasData, p, pLibConfig->mixBufferSize, &count); - if (result != EAS_SUCCESS) { - LOGE("EAS_Render returned %ld", result); - } - p += count * pLibConfig->numChannels; - num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM); - } - - // update playback state and position - // LOGV("MidiFile::render - updating state"); - EAS_GetLocation(mEasData, mEasHandle, &mPlayTime); - EAS_State(mEasData, mEasHandle, &mState); - mMutex.unlock(); - - // create audio output track if necessary - if (!mAudioSink->ready()) { - LOGV("MidiFile::render - create output track"); - if (createOutputTrack() != NO_ERROR) - goto threadExit; - } - - // Write data to the audio hardware - // LOGV("MidiFile::render - writing to audio output"); - if ((temp = mAudioSink->write(mAudioBuffer, num_output)) < 0) { - LOGE("Error in writing:%d",temp); - return temp; - } - - // start audio output if necessary - if (!audioStarted) { - //LOGV("MidiFile::render - starting audio"); - mAudioSink->start(); - audioStarted = true; - } - - // still playing? - if ((mState == EAS_STATE_STOPPED) || (mState == EAS_STATE_ERROR) || - (mState == EAS_STATE_PAUSED)) - { - switch(mState) { - case EAS_STATE_STOPPED: - { - LOGV("MidiFile::render - stopped"); - sendEvent(MEDIA_PLAYBACK_COMPLETE); - break; - } - case EAS_STATE_ERROR: - { - LOGE("MidiFile::render - error"); - sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN); - break; - } - case EAS_STATE_PAUSED: - LOGV("MidiFile::render - paused"); - break; - default: - break; - } - mAudioSink->stop(); - audioStarted = false; - mRender = false; - } - } - -threadExit: - mAudioSink.clear(); - if (mAudioBuffer) { - delete [] mAudioBuffer; - mAudioBuffer = NULL; - } - mMutex.lock(); - mTid = -1; - mCondition.signal(); - mMutex.unlock(); - return result; -} - -} // end namespace android diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h deleted file mode 100644 index 302f1cf..0000000 --- a/media/libmediaplayerservice/MidiFile.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -** -** Copyright 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_MIDIFILE_H -#define ANDROID_MIDIFILE_H - -#include -#include -#include - -namespace android { - -class MidiFile : public MediaPlayerInterface { -public: - MidiFile(); - ~MidiFile(); - - virtual status_t initCheck(); - virtual status_t setDataSource(const char* path); - virtual status_t setDataSource(int fd, int64_t offset, int64_t length); - virtual status_t setVideoSurface(const sp& surface) { return UNKNOWN_ERROR; } - virtual status_t prepare(); - virtual status_t prepareAsync(); - virtual status_t start(); - virtual status_t stop(); - virtual status_t seekTo(int msec); - virtual status_t pause(); - virtual bool isPlaying(); - virtual status_t getCurrentPosition(int* msec); - virtual status_t getDuration(int* msec); - virtual status_t release(); - virtual status_t reset(); - virtual status_t setLooping(int loop); - virtual player_type playerType() { return SONIVOX_PLAYER; } - -private: - status_t createOutputTrack(); - status_t reset_nosync(); - static int renderThread(void*); - int render(); - void updateState(){ EAS_State(mEasData, mEasHandle, &mState); } - - Mutex mMutex; - Condition mCondition; - EAS_DATA_HANDLE mEasData; - EAS_HANDLE mEasHandle; - EAS_PCM* mAudioBuffer; - EAS_I32 mPlayTime; - EAS_I32 mDuration; - EAS_STATE mState; - EAS_FILE mFileLocator; - int mStreamType; - bool mLoop; - volatile bool mExit; - bool mPaused; - volatile bool mRender; - pid_t mTid; -}; - -}; // namespace android - -#endif // ANDROID_MIDIFILE_H - diff --git a/media/libmediaplayerservice/VorbisPlayer.cpp b/media/libmediaplayerservice/VorbisPlayer.cpp deleted file mode 100644 index 0ad335f..0000000 --- a/media/libmediaplayerservice/VorbisPlayer.cpp +++ /dev/null @@ -1,529 +0,0 @@ -/* -** Copyright 2007, 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 "VorbisPlayer" -#include "utils/Log.h" - -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "VorbisPlayer.h" - -#ifdef HAVE_GETTID -static pid_t myTid() { return gettid(); } -#else -static pid_t myTid() { return getpid(); } -#endif - -// ---------------------------------------------------------------------------- - -namespace android { - -// ---------------------------------------------------------------------------- - -// TODO: Determine appropriate return codes -static status_t ERROR_NOT_OPEN = -1; -static status_t ERROR_OPEN_FAILED = -2; -static status_t ERROR_ALLOCATE_FAILED = -4; -static status_t ERROR_NOT_SUPPORTED = -8; -static status_t ERROR_NOT_READY = -16; -static status_t STATE_INIT = 0; -static status_t STATE_ERROR = 1; -static status_t STATE_OPEN = 2; - - -VorbisPlayer::VorbisPlayer() : - mAudioBuffer(NULL), mPlayTime(-1), mDuration(-1), mState(STATE_ERROR), - mStreamType(AudioSystem::MUSIC), mLoop(false), mAndroidLoop(false), - mExit(false), mPaused(false), mRender(false), mRenderTid(-1) -{ - LOGV("constructor\n"); - memset(&mVorbisFile, 0, sizeof mVorbisFile); -} - -void VorbisPlayer::onFirstRef() -{ - LOGV("onFirstRef"); - // create playback thread - Mutex::Autolock l(mMutex); - createThreadEtc(renderThread, this, "vorbis decoder"); - mCondition.wait(mMutex); - if (mRenderTid > 0) { - LOGV("render thread(%d) started", mRenderTid); - mState = STATE_INIT; - } -} - -status_t VorbisPlayer::initCheck() -{ - if (mState != STATE_ERROR) return NO_ERROR; - return ERROR_NOT_READY; -} - -VorbisPlayer::~VorbisPlayer() { - LOGV("VorbisPlayer destructor\n"); - release(); -} - -status_t VorbisPlayer::setDataSource(const char* path) -{ - return setdatasource(path, -1, 0, 0x7ffffffffffffffLL); // intentionally less than LONG_MAX -} - -status_t VorbisPlayer::setDataSource(int fd, int64_t offset, int64_t length) -{ - return setdatasource(NULL, fd, offset, length); -} - -size_t VorbisPlayer::vp_fread(void *buf, size_t size, size_t nmemb, void *me) { - VorbisPlayer *self = (VorbisPlayer*) me; - - long curpos = vp_ftell(me); - while (nmemb != 0 && (curpos + size * nmemb) > self->mLength) { - nmemb--; - } - return fread(buf, size, nmemb, self->mFile); -} - -int VorbisPlayer::vp_fseek(void *me, ogg_int64_t off, int whence) { - VorbisPlayer *self = (VorbisPlayer*) me; - if (whence == SEEK_SET) - return fseek(self->mFile, off + self->mOffset, whence); - else if (whence == SEEK_CUR) - return fseek(self->mFile, off, whence); - else if (whence == SEEK_END) - return fseek(self->mFile, self->mOffset + self->mLength + off, SEEK_SET); - return -1; -} - -int VorbisPlayer::vp_fclose(void *me) { - LOGV("vp_fclose"); - VorbisPlayer *self = (VorbisPlayer*) me; - int ret = fclose (self->mFile); - self->mFile = NULL; - return ret; -} - -long VorbisPlayer::vp_ftell(void *me) { - VorbisPlayer *self = (VorbisPlayer*) me; - return ftell(self->mFile) - self->mOffset; -} - -status_t VorbisPlayer::setdatasource(const char *path, int fd, int64_t offset, int64_t length) -{ - LOGV("setDataSource url=%s, fd=%d\n", path, fd); - - // file still open? - Mutex::Autolock l(mMutex); - if (mState == STATE_OPEN) { - reset_nosync(); - } - - // open file and set paused state - if (path) { - mFile = fopen(path, "r"); - } else { - mFile = fdopen(dup(fd), "r"); - } - if (mFile == NULL) { - return ERROR_OPEN_FAILED; - } - - struct stat sb; - int ret; - if (path) { - ret = stat(path, &sb); - } else { - ret = fstat(fd, &sb); - } - if (ret != 0) { - mState = STATE_ERROR; - fclose(mFile); - return ERROR_OPEN_FAILED; - } - if (sb.st_size > (length + offset)) { - mLength = length; - } else { - mLength = sb.st_size - offset; - } - - ov_callbacks callbacks = { - (size_t (*)(void *, size_t, size_t, void *)) vp_fread, - (int (*)(void *, ogg_int64_t, int)) vp_fseek, - (int (*)(void *)) vp_fclose, - (long (*)(void *)) vp_ftell - }; - - mOffset = offset; - fseek(mFile, offset, SEEK_SET); - - int result = ov_open_callbacks(this, &mVorbisFile, NULL, 0, callbacks); - if (result < 0) { - LOGE("ov_open() failed: [%d]\n", (int)result); - mState = STATE_ERROR; - fclose(mFile); - return ERROR_OPEN_FAILED; - } - - // look for the android loop tag (for ringtones) - char **ptr = ov_comment(&mVorbisFile,-1)->user_comments; - while(*ptr) { - // does the comment start with ANDROID_LOOP_TAG - if(strncmp(*ptr, ANDROID_LOOP_TAG, strlen(ANDROID_LOOP_TAG)) == 0) { - // read the value of the tag - char *val = *ptr + strlen(ANDROID_LOOP_TAG) + 1; - mAndroidLoop = (strncmp(val, "true", 4) == 0); - } - // we keep parsing even after finding one occurence of ANDROID_LOOP_TAG, - // as we could find another one (the tag might have been appended more than once). - ++ptr; - } - LOGV_IF(mAndroidLoop, "looped sound"); - - mState = STATE_OPEN; - return NO_ERROR; -} - -status_t VorbisPlayer::prepare() -{ - LOGV("prepare\n"); - if (mState != STATE_OPEN ) { - return ERROR_NOT_OPEN; - } - return NO_ERROR; -} - -status_t VorbisPlayer::prepareAsync() { - LOGV("prepareAsync\n"); - // can't hold the lock here because of the callback - // it's safe because we don't change state - if (mState != STATE_OPEN ) { - sendEvent(MEDIA_ERROR); - return NO_ERROR; - } - sendEvent(MEDIA_PREPARED); - return NO_ERROR; -} - -status_t VorbisPlayer::start() -{ - LOGV("start\n"); - Mutex::Autolock l(mMutex); - if (mState != STATE_OPEN) { - return ERROR_NOT_OPEN; - } - - mPaused = false; - mRender = true; - - // wake up render thread - LOGV(" wakeup render thread\n"); - mCondition.signal(); - return NO_ERROR; -} - -status_t VorbisPlayer::stop() -{ - LOGV("stop\n"); - Mutex::Autolock l(mMutex); - if (mState != STATE_OPEN) { - return ERROR_NOT_OPEN; - } - mPaused = true; - mRender = false; - return NO_ERROR; -} - -status_t VorbisPlayer::seekTo(int position) -{ - LOGV("seekTo %d\n", position); - Mutex::Autolock l(mMutex); - if (mState != STATE_OPEN) { - return ERROR_NOT_OPEN; - } - - int result = ov_time_seek(&mVorbisFile, position); - if (result != 0) { - LOGE("ov_time_seek() returned %d\n", result); - return result; - } - sendEvent(MEDIA_SEEK_COMPLETE); - return NO_ERROR; -} - -status_t VorbisPlayer::pause() -{ - LOGV("pause\n"); - Mutex::Autolock l(mMutex); - if (mState != STATE_OPEN) { - return ERROR_NOT_OPEN; - } - mPaused = true; - return NO_ERROR; -} - -bool VorbisPlayer::isPlaying() -{ - LOGV("isPlaying\n"); - if (mState == STATE_OPEN) { - return mRender; - } - return false; -} - -status_t VorbisPlayer::getCurrentPosition(int* position) -{ - LOGV("getCurrentPosition\n"); - Mutex::Autolock l(mMutex); - if (mState != STATE_OPEN) { - LOGE("getCurrentPosition(): file not open"); - return ERROR_NOT_OPEN; - } - *position = ov_time_tell(&mVorbisFile); - if (*position < 0) { - LOGE("getCurrentPosition(): ov_time_tell returned %d", *position); - return *position; - } - return NO_ERROR; -} - -status_t VorbisPlayer::getDuration(int* duration) -{ - LOGV("getDuration\n"); - Mutex::Autolock l(mMutex); - if (mState != STATE_OPEN) { - return ERROR_NOT_OPEN; - } - - int ret = ov_time_total(&mVorbisFile, -1); - if (ret == OV_EINVAL) { - return -1; - } - - *duration = ret; - return NO_ERROR; -} - -status_t VorbisPlayer::release() -{ - LOGV("release\n"); - Mutex::Autolock l(mMutex); - reset_nosync(); - - // TODO: timeout when thread won't exit - // wait for render thread to exit - if (mRenderTid > 0) { - mExit = true; - mCondition.signal(); - mCondition.wait(mMutex); - } - return NO_ERROR; -} - -status_t VorbisPlayer::reset() -{ - LOGV("reset\n"); - Mutex::Autolock l(mMutex); - if (mState != STATE_OPEN) { - return NO_ERROR; - } - return reset_nosync(); -} - -// always call with lock held -status_t VorbisPlayer::reset_nosync() -{ - // close file - ov_clear(&mVorbisFile); // this also closes the FILE - if (mFile != NULL) { - LOGV("OOPS! Vorbis didn't close the file"); - fclose(mFile); - } - mState = STATE_ERROR; - - mPlayTime = -1; - mDuration = -1; - mLoop = false; - mAndroidLoop = false; - mPaused = false; - mRender = false; - return NO_ERROR; -} - -status_t VorbisPlayer::setLooping(int loop) -{ - LOGV("setLooping\n"); - Mutex::Autolock l(mMutex); - mLoop = (loop != 0); - return NO_ERROR; -} - -status_t VorbisPlayer::createOutputTrack() { - // open audio track - vorbis_info *vi = ov_info(&mVorbisFile, -1); - - LOGV("Create AudioTrack object: rate=%ld, channels=%d\n", - vi->rate, vi->channels); - if (mAudioSink->open(vi->rate, vi->channels, AudioSystem::PCM_16_BIT, DEFAULT_AUDIOSINK_BUFFERCOUNT) != NO_ERROR) { - LOGE("mAudioSink open failed"); - return ERROR_OPEN_FAILED; - } - return NO_ERROR; -} - -int VorbisPlayer::renderThread(void* p) { - return ((VorbisPlayer*)p)->render(); -} - -#define AUDIOBUFFER_SIZE 4096 - -int VorbisPlayer::render() { - int result = -1; - int temp; - int current_section = 0; - bool audioStarted = false; - - LOGV("render\n"); - - // allocate render buffer - mAudioBuffer = new char[AUDIOBUFFER_SIZE]; - if (!mAudioBuffer) { - LOGE("mAudioBuffer allocate failed\n"); - goto threadExit; - } - - // let main thread know we're ready - { - Mutex::Autolock l(mMutex); - mRenderTid = myTid(); - mCondition.signal(); - } - - while (1) { - long numread = 0; - { - Mutex::Autolock l(mMutex); - - // pausing? - if (mPaused) { - if (mAudioSink->ready()) mAudioSink->pause(); - mRender = false; - audioStarted = false; - } - - // nothing to render, wait for client thread to wake us up - if (!mExit && !mRender) { - LOGV("render - signal wait\n"); - mCondition.wait(mMutex); - LOGV("render - signal rx'd\n"); - } - if (mExit) break; - - // We could end up here if start() is called, and before we get a - // chance to run, the app calls stop() or reset(). Re-check render - // flag so we don't try to render in stop or reset state. - if (!mRender) continue; - - // render vorbis data into the input buffer - numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, ¤t_section); - if (numread == 0) { - // end of file, do we need to loop? - // ... - if (mLoop || mAndroidLoop) { - ov_time_seek(&mVorbisFile, 0); - current_section = 0; - numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, ¤t_section); - } else { - mAudioSink->stop(); - audioStarted = false; - mRender = false; - mPaused = true; - int endpos = ov_time_tell(&mVorbisFile); - - LOGV("send MEDIA_PLAYBACK_COMPLETE"); - sendEvent(MEDIA_PLAYBACK_COMPLETE); - - // wait until we're started again - LOGV("playback complete - wait for signal"); - mCondition.wait(mMutex); - LOGV("playback complete - signal rx'd"); - if (mExit) break; - - // if we're still at the end, restart from the beginning - if (mState == STATE_OPEN) { - int curpos = ov_time_tell(&mVorbisFile); - if (curpos == endpos) { - ov_time_seek(&mVorbisFile, 0); - } - current_section = 0; - numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, ¤t_section); - } - } - } - } - - // codec returns negative number on error - if (numread < 0) { - LOGE("Error in Vorbis decoder"); - sendEvent(MEDIA_ERROR); - break; - } - - // create audio output track if necessary - if (!mAudioSink->ready()) { - LOGV("render - create output track\n"); - if (createOutputTrack() != NO_ERROR) - break; - } - - // Write data to the audio hardware - if ((temp = mAudioSink->write(mAudioBuffer, numread)) < 0) { - LOGE("Error in writing:%d",temp); - result = temp; - break; - } - - // start audio output if necessary - if (!audioStarted && !mPaused && !mExit) { - LOGV("render - starting audio\n"); - mAudioSink->start(); - audioStarted = true; - } - } - -threadExit: - mAudioSink.clear(); - if (mAudioBuffer) { - delete [] mAudioBuffer; - mAudioBuffer = NULL; - } - - // tell main thread goodbye - Mutex::Autolock l(mMutex); - mRenderTid = -1; - mCondition.signal(); - return result; -} - -} // end namespace android diff --git a/media/libmediaplayerservice/VorbisPlayer.h b/media/libmediaplayerservice/VorbisPlayer.h deleted file mode 100644 index c30dc1b..0000000 --- a/media/libmediaplayerservice/VorbisPlayer.h +++ /dev/null @@ -1,91 +0,0 @@ -/* -** -** Copyright 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_VORBISPLAYER_H -#define ANDROID_VORBISPLAYER_H - -#include - -#include -#include - -#include "ivorbiscodec.h" -#include "ivorbisfile.h" - -#define ANDROID_LOOP_TAG "ANDROID_LOOP" - -namespace android { - -class VorbisPlayer : public MediaPlayerInterface { -public: - VorbisPlayer(); - ~VorbisPlayer(); - - virtual void onFirstRef(); - virtual status_t initCheck(); - virtual status_t setDataSource(const char* path); - virtual status_t setDataSource(int fd, int64_t offset, int64_t length); - virtual status_t setVideoSurface(const sp& surface) { return UNKNOWN_ERROR; } - virtual status_t prepare(); - virtual status_t prepareAsync(); - virtual status_t start(); - virtual status_t stop(); - virtual status_t seekTo(int msec); - virtual status_t pause(); - virtual bool isPlaying(); - virtual status_t getCurrentPosition(int* msec); - virtual status_t getDuration(int* msec); - virtual status_t release(); - virtual status_t reset(); - virtual status_t setLooping(int loop); - virtual player_type playerType() { return VORBIS_PLAYER; } - -private: - status_t setdatasource(const char *path, int fd, int64_t offset, int64_t length); - status_t reset_nosync(); - status_t createOutputTrack(); - static int renderThread(void*); - int render(); - - static size_t vp_fread(void *, size_t, size_t, void *); - static int vp_fseek(void *, ogg_int64_t, int); - static int vp_fclose(void *); - static long vp_ftell(void *); - - Mutex mMutex; - Condition mCondition; - FILE* mFile; - int64_t mOffset; - int64_t mLength; - OggVorbis_File mVorbisFile; - char* mAudioBuffer; - int mPlayTime; - int mDuration; - status_t mState; - int mStreamType; - bool mLoop; - bool mAndroidLoop; - volatile bool mExit; - bool mPaused; - volatile bool mRender; - pid_t mRenderTid; -}; - -}; // namespace android - -#endif // ANDROID_VORBISPLAYER_H - diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk deleted file mode 100644 index c681698..0000000 --- a/media/mediaserver/Android.mk +++ /dev/null @@ -1,22 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - main_mediaserver.cpp - -LOCAL_SHARED_LIBRARIES := \ - libaudioflinger \ - libcameraservice \ - libmediaplayerservice \ - libutils - -base := $(LOCAL_PATH)/../.. - -LOCAL_C_INCLUDES := \ - $(base)/libs/audioflinger \ - $(base)/camera/libcameraservice \ - $(base)/media/libmediaplayerservice - -LOCAL_MODULE:= mediaserver - -include $(BUILD_EXECUTABLE) diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp deleted file mode 100644 index 6954b63..0000000 --- a/media/mediaserver/main_mediaserver.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* -** -** Copyright 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. -*/ - -// System headers required for setgroups, etc. -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -using namespace android; - -int main(int argc, char** argv) -{ - sp proc(ProcessState::self()); - sp sm = defaultServiceManager(); - LOGI("ServiceManager: %p", sm.get()); - AudioFlinger::instantiate(); - MediaPlayerService::instantiate(); - CameraService::instantiate(); - ProcessState::self()->startThreadPool(); - IPCThreadState::self()->joinThreadPool(); -} -- cgit v1.1 From 89fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Tue, 3 Mar 2009 19:31:44 -0800 Subject: auto import from //depot/cupcake/@135843 --- include/media/AudioRecord.h | 344 ++++++ include/media/AudioSystem.h | 177 +++ include/media/AudioTrack.h | 419 +++++++ include/media/IAudioFlinger.h | 141 +++ include/media/IAudioFlingerClient.h | 55 + include/media/IAudioRecord.h | 68 ++ include/media/IAudioTrack.h | 84 ++ include/media/IMediaMetadataRetriever.h | 56 + include/media/IMediaPlayer.h | 64 ++ include/media/IMediaPlayerClient.h | 48 + include/media/IMediaPlayerService.h | 60 + include/media/IMediaRecorder.h | 70 ++ include/media/JetPlayer.h | 107 ++ include/media/MediaMetadataRetrieverInterface.h | 52 + include/media/MediaPlayerInterface.h | 126 +++ include/media/PVMediaRecorder.h | 65 ++ include/media/PVMetadataRetriever.h | 51 + include/media/PVPlayer.h | 81 ++ include/media/ToneGenerator.h | 176 +++ include/media/mediametadataretriever.h | 95 ++ include/media/mediaplayer.h | 144 +++ include/media/mediarecorder.h | 155 +++ include/media/mediascanner.h | 85 ++ include/media/thread_init.h | 25 + include/private/media/AudioTrackShared.h | 83 ++ include/private/media/VideoFrame.h | 127 +++ include/private/opengles/gl_context.h | 632 +++++++++++ include/private/ui/LayerState.h | 75 ++ include/private/ui/SharedState.h | 168 +++ include/private/ui/SurfaceFlingerSynchro.h | 76 ++ include/private/utils/Static.h | 58 + include/private/utils/binder_module.h | 148 +++ include/private/utils/futex_synchro.h | 60 + media/libmedia/Android.mk | 39 + media/libmedia/AudioRecord.cpp | 574 ++++++++++ media/libmedia/AudioSystem.cpp | 383 +++++++ media/libmedia/AudioTrack.cpp | 1021 +++++++++++++++++ media/libmedia/IAudioFlinger.cpp | 553 +++++++++ media/libmedia/IAudioFlingerClient.cpp | 77 ++ media/libmedia/IAudioRecord.cpp | 100 ++ media/libmedia/IAudioTrack.cpp | 140 +++ media/libmedia/IMediaMetadataRetriever.cpp | 218 ++++ media/libmedia/IMediaPlayer.cpp | 275 +++++ media/libmedia/IMediaPlayerClient.cpp | 77 ++ media/libmedia/IMediaPlayerService.cpp | 198 ++++ media/libmedia/IMediaRecorder.cpp | 417 +++++++ media/libmedia/JetPlayer.cpp | 489 ++++++++ media/libmedia/MODULE_LICENSE_APACHE2 | 0 media/libmedia/NOTICE | 190 ++++ media/libmedia/ToneGenerator.cpp | 730 ++++++++++++ media/libmedia/mediametadataretriever.cpp | 188 ++++ media/libmedia/mediaplayer.cpp | 624 +++++++++++ media/libmedia/mediarecorder.cpp | 617 ++++++++++ media/libmediaplayerservice/Android.mk | 36 + media/libmediaplayerservice/MediaPlayerService.cpp | 1173 ++++++++++++++++++++ media/libmediaplayerservice/MediaPlayerService.h | 238 ++++ .../libmediaplayerservice/MediaRecorderClient.cpp | 273 +++++ media/libmediaplayerservice/MediaRecorderClient.h | 66 ++ .../MetadataRetrieverClient.cpp | 250 +++++ .../MetadataRetrieverClient.h | 71 ++ media/libmediaplayerservice/MidiFile.cpp | 558 ++++++++++ media/libmediaplayerservice/MidiFile.h | 77 ++ media/libmediaplayerservice/VorbisPlayer.cpp | 529 +++++++++ media/libmediaplayerservice/VorbisPlayer.h | 91 ++ media/mediaserver/Android.mk | 22 + media/mediaserver/main_mediaserver.cpp | 45 + 66 files changed, 14514 insertions(+) create mode 100644 include/media/AudioRecord.h create mode 100644 include/media/AudioSystem.h create mode 100644 include/media/AudioTrack.h create mode 100644 include/media/IAudioFlinger.h create mode 100644 include/media/IAudioFlingerClient.h create mode 100644 include/media/IAudioRecord.h create mode 100644 include/media/IAudioTrack.h create mode 100644 include/media/IMediaMetadataRetriever.h create mode 100644 include/media/IMediaPlayer.h create mode 100644 include/media/IMediaPlayerClient.h create mode 100644 include/media/IMediaPlayerService.h create mode 100644 include/media/IMediaRecorder.h create mode 100644 include/media/JetPlayer.h create mode 100644 include/media/MediaMetadataRetrieverInterface.h create mode 100644 include/media/MediaPlayerInterface.h create mode 100644 include/media/PVMediaRecorder.h create mode 100644 include/media/PVMetadataRetriever.h create mode 100644 include/media/PVPlayer.h create mode 100644 include/media/ToneGenerator.h create mode 100644 include/media/mediametadataretriever.h create mode 100644 include/media/mediaplayer.h create mode 100644 include/media/mediarecorder.h create mode 100644 include/media/mediascanner.h create mode 100644 include/media/thread_init.h create mode 100644 include/private/media/AudioTrackShared.h create mode 100644 include/private/media/VideoFrame.h create mode 100644 include/private/opengles/gl_context.h create mode 100644 include/private/ui/LayerState.h create mode 100644 include/private/ui/SharedState.h create mode 100644 include/private/ui/SurfaceFlingerSynchro.h create mode 100644 include/private/utils/Static.h create mode 100644 include/private/utils/binder_module.h create mode 100644 include/private/utils/futex_synchro.h create mode 100644 media/libmedia/Android.mk create mode 100644 media/libmedia/AudioRecord.cpp create mode 100644 media/libmedia/AudioSystem.cpp create mode 100644 media/libmedia/AudioTrack.cpp create mode 100644 media/libmedia/IAudioFlinger.cpp create mode 100644 media/libmedia/IAudioFlingerClient.cpp create mode 100644 media/libmedia/IAudioRecord.cpp create mode 100644 media/libmedia/IAudioTrack.cpp create mode 100644 media/libmedia/IMediaMetadataRetriever.cpp create mode 100644 media/libmedia/IMediaPlayer.cpp create mode 100644 media/libmedia/IMediaPlayerClient.cpp create mode 100644 media/libmedia/IMediaPlayerService.cpp create mode 100644 media/libmedia/IMediaRecorder.cpp create mode 100644 media/libmedia/JetPlayer.cpp create mode 100644 media/libmedia/MODULE_LICENSE_APACHE2 create mode 100644 media/libmedia/NOTICE create mode 100644 media/libmedia/ToneGenerator.cpp create mode 100644 media/libmedia/mediametadataretriever.cpp create mode 100644 media/libmedia/mediaplayer.cpp create mode 100644 media/libmedia/mediarecorder.cpp create mode 100644 media/libmediaplayerservice/Android.mk create mode 100644 media/libmediaplayerservice/MediaPlayerService.cpp create mode 100644 media/libmediaplayerservice/MediaPlayerService.h create mode 100644 media/libmediaplayerservice/MediaRecorderClient.cpp create mode 100644 media/libmediaplayerservice/MediaRecorderClient.h create mode 100644 media/libmediaplayerservice/MetadataRetrieverClient.cpp create mode 100644 media/libmediaplayerservice/MetadataRetrieverClient.h create mode 100644 media/libmediaplayerservice/MidiFile.cpp create mode 100644 media/libmediaplayerservice/MidiFile.h create mode 100644 media/libmediaplayerservice/VorbisPlayer.cpp create mode 100644 media/libmediaplayerservice/VorbisPlayer.h create mode 100644 media/mediaserver/Android.mk create mode 100644 media/mediaserver/main_mediaserver.cpp diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h new file mode 100644 index 0000000..ff64855 --- /dev/null +++ b/include/media/AudioRecord.h @@ -0,0 +1,344 @@ +/* + * 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 AUDIORECORD_H_ +#define AUDIORECORD_H_ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + + +namespace android { + +// ---------------------------------------------------------------------------- + +class AudioRecord +{ +public: + + enum stream_type { + DEFAULT_INPUT =-1, + MIC_INPUT = 0, + NUM_STREAM_TYPES + }; + + static const int DEFAULT_SAMPLE_RATE = 8000; + + /* Events used by AudioRecord callback function (callback_t). + * + * to keep in sync with frameworks/base/media/java/android/media/AudioRecord.java + */ + enum event_type { + EVENT_MORE_DATA = 0, // Request to reqd more data from PCM buffer. + EVENT_OVERRUN = 1, // PCM buffer overrun occured. + EVENT_MARKER = 2, // Record head is at the specified marker position + // (See setMarkerPosition()). + EVENT_NEW_POS = 3, // Record head is at a new position + // (See setPositionUpdatePeriod()). + }; + + /* Create Buffer on the stack and pass it to obtainBuffer() + * and releaseBuffer(). + */ + + class Buffer + { + public: + enum { + MUTE = 0x00000001 + }; + uint32_t flags; + int channelCount; + int format; + size_t frameCount; + size_t size; + union { + void* raw; + short* i16; + int8_t* i8; + }; + }; + + /* These are static methods to control the system-wide AudioFlinger + * only privileged processes can have access to them + */ + +// static status_t setMasterMute(bool mute); + + /* As a convenience, if a callback is supplied, a handler thread + * is automatically created with the appropriate priority. This thread + * invokes the callback when a new buffer becomes ready or an overrun condition occurs. + * Parameters: + * + * event: type of event notified (see enum AudioRecord::event_type). + * user: Pointer to context for use by the callback receiver. + * info: Pointer to optional parameter according to event type: + * - EVENT_MORE_DATA: pointer to AudioRecord::Buffer struct. The callback must not read + * more bytes than indicated by 'size' field and update 'size' if less bytes are + * read. + * - EVENT_OVERRUN: unused. + * - EVENT_MARKER: pointer to an uin32_t containing the marker position in frames. + * - EVENT_NEW_POS: pointer to an uin32_t containing the new position in frames. + */ + + typedef void (*callback_t)(int event, void* user, void *info); + + /* Constructs an uninitialized AudioRecord. No connection with + * AudioFlinger takes place. + */ + AudioRecord(); + + /* Creates an AudioRecord track and registers it with AudioFlinger. + * Once created, the track needs to be started before it can be used. + * Unspecified values are set to the audio hardware's current + * values. + * + * Parameters: + * + * streamType: Select the audio input to record to (e.g. AudioRecord::MIC_INPUT). + * sampleRate: Track sampling rate in Hz. + * format: PCM sample format (e.g AudioSystem::PCM_16_BIT for signed + * 16 bits per sample). + * channelCount: Number of PCM channels (e.g 2 for stereo). + * frameCount: Total size of track PCM buffer in frames. This defines the + * latency of the track. + * flags: A bitmask of acoustic values from enum record_flags. It enables + * AGC, NS, and IIR. + * cbf: Callback function. If not null, this function is called periodically + * to provide new PCM data. + * notificationFrames: The callback function is called each time notificationFrames PCM + * frames are ready in record track output buffer. + * user Context for use by the callback receiver. + */ + + enum record_flags { + RECORD_AGC_ENABLE = AudioSystem::AGC_ENABLE, + RECORD_NS_ENABLE = AudioSystem::NS_ENABLE, + RECORD_IIR_ENABLE = AudioSystem::TX_IIR_ENABLE + }; + + AudioRecord(int streamType, + uint32_t sampleRate = 0, + int format = 0, + int channelCount = 0, + int frameCount = 0, + uint32_t flags = 0, + callback_t cbf = 0, + void* user = 0, + int notificationFrames = 0); + + + /* Terminates the AudioRecord and unregisters it from AudioFlinger. + * Also destroys all resources assotiated with the AudioRecord. + */ + ~AudioRecord(); + + + /* Initialize an uninitialized AudioRecord. + * Returned status (from utils/Errors.h) can be: + * - NO_ERROR: successful intialization + * - INVALID_OPERATION: AudioRecord is already intitialized or record device is already in use + * - BAD_VALUE: invalid parameter (channelCount, format, sampleRate...) + * - NO_INIT: audio server or audio hardware not initialized + * - PERMISSION_DENIED: recording is not allowed for the requesting process + * */ + status_t set(int streamType = 0, + uint32_t sampleRate = 0, + int format = 0, + int channelCount = 0, + int frameCount = 0, + uint32_t flags = 0, + callback_t cbf = 0, + void* user = 0, + int notificationFrames = 0, + bool threadCanCallJava = false); + + + /* Result of constructing the AudioRecord. This must be checked + * before using any AudioRecord API (except for set()), using + * an uninitialized AudioRecord produces undefined results. + * See set() method above for possible return codes. + */ + status_t initCheck() const; + + /* Returns this track's latency in milliseconds. + * This includes the latency due to AudioRecord buffer size + * and audio hardware driver. + */ + uint32_t latency() const; + + /* getters, see constructor */ + + uint32_t sampleRate() const; + int format() const; + int channelCount() const; + uint32_t frameCount() const; + int frameSize() const; + + + /* After it's created the track is not active. Call start() to + * make it active. If set, the callback will start being called. + */ + status_t start(); + + /* Stop a track. If set, the callback will cease being called and + * obtainBuffer returns STOPPED. Note that obtainBuffer() still works + * and will fill up buffers until the pool is exhausted. + */ + status_t stop(); + bool stopped() const; + + /* get sample rate for this track + */ + uint32_t getSampleRate(); + + /* Sets marker position. When record reaches the number of frames specified, + * a callback with event type EVENT_MARKER is called. Calling setMarkerPosition + * with marker == 0 cancels marker notification callback. + * If the AudioRecord has been opened with no callback function associated, + * the operation will fail. + * + * Parameters: + * + * marker: marker position expressed in frames. + * + * Returned status (from utils/Errors.h) can be: + * - NO_ERROR: successful operation + * - INVALID_OPERATION: the AudioRecord has no callback installed. + */ + status_t setMarkerPosition(uint32_t marker); + status_t getMarkerPosition(uint32_t *marker); + + + /* Sets position update period. Every time the number of frames specified has been recorded, + * a callback with event type EVENT_NEW_POS is called. + * Calling setPositionUpdatePeriod with updatePeriod == 0 cancels new position notification + * callback. + * If the AudioRecord has been opened with no callback function associated, + * the operation will fail. + * + * Parameters: + * + * updatePeriod: position update notification period expressed in frames. + * + * Returned status (from utils/Errors.h) can be: + * - NO_ERROR: successful operation + * - INVALID_OPERATION: the AudioRecord has no callback installed. + */ + status_t setPositionUpdatePeriod(uint32_t updatePeriod); + status_t getPositionUpdatePeriod(uint32_t *updatePeriod); + + + /* Gets record head position. The position is the total number of frames + * recorded since record start. + * + * Parameters: + * + * position: Address where to return record head position within AudioRecord buffer. + * + * Returned status (from utils/Errors.h) can be: + * - NO_ERROR: successful operation + * - BAD_VALUE: position is NULL + */ + status_t getPosition(uint32_t *position); + + + + /* obtains a buffer of "frameCount" frames. The buffer must be + * filled entirely. If the track is stopped, obtainBuffer() returns + * STOPPED instead of NO_ERROR as long as there are buffers availlable, + * at which point NO_MORE_BUFFERS is returned. + * Buffers will be returned until the pool (buffercount()) + * is exhausted, at which point obtainBuffer() will either block + * or return WOULD_BLOCK depending on the value of the "blocking" + * parameter. + */ + + enum { + NO_MORE_BUFFERS = 0x80000001, + STOPPED = 1 + }; + + status_t obtainBuffer(Buffer* audioBuffer, int32_t waitCount); + void releaseBuffer(Buffer* audioBuffer); + + + /* As a convenience we provide a read() interface to the audio buffer. + * This is implemented on top of lockBuffer/unlockBuffer. + */ + ssize_t read(void* buffer, size_t size); + +private: + /* copying audio tracks is not allowed */ + AudioRecord(const AudioRecord& other); + AudioRecord& operator = (const AudioRecord& other); + + /* a small internal class to handle the callback */ + class ClientRecordThread : public Thread + { + public: + ClientRecordThread(AudioRecord& receiver, bool bCanCallJava = false); + private: + friend class AudioRecord; + virtual bool threadLoop(); + virtual status_t readyToRun() { return NO_ERROR; } + virtual void onFirstRef() {} + AudioRecord& mReceiver; + Mutex mLock; + }; + + bool processAudioBuffer(const sp& thread); + + sp mAudioFlinger; + sp mAudioRecord; + sp mCblkMemory; + sp mClientRecordThread; + Mutex mRecordThreadLock; + + uint32_t mSampleRate; + uint32_t mFrameCount; + + audio_track_cblk_t* mCblk; + uint8_t mFormat; + uint8_t mChannelCount; + uint8_t mReserved[2]; + status_t mStatus; + uint32_t mLatency; + + volatile int32_t mActive; + + callback_t mCbf; + void* mUserData; + uint32_t mNotificationFrames; + uint32_t mRemainingFrames; + uint32_t mMarkerPosition; + uint32_t mNewPosition; + uint32_t mUpdatePeriod; +}; + +}; // namespace android + +#endif /*AUDIORECORD_H_*/ diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h new file mode 100644 index 0000000..77c90ba --- /dev/null +++ b/include/media/AudioSystem.h @@ -0,0 +1,177 @@ +/* + * 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_AUDIOSYSTEM_H_ +#define ANDROID_AUDIOSYSTEM_H_ + +#include +#include +#include + +namespace android { + +typedef void (*audio_error_callback)(status_t err); + +class AudioSystem +{ +public: + + enum stream_type { + DEFAULT =-1, + VOICE_CALL = 0, + SYSTEM = 1, + RING = 2, + MUSIC = 3, + ALARM = 4, + NOTIFICATION = 5, + BLUETOOTH_SCO = 6, + NUM_STREAM_TYPES + }; + + enum audio_output_type { + AUDIO_OUTPUT_DEFAULT =-1, + AUDIO_OUTPUT_HARDWARE = 0, + AUDIO_OUTPUT_A2DP = 1, + NUM_AUDIO_OUTPUT_TYPES + }; + + enum audio_format { + FORMAT_DEFAULT = 0, + PCM_16_BIT, + PCM_8_BIT, + INVALID_FORMAT + }; + + enum audio_mode { + MODE_INVALID = -2, + MODE_CURRENT = -1, + MODE_NORMAL = 0, + MODE_RINGTONE, + MODE_IN_CALL, + NUM_MODES // not a valid entry, denotes end-of-list + }; + + enum audio_routes { + ROUTE_EARPIECE = (1 << 0), + ROUTE_SPEAKER = (1 << 1), + ROUTE_BLUETOOTH_SCO = (1 << 2), + ROUTE_HEADSET = (1 << 3), + ROUTE_BLUETOOTH_A2DP = (1 << 4), + ROUTE_ALL = -1UL, + }; + + enum audio_in_acoustics { + AGC_ENABLE = 0x0001, + AGC_DISABLE = 0, + NS_ENABLE = 0x0002, + NS_DISABLE = 0, + TX_IIR_ENABLE = 0x0004, + TX_DISABLE = 0 + }; + + /* These are static methods to control the system-wide AudioFlinger + * only privileged processes can have access to them + */ + + // routing helper functions + static status_t speakerphone(bool state); + static status_t isSpeakerphoneOn(bool* state); + static status_t bluetoothSco(bool state); + static status_t isBluetoothScoOn(bool* state); + static status_t muteMicrophone(bool state); + static status_t isMicrophoneMuted(bool *state); + + static status_t setMasterVolume(float value); + static status_t setMasterMute(bool mute); + static status_t getMasterVolume(float* volume); + static status_t getMasterMute(bool* mute); + + static status_t setStreamVolume(int stream, float value); + static status_t setStreamMute(int stream, bool mute); + static status_t getStreamVolume(int stream, float* volume); + static status_t getStreamMute(int stream, bool* mute); + + static status_t setMode(int mode); + static status_t getMode(int* mode); + + static status_t setRouting(int mode, uint32_t routes, uint32_t mask); + static status_t getRouting(int mode, uint32_t* routes); + + static status_t isMusicActive(bool *state); + + // Temporary interface, do not use + // TODO: Replace with a more generic key:value get/set mechanism + static status_t setParameter(const char* key, const char* value); + + static void setErrorCallback(audio_error_callback cb); + + // helper function to obtain AudioFlinger service handle + static const sp& get_audio_flinger(); + + static float linearToLog(int volume); + static int logToLinear(float volume); + + static status_t getOutputSamplingRate(int* samplingRate, int stream = DEFAULT); + static status_t getOutputFrameCount(int* frameCount, int stream = DEFAULT); + static status_t getOutputLatency(uint32_t* latency, int stream = DEFAULT); + + static bool routedToA2dpOutput(int streamType); + + static status_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount, + size_t* buffSize); + + // ---------------------------------------------------------------------------- + +private: + + class AudioFlingerClient: public IBinder::DeathRecipient, public BnAudioFlingerClient + { + public: + AudioFlingerClient() { + } + + // DeathRecipient + virtual void binderDied(const wp& who); + + // IAudioFlingerClient + virtual void a2dpEnabledChanged(bool enabled); + + }; + static int getOutput(int streamType); + + static sp gAudioFlingerClient; + + friend class AudioFlingerClient; + + static Mutex gLock; + static sp gAudioFlinger; + static audio_error_callback gAudioErrorCallback; + static int gOutSamplingRate[NUM_AUDIO_OUTPUT_TYPES]; + static int gOutFrameCount[NUM_AUDIO_OUTPUT_TYPES]; + static uint32_t gOutLatency[NUM_AUDIO_OUTPUT_TYPES]; + static bool gA2dpEnabled; + + static size_t gInBuffSize; + // previous parameters for recording buffer size queries + static uint32_t gPrevInSamplingRate; + static int gPrevInFormat; + static int gPrevInChannelCount; + +}; + +}; // namespace android + +#endif /*ANDROID_AUDIOSYSTEM_H_*/ diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h new file mode 100644 index 0000000..659f5f8 --- /dev/null +++ b/include/media/AudioTrack.h @@ -0,0 +1,419 @@ +/* + * Copyright (C) 2007 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_AUDIOTRACK_H +#define ANDROID_AUDIOTRACK_H + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + + +namespace android { + +// ---------------------------------------------------------------------------- + +class audio_track_cblk_t; + +// ---------------------------------------------------------------------------- + +class AudioTrack +{ +public: + enum channel_index { + MONO = 0, + LEFT = 0, + RIGHT = 1 + }; + + /* Events used by AudioTrack callback function (audio_track_cblk_t). + */ + enum event_type { + EVENT_MORE_DATA = 0, // Request to write more data to PCM buffer. + EVENT_UNDERRUN = 1, // PCM buffer underrun occured. + EVENT_LOOP_END = 2, // Sample loop end was reached; playback restarted from loop start if loop count was not 0. + EVENT_MARKER = 3, // Playback head is at the specified marker position (See setMarkerPosition()). + EVENT_NEW_POS = 4, // Playback head is at a new position (See setPositionUpdatePeriod()). + EVENT_BUFFER_END = 5 // Playback head is at the end of the buffer. + }; + + /* Create Buffer on the stack and pass it to obtainBuffer() + * and releaseBuffer(). + */ + + class Buffer + { + public: + enum { + MUTE = 0x00000001 + }; + uint32_t flags; + int channelCount; + int format; + size_t frameCount; + size_t size; + union { + void* raw; + short* i16; + int8_t* i8; + }; + }; + + + /* As a convenience, if a callback is supplied, a handler thread + * is automatically created with the appropriate priority. This thread + * invokes the callback when a new buffer becomes availlable or an underrun condition occurs. + * Parameters: + * + * event: type of event notified (see enum AudioTrack::event_type). + * user: Pointer to context for use by the callback receiver. + * info: Pointer to optional parameter according to event type: + * - EVENT_MORE_DATA: pointer to AudioTrack::Buffer struct. The callback must not write + * more bytes than indicated by 'size' field and update 'size' if less bytes are + * written. + * - EVENT_UNDERRUN: unused. + * - EVENT_LOOP_END: pointer to an int indicating the number of loops remaining. + * - EVENT_MARKER: pointer to an uin32_t containing the marker position in frames. + * - EVENT_NEW_POS: pointer to an uin32_t containing the new position in frames. + * - EVENT_BUFFER_END: unused. + */ + + typedef void (*callback_t)(int event, void* user, void *info); + + /* Constructs an uninitialized AudioTrack. No connection with + * AudioFlinger takes place. + */ + AudioTrack(); + + /* Creates an audio track and registers it with AudioFlinger. + * Once created, the track needs to be started before it can be used. + * Unspecified values are set to the audio hardware's current + * values. + * + * Parameters: + * + * streamType: Select the type of audio stream this track is attached to + * (e.g. AudioSystem::MUSIC). + * sampleRate: Track sampling rate in Hz. + * format: PCM sample format (e.g AudioSystem::PCM_16_BIT for signed + * 16 bits per sample). + * channelCount: Number of PCM channels (e.g 2 for stereo). + * frameCount: Total size of track PCM buffer in frames. This defines the + * latency of the track. + * flags: Reserved for future use. + * cbf: Callback function. If not null, this function is called periodically + * to request new PCM data. + * notificationFrames: The callback function is called each time notificationFrames PCM + * frames have been comsumed from track input buffer. + * user Context for use by the callback receiver. + */ + + AudioTrack( int streamType, + uint32_t sampleRate = 0, + int format = 0, + int channelCount = 0, + int frameCount = 0, + uint32_t flags = 0, + callback_t cbf = 0, + void* user = 0, + int notificationFrames = 0); + + /* Creates an audio track and registers it with AudioFlinger. With this constructor, + * The PCM data to be rendered by AudioTrack is passed in a shared memory buffer + * identified by the argument sharedBuffer. This prototype is for static buffer playback. + * PCM data must be present into memory before the AudioTrack is started. + * The Write() and Flush() methods are not supported in this case. + * It is recommented to pass a callback function to be notified of playback end by an + * EVENT_UNDERRUN event. + */ + + AudioTrack( int streamType, + uint32_t sampleRate = 0, + int format = 0, + int channelCount = 0, + const sp& sharedBuffer = 0, + uint32_t flags = 0, + callback_t cbf = 0, + void* user = 0, + int notificationFrames = 0); + + /* Terminates the AudioTrack and unregisters it from AudioFlinger. + * Also destroys all resources assotiated with the AudioTrack. + */ + ~AudioTrack(); + + + /* Initialize an uninitialized AudioTrack. + * Returned status (from utils/Errors.h) can be: + * - NO_ERROR: successful intialization + * - INVALID_OPERATION: AudioTrack is already intitialized + * - BAD_VALUE: invalid parameter (channelCount, format, sampleRate...) + * - NO_INIT: audio server or audio hardware not initialized + * */ + status_t set(int streamType =-1, + uint32_t sampleRate = 0, + int format = 0, + int channelCount = 0, + int frameCount = 0, + uint32_t flags = 0, + callback_t cbf = 0, + void* user = 0, + int notificationFrames = 0, + const sp& sharedBuffer = 0, + bool threadCanCallJava = false); + + + /* Result of constructing the AudioTrack. This must be checked + * before using any AudioTrack API (except for set()), using + * an uninitialized AudioTrack produces undefined results. + * See set() method above for possible return codes. + */ + status_t initCheck() const; + + /* Returns this track's latency in milliseconds. + * This includes the latency due to AudioTrack buffer size, AudioMixer (if any) + * and audio hardware driver. + */ + uint32_t latency() const; + + /* getters, see constructor */ + + int streamType() const; + uint32_t sampleRate() const; + int format() const; + int channelCount() const; + uint32_t frameCount() const; + int frameSize() const; + sp& sharedBuffer(); + + + /* After it's created the track is not active. Call start() to + * make it active. If set, the callback will start being called. + */ + void start(); + + /* Stop a track. If set, the callback will cease being called and + * obtainBuffer returns STOPPED. Note that obtainBuffer() still works + * and will fill up buffers until the pool is exhausted. + */ + void stop(); + bool stopped() const; + + /* flush a stopped track. All pending buffers are discarded. + * This function has no effect if the track is not stoped. + */ + void flush(); + + /* Pause a track. If set, the callback will cease being called and + * obtainBuffer returns STOPPED. Note that obtainBuffer() still works + * and will fill up buffers until the pool is exhausted. + */ + void pause(); + + /* mute or unmutes this track. + * While mutted, the callback, if set, is still called. + */ + void mute(bool); + bool muted() const; + + + /* set volume for this track, mostly used for games' sound effects + */ + void setVolume(float left, float right); + void getVolume(float* left, float* right); + + /* set sample rate for this track, mostly used for games' sound effects + */ + void setSampleRate(int sampleRate); + uint32_t getSampleRate(); + + /* Enables looping and sets the start and end points of looping. + * + * Parameters: + * + * loopStart: loop start expressed as the number of PCM frames played since AudioTrack start. + * loopEnd: loop end expressed as the number of PCM frames played since AudioTrack start. + * loopCount: number of loops to execute. Calling setLoop() with loopCount == 0 cancels any pending or + * active loop. loopCount = -1 means infinite looping. + * + * For proper operation the following condition must be respected: + * (loopEnd-loopStart) <= framecount() + */ + status_t setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount); + status_t getLoop(uint32_t *loopStart, uint32_t *loopEnd, int *loopCount); + + + /* Sets marker position. When playback reaches the number of frames specified, a callback with event + * type EVENT_MARKER is called. Calling setMarkerPosition with marker == 0 cancels marker notification + * callback. + * If the AudioTrack has been opened with no callback function associated, the operation will fail. + * + * Parameters: + * + * marker: marker position expressed in frames. + * + * Returned status (from utils/Errors.h) can be: + * - NO_ERROR: successful operation + * - INVALID_OPERATION: the AudioTrack has no callback installed. + */ + status_t setMarkerPosition(uint32_t marker); + status_t getMarkerPosition(uint32_t *marker); + + + /* Sets position update period. Every time the number of frames specified has been played, + * a callback with event type EVENT_NEW_POS is called. + * Calling setPositionUpdatePeriod with updatePeriod == 0 cancels new position notification + * callback. + * If the AudioTrack has been opened with no callback function associated, the operation will fail. + * + * Parameters: + * + * updatePeriod: position update notification period expressed in frames. + * + * Returned status (from utils/Errors.h) can be: + * - NO_ERROR: successful operation + * - INVALID_OPERATION: the AudioTrack has no callback installed. + */ + status_t setPositionUpdatePeriod(uint32_t updatePeriod); + status_t getPositionUpdatePeriod(uint32_t *updatePeriod); + + + /* Sets playback head position within AudioTrack buffer. The new position is specified + * in number of frames. + * This method must be called with the AudioTrack in paused or stopped state. + * Note that the actual position set is modulo the AudioTrack buffer size in frames. + * Therefore using this method makes sense only when playing a "static" audio buffer + * as opposed to streaming. + * The getPosition() method on the other hand returns the total number of frames played since + * playback start. + * + * Parameters: + * + * position: New playback head position within AudioTrack buffer. + * + * Returned status (from utils/Errors.h) can be: + * - NO_ERROR: successful operation + * - INVALID_OPERATION: the AudioTrack is not stopped. + * - BAD_VALUE: The specified position is beyond the number of frames present in AudioTrack buffer + */ + status_t setPosition(uint32_t position); + status_t getPosition(uint32_t *position); + + /* Forces AudioTrack buffer full condition. When playing a static buffer, this method avoids + * rewriting the buffer before restarting playback after a stop. + * This method must be called with the AudioTrack in paused or stopped state. + * + * Returned status (from utils/Errors.h) can be: + * - NO_ERROR: successful operation + * - INVALID_OPERATION: the AudioTrack is not stopped. + */ + status_t reload(); + + /* obtains a buffer of "frameCount" frames. The buffer must be + * filled entirely. If the track is stopped, obtainBuffer() returns + * STOPPED instead of NO_ERROR as long as there are buffers availlable, + * at which point NO_MORE_BUFFERS is returned. + * Buffers will be returned until the pool (buffercount()) + * is exhausted, at which point obtainBuffer() will either block + * or return WOULD_BLOCK depending on the value of the "blocking" + * parameter. + */ + + enum { + NO_MORE_BUFFERS = 0x80000001, + STOPPED = 1 + }; + + status_t obtainBuffer(Buffer* audioBuffer, int32_t waitCount); + void releaseBuffer(Buffer* audioBuffer); + + + /* As a convenience we provide a write() interface to the audio buffer. + * This is implemented on top of lockBuffer/unlockBuffer. For best + * performance + * + */ + ssize_t write(const void* buffer, size_t size); + + /* + * Dumps the state of an audio track. + */ + status_t dump(int fd, const Vector& args) const; + +private: + /* copying audio tracks is not allowed */ + AudioTrack(const AudioTrack& other); + AudioTrack& operator = (const AudioTrack& other); + + /* a small internal class to handle the callback */ + class AudioTrackThread : public Thread + { + public: + AudioTrackThread(AudioTrack& receiver, bool bCanCallJava = false); + private: + friend class AudioTrack; + virtual bool threadLoop(); + virtual status_t readyToRun(); + virtual void onFirstRef(); + AudioTrack& mReceiver; + Mutex mLock; + }; + + bool processAudioBuffer(const sp& thread); + + sp mAudioFlinger; + sp mAudioTrack; + sp mCblkMemory; + sp mAudioTrackThread; + + float mVolume[2]; + uint32_t mSampleRate; + uint32_t mFrameCount; + + audio_track_cblk_t* mCblk; + uint8_t mStreamType; + uint8_t mFormat; + uint8_t mChannelCount; + uint8_t mMuted; + status_t mStatus; + uint32_t mLatency; + + volatile int32_t mActive; + + callback_t mCbf; + void* mUserData; + uint32_t mNotificationFrames; + sp mSharedBuffer; + int mLoopCount; + uint32_t mRemainingFrames; + uint32_t mMarkerPosition; + uint32_t mNewPosition; + uint32_t mUpdatePeriod; +}; + + +}; // namespace android + +#endif // ANDROID_AUDIOTRACK_H diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h new file mode 100644 index 0000000..6f13fe0 --- /dev/null +++ b/include/media/IAudioFlinger.h @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2007 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_IAUDIOFLINGER_H +#define ANDROID_IAUDIOFLINGER_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +namespace android { + +// ---------------------------------------------------------------------------- + +class IAudioFlinger : public IInterface +{ +public: + DECLARE_META_INTERFACE(AudioFlinger); + + /* create an audio track and registers it with AudioFlinger. + * return null if the track cannot be created. + */ + virtual sp createTrack( + pid_t pid, + int streamType, + uint32_t sampleRate, + int format, + int channelCount, + int frameCount, + uint32_t flags, + const sp& sharedBuffer, + status_t *status) = 0; + + virtual sp openRecord( + pid_t pid, + int streamType, + uint32_t sampleRate, + int format, + int channelCount, + int frameCount, + uint32_t flags, + status_t *status) = 0; + + /* query the audio hardware state. This state never changes, + * and therefore can be cached. + */ + virtual uint32_t sampleRate(int output) const = 0; + virtual int channelCount(int output) const = 0; + virtual int format(int output) const = 0; + virtual size_t frameCount(int output) const = 0; + virtual uint32_t latency(int output) const = 0; + + /* set/get the audio hardware state. This will probably be used by + * the preference panel, mostly. + */ + virtual status_t setMasterVolume(float value) = 0; + virtual status_t setMasterMute(bool muted) = 0; + + virtual float masterVolume() const = 0; + virtual bool masterMute() const = 0; + + /* set/get stream type state. This will probably be used by + * the preference panel, mostly. + */ + virtual status_t setStreamVolume(int stream, float value) = 0; + virtual status_t setStreamMute(int stream, bool muted) = 0; + + virtual float streamVolume(int stream) const = 0; + virtual bool streamMute(int stream) const = 0; + + // set/get audio routing + virtual status_t setRouting(int mode, uint32_t routes, uint32_t mask) = 0; + virtual uint32_t getRouting(int mode) const = 0; + + // set/get audio mode + virtual status_t setMode(int mode) = 0; + virtual int getMode() const = 0; + + // mic mute/state + virtual status_t setMicMute(bool state) = 0; + virtual bool getMicMute() const = 0; + + // is a music stream active? + virtual bool isMusicActive() const = 0; + + // pass a generic configuration parameter to libaudio + // Temporary interface, do not use + // TODO: Replace with a more generic key:value get/set mechanism + virtual status_t setParameter(const char* key, const char* value) = 0; + + // register a current process for audio output change notifications + virtual void registerClient(const sp& client) = 0; + + // retrieve the audio recording buffer size + virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount) = 0; + + // force AudioFlinger thread out of standby + virtual void wakeUp() = 0; + + // is A2DP output enabled + virtual bool isA2dpEnabled() const = 0; +}; + + +// ---------------------------------------------------------------------------- + +class BnAudioFlinger : public BnInterface +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +// ---------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_IAUDIOFLINGER_H diff --git a/include/media/IAudioFlingerClient.h b/include/media/IAudioFlingerClient.h new file mode 100644 index 0000000..c3deb0b --- /dev/null +++ b/include/media/IAudioFlingerClient.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2009 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_IAUDIOFLINGERCLIENT_H +#define ANDROID_IAUDIOFLINGERCLIENT_H + + +#include +#include + + +namespace android { + +// ---------------------------------------------------------------------------- + +class IAudioFlingerClient : public IInterface +{ +public: + DECLARE_META_INTERFACE(AudioFlingerClient); + + // Notifies a change of audio output from/to hardware to/from A2DP. + virtual void a2dpEnabledChanged(bool enabled) = 0; + +}; + + +// ---------------------------------------------------------------------------- + +class BnAudioFlingerClient : public BnInterface +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +// ---------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_IAUDIOFLINGERCLIENT_H diff --git a/include/media/IAudioRecord.h b/include/media/IAudioRecord.h new file mode 100644 index 0000000..9d45d2d --- /dev/null +++ b/include/media/IAudioRecord.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2007 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 IAUDIORECORD_H_ +#define IAUDIORECORD_H_ + +#include +#include + +#include +#include +#include +#include + + +namespace android { + +// ---------------------------------------------------------------------------- + +class IAudioRecord : public IInterface +{ +public: + DECLARE_META_INTERFACE(AudioRecord); + + /* After it's created the track is not active. Call start() to + * make it active. If set, the callback will start being called. + */ + virtual status_t start() = 0; + + /* Stop a track. If set, the callback will cease being called and + * obtainBuffer will return an error. Buffers that are already released + * will be processed, unless flush() is called. + */ + virtual void stop() = 0; + + /* get this tracks control block */ + virtual sp getCblk() const = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnAudioRecord : public BnInterface +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +// ---------------------------------------------------------------------------- + +}; // namespace android + +#endif /*IAUDIORECORD_H_*/ diff --git a/include/media/IAudioTrack.h b/include/media/IAudioTrack.h new file mode 100644 index 0000000..12f2111 --- /dev/null +++ b/include/media/IAudioTrack.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2007 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_IAUDIOTRACK_H +#define ANDROID_IAUDIOTRACK_H + +#include +#include + +#include +#include +#include +#include + + +namespace android { + +// ---------------------------------------------------------------------------- + +class IAudioTrack : public IInterface +{ +public: + DECLARE_META_INTERFACE(AudioTrack); + + /* After it's created the track is not active. Call start() to + * make it active. If set, the callback will start being called. + */ + virtual status_t start() = 0; + + /* Stop a track. If set, the callback will cease being called and + * obtainBuffer will return an error. Buffers that are already released + * will be processed, unless flush() is called. + */ + virtual void stop() = 0; + + /* flush a stopped track. All pending buffers are discarded. + * This function has no effect if the track is not stoped. + */ + virtual void flush() = 0; + + /* mute or unmutes this track. + * While mutted, the callback, if set, is still called. + */ + virtual void mute(bool) = 0; + + /* Pause a track. If set, the callback will cease being called and + * obtainBuffer will return an error. Buffers that are already released + * will be processed, unless flush() is called. + */ + virtual void pause() = 0; + + /* get this tracks control block */ + virtual sp getCblk() const = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnAudioTrack : public BnInterface +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +// ---------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_IAUDIOTRACK_H diff --git a/include/media/IMediaMetadataRetriever.h b/include/media/IMediaMetadataRetriever.h new file mode 100644 index 0000000..c677e83 --- /dev/null +++ b/include/media/IMediaMetadataRetriever.h @@ -0,0 +1,56 @@ +/* +** +** 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_IMEDIAMETADATARETRIEVER_H +#define ANDROID_IMEDIAMETADATARETRIEVER_H + +#include +#include +#include +#include + +namespace android { + +class IMediaMetadataRetriever: public IInterface +{ +public: + DECLARE_META_INTERFACE(MediaMetadataRetriever); + virtual void disconnect() = 0; + virtual status_t setDataSource(const char* srcUrl) = 0; + virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; + virtual status_t setMode(int mode) = 0; + virtual status_t getMode(int* mode) const = 0; + virtual sp captureFrame() = 0; + virtual sp extractAlbumArt() = 0; + virtual const char* extractMetadata(int keyCode) = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnMediaMetadataRetriever: public BnInterface +{ +public: + virtual status_t onTransact(uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +}; // namespace android + +#endif // ANDROID_IMEDIAMETADATARETRIEVER_H + diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h new file mode 100644 index 0000000..a683e74 --- /dev/null +++ b/include/media/IMediaPlayer.h @@ -0,0 +1,64 @@ +/* + * 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_IMEDIAPLAYER_H +#define ANDROID_IMEDIAPLAYER_H + +#include +#include +#include + +namespace android { + +class ISurface; + +class IMediaPlayer: public IInterface +{ +public: + DECLARE_META_INTERFACE(MediaPlayer); + + virtual void disconnect() = 0; + + virtual status_t setVideoSurface(const sp& surface) = 0; + virtual status_t prepareAsync() = 0; + virtual status_t start() = 0; + virtual status_t stop() = 0; + virtual status_t pause() = 0; + virtual status_t isPlaying(bool* state) = 0; + virtual status_t seekTo(int msec) = 0; + virtual status_t getCurrentPosition(int* msec) = 0; + virtual status_t getDuration(int* msec) = 0; + virtual status_t reset() = 0; + virtual status_t setAudioStreamType(int type) = 0; + virtual status_t setLooping(int loop) = 0; + virtual status_t setVolume(float leftVolume, float rightVolume) = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnMediaPlayer: public BnInterface +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +}; // namespace android + +#endif // ANDROID_IMEDIAPLAYER_H + diff --git a/include/media/IMediaPlayerClient.h b/include/media/IMediaPlayerClient.h new file mode 100644 index 0000000..5d32811 --- /dev/null +++ b/include/media/IMediaPlayerClient.h @@ -0,0 +1,48 @@ +/* + * 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_IMEDIAPLAYERCLIENT_H +#define ANDROID_IMEDIAPLAYERCLIENT_H + +#include +#include +#include + +namespace android { + +class IMediaPlayerClient: public IInterface +{ +public: + DECLARE_META_INTERFACE(MediaPlayerClient); + + virtual void notify(int msg, int ext1, int ext2) = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnMediaPlayerClient: public BnInterface +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +}; // namespace android + +#endif // ANDROID_IMEDIAPLAYERCLIENT_H + diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h new file mode 100644 index 0000000..8125cc9 --- /dev/null +++ b/include/media/IMediaPlayerService.h @@ -0,0 +1,60 @@ +/* + * 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_IMEDIAPLAYERSERVICE_H +#define ANDROID_IMEDIAPLAYERSERVICE_H + +#include +#include +#include + +#include +#include +#include + +namespace android { + +class IMediaRecorder; + +class IMediaPlayerService: public IInterface +{ +public: + DECLARE_META_INTERFACE(MediaPlayerService); + + virtual sp createMediaRecorder(pid_t pid) = 0; + virtual sp createMetadataRetriever(pid_t pid) = 0; + + virtual sp create(pid_t pid, const sp& client, const char* url) = 0; + virtual sp create(pid_t pid, const sp& client, int fd, int64_t offset, int64_t length) = 0; + virtual sp decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0; + virtual sp decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnMediaPlayerService: public BnInterface +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +}; // namespace android + +#endif // ANDROID_IMEDIAPLAYERSERVICE_H + diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h new file mode 100644 index 0000000..eace996 --- /dev/null +++ b/include/media/IMediaRecorder.h @@ -0,0 +1,70 @@ +/* + ** + ** 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_IMEDIARECORDER_H +#define ANDROID_IMEDIARECORDER_H + +#include + +namespace android { + +class ISurface; +class ICamera; +class IMediaPlayerClient; + +class IMediaRecorder: public IInterface +{ +public: + DECLARE_META_INTERFACE(MediaRecorder); + + virtual status_t setCamera(const sp& camera) = 0; + virtual status_t setPreviewSurface(const sp& surface) = 0; + virtual status_t setVideoSource(int vs) = 0; + virtual status_t setAudioSource(int as) = 0; + virtual status_t setOutputFormat(int of) = 0; + virtual status_t setVideoEncoder(int ve) = 0; + virtual status_t setAudioEncoder(int ae) = 0; + virtual status_t setOutputFile(const char* path) = 0; + virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0; + virtual status_t setVideoSize(int width, int height) = 0; + virtual status_t setVideoFrameRate(int frames_per_second) = 0; + virtual status_t setListener(const sp& listener) = 0; + virtual status_t prepare() = 0; + virtual status_t getMaxAmplitude(int* max) = 0; + virtual status_t start() = 0; + virtual status_t stop() = 0; + virtual status_t reset() = 0; + virtual status_t init() = 0; + virtual status_t close() = 0; + virtual status_t release() = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnMediaRecorder: public BnInterface +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +}; // namespace android + +#endif // ANDROID_IMEDIARECORDER_H + diff --git a/include/media/JetPlayer.h b/include/media/JetPlayer.h new file mode 100644 index 0000000..16764a9 --- /dev/null +++ b/include/media/JetPlayer.h @@ -0,0 +1,107 @@ +/* + * 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 JETPLAYER_H_ +#define JETPLAYER_H_ + +#include +#include + +#include +#include +#include "AudioTrack.h" + + +namespace android { + +typedef void (*jetevent_callback)(int eventType, int val1, int val2, void *cookie); + +class JetPlayer { + +public: + + // to keep in sync with the JetPlayer class constants + // defined in frameworks/base/media/java/android/media/JetPlayer.java + static const int JET_EVENT = 1; + static const int JET_USERID_UPDATE = 2; + static const int JET_NUMQUEUEDSEGMENT_UPDATE = 3; + static const int JET_PAUSE_UPDATE = 4; + + JetPlayer(jobject javaJetPlayer, + int maxTracks = 32, + int trackBufferSize = 1200); + ~JetPlayer(); + int init(); + int release(); + + int loadFromFile(const char* url); + int loadFromFD(const int fd, const long long offset, const long long length); + int closeFile(); + int play(); + int pause(); + int queueSegment(int segmentNum, int libNum, int repeatCount, int transpose, + EAS_U32 muteFlags, EAS_U8 userID); + int setMuteFlags(EAS_U32 muteFlags, bool sync); + int setMuteFlag(int trackNum, bool muteFlag, bool sync); + int triggerClip(int clipId); + int clearQueue(); + + void setEventCallback(jetevent_callback callback); + + int getMaxTracks() { return mMaxTracks; }; + + +private: + static int renderThread(void*); + int render(); + void fireUpdateOnStatusChange(); + void fireEventsFromJetQueue(); + + JetPlayer() {} // no default constructor + void dump(); + void dumpJetStatus(S_JET_STATUS* pJetStatus); + + jetevent_callback mEventCallback; + + jobject mJavaJetPlayerRef; + Mutex mMutex; // mutex to sync the render and playback thread with the JET calls + pid_t mTid; + Condition mCondition; + volatile bool mRender; + bool mPaused; + + EAS_STATE mState; + int* mMemFailedVar; + + int mMaxTracks; // max number of MIDI tracks, usually 32 + EAS_DATA_HANDLE mEasData; + EAS_FILE_LOCATOR mEasJetFileLoc; + EAS_PCM* mAudioBuffer;// EAS renders the MIDI data into this buffer, + AudioTrack* mAudioTrack; // and we play it in this audio track + int mTrackBufferSize; + S_JET_STATUS mJetStatus; + S_JET_STATUS mPreviousJetStatus; + + char mJetFilePath[256]; + + +}; // end class JetPlayer + +} // end namespace android + + + +#endif /*JETPLAYER_H_*/ diff --git a/include/media/MediaMetadataRetrieverInterface.h b/include/media/MediaMetadataRetrieverInterface.h new file mode 100644 index 0000000..b178836 --- /dev/null +++ b/include/media/MediaMetadataRetrieverInterface.h @@ -0,0 +1,52 @@ +/* +** +** 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_MEDIAMETADATARETRIEVERINTERFACE_H +#define ANDROID_MEDIAMETADATARETRIEVERINTERFACE_H + +#include +#include +#include + +namespace android { + +// Abstract base class +class MediaMetadataRetrieverBase : public RefBase +{ +public: + MediaMetadataRetrieverBase() {} + virtual ~MediaMetadataRetrieverBase() {} + virtual status_t setDataSource(const char *url) = 0; + virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; + virtual status_t setMode(int mode) = 0; + virtual status_t getMode(int* mode) const = 0; + virtual VideoFrame* captureFrame() = 0; + virtual MediaAlbumArt* extractAlbumArt() = 0; + virtual const char* extractMetadata(int keyCode) = 0; +}; + +// MediaMetadataRetrieverInterface +class MediaMetadataRetrieverInterface : public MediaMetadataRetrieverBase +{ +public: + virtual ~MediaMetadataRetrieverInterface() {} +}; + +}; // namespace android + +#endif // ANDROID_MEDIAMETADATARETRIEVERINTERFACE_H + diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h new file mode 100644 index 0000000..7f0e7b3 --- /dev/null +++ b/include/media/MediaPlayerInterface.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2007 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_MEDIAPLAYERINTERFACE_H +#define ANDROID_MEDIAPLAYERINTERFACE_H + +#ifdef __cplusplus + +#include +#include + +#include +#include + +namespace android { + +enum player_type { + PV_PLAYER = 1, + SONIVOX_PLAYER = 2, + VORBIS_PLAYER = 3 +}; + +#define DEFAULT_AUDIOSINK_BUFFERCOUNT 4 +#define DEFAULT_AUDIOSINK_BUFFERSIZE 1200 +#define DEFAULT_AUDIOSINK_SAMPLERATE 44100 + + +// callback mechanism for passing messages to MediaPlayer object +typedef void (*notify_callback_f)(void* cookie, int msg, int ext1, int ext2); + +// abstract base class - use MediaPlayerInterface +class MediaPlayerBase : public RefBase +{ +public: + + // AudioSink: abstraction layer for audio output + class AudioSink : public RefBase { + public: + virtual ~AudioSink() {} + virtual bool ready() const = 0; // audio output is open and ready + virtual bool realtime() const = 0; // audio output is real-time output + virtual ssize_t bufferSize() const = 0; + virtual ssize_t frameCount() const = 0; + virtual ssize_t channelCount() const = 0; + virtual ssize_t frameSize() const = 0; + virtual uint32_t latency() const = 0; + virtual float msecsPerFrame() const = 0; + virtual status_t open(uint32_t sampleRate, int channelCount, int format=AudioSystem::PCM_16_BIT, int bufferCount=DEFAULT_AUDIOSINK_BUFFERCOUNT) = 0; + virtual void start() = 0; + virtual ssize_t write(const void* buffer, size_t size) = 0; + virtual void stop() = 0; + virtual void flush() = 0; + virtual void pause() = 0; + virtual void close() = 0; + }; + + MediaPlayerBase() : mCookie(0), mNotify(0) {} + virtual ~MediaPlayerBase() {} + virtual status_t initCheck() = 0; + virtual bool hardwareOutput() = 0; + virtual status_t setDataSource(const char *url) = 0; + virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; + virtual status_t setVideoSurface(const sp& surface) = 0; + virtual status_t prepare() = 0; + virtual status_t prepareAsync() = 0; + virtual status_t start() = 0; + virtual status_t stop() = 0; + virtual status_t pause() = 0; + virtual bool isPlaying() = 0; + virtual status_t seekTo(int msec) = 0; + virtual status_t getCurrentPosition(int *msec) = 0; + virtual status_t getDuration(int *msec) = 0; + virtual status_t reset() = 0; + virtual status_t setLooping(int loop) = 0; + virtual player_type playerType() = 0; + virtual void setNotifyCallback(void* cookie, notify_callback_f notifyFunc) { + mCookie = cookie; mNotify = notifyFunc; } + +protected: + virtual void sendEvent(int msg, int ext1=0, int ext2=0) { if (mNotify) mNotify(mCookie, msg, ext1, ext2); } + + void* mCookie; + notify_callback_f mNotify; +}; + +// Implement this class for media players that use the AudioFlinger software mixer +class MediaPlayerInterface : public MediaPlayerBase +{ +public: + virtual ~MediaPlayerInterface() { } + virtual bool hardwareOutput() { return false; } + virtual void setAudioSink(const sp& audioSink) { mAudioSink = audioSink; } +protected: + sp mAudioSink; +}; + +// Implement this class for media players that output directo to hardware +class MediaPlayerHWInterface : public MediaPlayerBase +{ +public: + virtual ~MediaPlayerHWInterface() {} + virtual bool hardwareOutput() { return true; } + virtual status_t setVolume(float leftVolume, float rightVolume) = 0; + virtual status_t setAudioStreamType(int streamType) = 0; +}; + +}; // namespace android + +#endif // __cplusplus + + +#endif // ANDROID_MEDIAPLAYERINTERFACE_H + diff --git a/include/media/PVMediaRecorder.h b/include/media/PVMediaRecorder.h new file mode 100644 index 0000000..3315c59 --- /dev/null +++ b/include/media/PVMediaRecorder.h @@ -0,0 +1,65 @@ +/* + ** + ** 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_PVMEDIARECORDER_H +#define ANDROID_PVMEDIARECORDER_H + +#include +#include + +namespace android { + +class ISurface; +class ICamera; +class AuthorDriverWrapper; + +class PVMediaRecorder +{ +public: + PVMediaRecorder(); + ~PVMediaRecorder(); + + status_t init(); + status_t setAudioSource(audio_source as); + status_t setVideoSource(video_source vs); + status_t setOutputFormat(output_format of); + status_t setAudioEncoder(audio_encoder ae); + status_t setVideoEncoder(video_encoder ve); + status_t setVideoSize(int width, int height); + status_t setVideoFrameRate(int frames_per_second); + status_t setCamera(const sp& camera); + status_t setPreviewSurface(const sp& surface); + status_t setOutputFile(const char *path); + status_t setOutputFile(int fd, int64_t offset, int64_t length); + status_t setListener(const sp& listener); + status_t prepare(); + status_t start(); + status_t stop(); + status_t close(); + status_t reset(); + status_t getMaxAmplitude(int *max); + +private: + status_t doStop(); + + AuthorDriverWrapper* mAuthorDriverWrapper; +}; + +}; // namespace android + +#endif // ANDROID_PVMEDIARECORDER_H + diff --git a/include/media/PVMetadataRetriever.h b/include/media/PVMetadataRetriever.h new file mode 100644 index 0000000..c202dfe --- /dev/null +++ b/include/media/PVMetadataRetriever.h @@ -0,0 +1,51 @@ +/* +** +** 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_PVMETADATARETRIEVER_H +#define ANDROID_PVMETADATARETRIEVER_H + +#include +#include +#include + +namespace android { + +class MetadataDriver; + +class PVMetadataRetriever : public MediaMetadataRetrieverInterface +{ +public: + PVMetadataRetriever(); + virtual ~PVMetadataRetriever(); + + 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 VideoFrame* captureFrame(); + virtual MediaAlbumArt* extractAlbumArt(); + virtual const char* extractMetadata(int keyCode); + +private: + mutable Mutex mLock; + MetadataDriver* mMetadataDriver; + char* mDataSourcePath; +}; + +}; // namespace android + +#endif // ANDROID_PVMETADATARETRIEVER_H diff --git a/include/media/PVPlayer.h b/include/media/PVPlayer.h new file mode 100644 index 0000000..6d98852 --- /dev/null +++ b/include/media/PVPlayer.h @@ -0,0 +1,81 @@ +/* + * 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_PVPLAYER_H +#define ANDROID_PVPLAYER_H + +#include +#include + +#define MAX_OPENCORE_INSTANCES 25 + +#ifdef MAX_OPENCORE_INSTANCES +#include +#endif + +class PlayerDriver; + +namespace android { + +class PVPlayer : public MediaPlayerInterface +{ +public: + PVPlayer(); + virtual ~PVPlayer(); + + virtual status_t initCheck(); + virtual status_t setDataSource(const char *url); + virtual status_t setDataSource(int fd, int64_t offset, int64_t length); + virtual status_t setVideoSurface(const sp& surface); + virtual status_t prepare(); + virtual status_t prepareAsync(); + virtual status_t start(); + virtual status_t stop(); + virtual status_t pause(); + virtual bool isPlaying(); + virtual status_t seekTo(int msec); + virtual status_t getCurrentPosition(int *msec); + virtual status_t getDuration(int *msec); + virtual status_t reset(); + virtual status_t setLooping(int loop); + virtual player_type playerType() { return PV_PLAYER; } + + // make available to PlayerDriver + void sendEvent(int msg, int ext1=0, int ext2=0) { MediaPlayerBase::sendEvent(msg, ext1, ext2); } + +private: + static void do_nothing(status_t s, void *cookie, bool cancelled) { } + static void run_init(status_t s, void *cookie, bool cancelled); + static void run_set_video_surface(status_t s, void *cookie, bool cancelled); + static void run_set_audio_output(status_t s, void *cookie, bool cancelled); + static void run_prepare(status_t s, void *cookie, bool cancelled); + + PlayerDriver* mPlayerDriver; + char * mDataSourcePath; + bool mIsDataSourceSet; + sp mSurface; + int mSharedFd; + status_t mInit; + int mDuration; + +#ifdef MAX_OPENCORE_INSTANCES + static volatile int32_t sNumInstances; +#endif +}; + +}; // namespace android + +#endif // ANDROID_PVPLAYER_H diff --git a/include/media/ToneGenerator.h b/include/media/ToneGenerator.h new file mode 100644 index 0000000..ec64e4d --- /dev/null +++ b/include/media/ToneGenerator.h @@ -0,0 +1,176 @@ +/* + * 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_TONEGENERATOR_H_ +#define ANDROID_TONEGENERATOR_H_ + +#include +#include +#include +#include +#include + +namespace android { + +class ToneGenerator { +public: + + // List of all available tones + // This enum must be kept consistant with constants in ToneGenerator JAVA class + enum tone_type { + // DTMF tones ITU-T Recommendation Q.23 + TONE_DTMF_0 = 0, // 0 key: 1336Hz, 941Hz + TONE_DTMF_1, // 1 key: 1209Hz, 697Hz + TONE_DTMF_2, // 2 key: 1336Hz, 697Hz + TONE_DTMF_3, // 3 key: 1477Hz, 697Hz + TONE_DTMF_4, // 4 key: 1209Hz, 770Hz + TONE_DTMF_5, // 5 key: 1336Hz, 770Hz + TONE_DTMF_6, // 6 key: 1477Hz, 770Hz + TONE_DTMF_7, // 7 key: 1209Hz, 852Hz + TONE_DTMF_8, // 8 key: 1336Hz, 852Hz + TONE_DTMF_9, // 9 key: 1477Hz, 852Hz + TONE_DTMF_S, // * key: 1209Hz, 941Hz + TONE_DTMF_P, // # key: 1477Hz, 941Hz + TONE_DTMF_A, // A key: 1633Hz, 697Hz + TONE_DTMF_B, // B key: 1633Hz, 770Hz + TONE_DTMF_C, // C key: 1633Hz, 852Hz + TONE_DTMF_D, // D key: 1633Hz, 941Hz + // Call supervisory tones: 3GPP TS 22.001 (CEPT) + TONE_SUP_DIAL, // Dial tone: 425Hz, continuous + TONE_SUP_BUSY, // Busy tone: 425Hz, 500ms ON, 500ms OFF... + TONE_SUP_CONGESTION, // Congestion tone: 425Hz, 200ms ON, 200ms OFF... + TONE_SUP_RADIO_ACK, // Radio path acknowlegment: 425Hz, 200ms ON + TONE_SUP_RADIO_NOTAVAIL, // Radio path not available: 425Hz, 200ms ON, 200 OFF 3 bursts + TONE_SUP_ERROR, // Error/Special info: 950Hz+1400Hz+1800Hz, 330ms ON, 1s OFF... + TONE_SUP_CALL_WAITING, // Call Waiting: 425Hz, 200ms ON, 600ms OFF, 200ms ON, 3s OFF... + TONE_SUP_RINGTONE, // Ring Tone: 425Hz, 1s ON, 4s OFF... + // Proprietary tones: 3GPP TS 31.111 + TONE_PROP_BEEP, // General beep: 400Hz+1200Hz, 35ms ON + TONE_PROP_ACK, // Positive Acknowlgement: 1200Hz, 100ms ON, 100ms OFF 2 bursts + TONE_PROP_NACK, // Negative Acknowlgement: 300Hz+400Hz+500Hz, 400ms ON + TONE_PROP_PROMPT, // Prompt tone: 400Hz+1200Hz, 200ms ON + TONE_PROP_BEEP2, // General double beep: 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms on + NUM_TONES + }; + + ToneGenerator(int streamType, float volume); + ~ToneGenerator(); + + bool startTone(int toneType); + void stopTone(); + + bool isInited() { return (mState == TONE_IDLE)?false:true;} + +private: + + enum tone_state { + TONE_IDLE, // ToneGenerator is being initialized or initialization failed + TONE_INIT, // ToneGenerator has been successfully initialized and is not playing + TONE_STARTING, // ToneGenerator is starting playing + TONE_PLAYING, // ToneGenerator is playing + TONE_STOPPING, // ToneGenerator is stoping + TONE_RESTARTING // + }; + + static const unsigned int TONEGEN_MAX_WAVES = 3; + static const unsigned int TONEGEN_MAX_SEGMENTS = 4; // Maximun number of elenemts in + static const unsigned int TONEGEN_INF = 0xFFFFFFFF; // Represents infinite time duration + static const float TONEGEN_GAIN = 0.9; // Default gain passed to WaveGenerator(). + + // ToneDescriptor class contains all parameters needed to generate a tone: + // - The array waveFreq[] contains the frequencies of all individual waves making the multi-tone. + // The number of sine waves varies from 1 to TONEGEN_MAX_WAVES. + // The first null value indicates that no more waves are needed. + // - The array segments[] is used to generate the tone pulses. A segment is a period of time + // during which the tone is ON or OFF. Segments with even index (starting from 0) + // correspond to tone ON state and segments with odd index to OFF state. + // The data stored in segments[] is the duration of the corresponding period in ms. + // The first segment encountered with a 0 duration indicates that no more segment follows. + // - repeatCnt indicates the number of times the sequence described by segments[] array must be repeated. + // When the tone generator encounters the first 0 duration segment, it will compare repeatCnt to mCurCount. + // If mCurCount > repeatCnt, the tone is stopped automatically. + + class ToneDescriptor { + public: + unsigned short waveFreq[TONEGEN_MAX_WAVES+1]; + unsigned long segments[TONEGEN_MAX_SEGMENTS+1]; + unsigned long repeatCnt; + }; + + static const ToneDescriptor toneDescriptors[NUM_TONES]; + + unsigned int mTotalSmp; // Total number of audio samples played (gives current time) + unsigned int mNextSegSmp; // Position of next segment transition expressed in samples + // NOTE: because mTotalSmp, mNextSegSmp are stored on 32 bit, current design will operate properly + // only if tone duration is less than about 27 Hours(@44100Hz sampling rate). If this time is exceeded, + // no crash will occur but tone sequence will show a glitch. + + unsigned short mCurSegment; // Current segment index in ToneDescriptor segments[] + unsigned short mCurCount; // Current sequence repeat count + volatile unsigned short mState; // ToneGenerator state (tone_state) + const ToneDescriptor *mpToneDesc; // pointer to active tone descriptor + const ToneDescriptor *mpNewToneDesc; // pointer to next active tone descriptor + + int mSamplingRate; // AudioFlinger Sampling rate + AudioTrack *mpAudioTrack; // Pointer to audio track used for playback + Mutex mLock; // Mutex to control concurent access to ToneGenerator object from audio callback and application API + Mutex mCbkCondLock; // Mutex associated to mWaitCbkCond + Condition mWaitCbkCond; // condition enabling interface to wait for audio callback completion after a change is requested + float mVolume; // Volume applied to audio track + int mStreamType; // Audio stream used for output + unsigned int mProcessSize; // Size of audio blocks generated at a time by audioCallback() (in PCM frames). + + bool initAudioTrack(); + static void audioCallback(int event, void* user, void *info); + bool prepareWave(); + unsigned int numWaves(); + void clearWaveGens(); + + // WaveGenerator generates a single sine wave + class WaveGenerator { + public: + enum gen_command { + WAVEGEN_START, // Start/restart wave from phase 0 + WAVEGEN_CONT, // Continue wave from current phase + WAVEGEN_STOP // Stop wave on zero crossing + }; + + WaveGenerator(unsigned short samplingRate, unsigned short frequency, + float volume); + ~WaveGenerator(); + + void getSamples(short *outBuffer, unsigned int count, + unsigned int command); + + private: + static const short GEN_AMP = 32000; // amplitude of generator + static const short S_Q14 = 14; // shift for Q14 + static const short S_Q15 = 15; // shift for Q15 + + short mA1_Q14; // Q14 coefficient + // delay line of full amplitude generator + short mS1, mS2; // delay line S2 oldest + short mS2_0; // saved value for reinitialisation + short mAmplitude_Q15; // Q15 amplitude + }; + + Vector mWaveGens; // list of active wave generators. +}; + +} +; // namespace android + +#endif /*ANDROID_TONEGENERATOR_H_*/ diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h new file mode 100644 index 0000000..f2719d3 --- /dev/null +++ b/include/media/mediametadataretriever.h @@ -0,0 +1,95 @@ +/* + * 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 MEDIAMETADATARETRIEVER_H +#define MEDIAMETADATARETRIEVER_H + +#include // for status_t +#include +#include +#include + +namespace android { + +class IMediaPlayerService; +class IMediaMetadataRetriever; + +// Keep these in synch with the constants defined in MediaMetadataRetriever.java +// class. +enum { + METADATA_KEY_CD_TRACK_NUMBER = 0, + METADATA_KEY_ALBUM = 1, + METADATA_KEY_ARTIST = 2, + METADATA_KEY_AUTHOR = 3, + METADATA_KEY_COMPOSER = 4, + METADATA_KEY_DATE = 5, + METADATA_KEY_GENRE = 6, + METADATA_KEY_TITLE = 7, + METADATA_KEY_YEAR = 8, + METADATA_KEY_DURATION = 9, + METADATA_KEY_NUM_TRACKS = 10, + METADATA_KEY_IS_DRM_CRIPPLED = 11, + METADATA_KEY_CODEC = 12, + METADATA_KEY_RATING = 13, + METADATA_KEY_COMMENT = 14, + METADATA_KEY_COPYRIGHT = 15, + METADATA_KEY_BIT_RATE = 16, + METADATA_KEY_FRAME_RATE = 17, + METADATA_KEY_VIDEO_FORMAT = 18, + METADATA_KEY_VIDEO_HEIGHT = 19, + METADATA_KEY_VIDEO_WIDTH = 20, + // Add more here... +}; + + +class MediaMetadataRetriever: public RefBase +{ +public: + MediaMetadataRetriever(); + ~MediaMetadataRetriever(); + void disconnect(); + status_t setDataSource(const char* dataSourceUrl); + status_t setDataSource(int fd, int64_t offset, int64_t length); + status_t setMode(int mode); + status_t getMode(int* mode); + sp captureFrame(); + sp extractAlbumArt(); + const char* extractMetadata(int keyCode); + +private: + static const sp& getService(); + + class DeathNotifier: public IBinder::DeathRecipient + { + public: + DeathNotifier() {} + virtual ~DeathNotifier(); + virtual void binderDied(const wp& who); + }; + + static sp sDeathNotifier; + static Mutex sServiceLock; + static sp sService; + + Mutex mLock; + sp mRetriever; + +}; + +}; // namespace android + +#endif // MEDIAMETADATARETRIEVER_H diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h new file mode 100644 index 0000000..7288445 --- /dev/null +++ b/include/media/mediaplayer.h @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2007 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_MEDIAPLAYER_H +#define ANDROID_MEDIAPLAYER_H + +#include +#include +#include +#include +#include +#include + +namespace android { + +enum media_event_type { + MEDIA_NOP = 0, // interface test message + MEDIA_PREPARED = 1, + MEDIA_PLAYBACK_COMPLETE = 2, + MEDIA_BUFFERING_UPDATE = 3, + MEDIA_SEEK_COMPLETE = 4, + MEDIA_SET_VIDEO_SIZE = 5, + MEDIA_ERROR = 100, +}; + +typedef int media_error_type; +const media_error_type MEDIA_ERROR_UNKNOWN = 1; +const media_error_type MEDIA_ERROR_SERVER_DIED = 100; + +enum media_player_states { + MEDIA_PLAYER_STATE_ERROR = 0, + MEDIA_PLAYER_IDLE = 1 << 0, + MEDIA_PLAYER_INITIALIZED = 1 << 1, + MEDIA_PLAYER_PREPARING = 1 << 2, + MEDIA_PLAYER_PREPARED = 1 << 3, + MEDIA_PLAYER_STARTED = 1 << 4, + MEDIA_PLAYER_PAUSED = 1 << 5, + MEDIA_PLAYER_STOPPED = 1 << 6, + MEDIA_PLAYER_PLAYBACK_COMPLETE = 1 << 7 +}; + +// ---------------------------------------------------------------------------- +// ref-counted object for callbacks +class MediaPlayerListener: virtual public RefBase +{ +public: + virtual void notify(int msg, int ext1, int ext2) = 0; +}; + +class MediaPlayer : public BnMediaPlayerClient +{ +public: + MediaPlayer(); + ~MediaPlayer(); + void onFirstRef(); + void disconnect(); + status_t setDataSource(const char *url); + status_t setDataSource(int fd, int64_t offset, int64_t length); + status_t setVideoSurface(const sp& surface); + status_t setListener(const sp& listener); + status_t prepare(); + status_t prepareAsync(); + status_t start(); + status_t stop(); + status_t pause(); + bool isPlaying(); + status_t getVideoWidth(int *w); + status_t getVideoHeight(int *h); + status_t seekTo(int msec); + status_t getCurrentPosition(int *msec); + status_t getDuration(int *msec); + status_t reset(); + status_t setAudioStreamType(int type); + status_t setLooping(int loop); + bool isLooping(); + status_t setVolume(float leftVolume, float rightVolume); + void notify(int msg, int ext1, int ext2); + static sp decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat); + static sp decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat); + +private: + void clear_l(); + status_t seekTo_l(int msec); + status_t prepareAsync_l(); + status_t getDuration_l(int *msec); + status_t setDataSource(const sp& player); + + static const sp& getMediaPlayerService(); + static void addObitRecipient(const wp& recipient); + static void removeObitRecipient(const wp& recipient); + + class DeathNotifier: public IBinder::DeathRecipient + { + public: + DeathNotifier() {} + virtual ~DeathNotifier(); + + virtual void binderDied(const wp& who); + }; + + sp mPlayer; + Mutex mLock; + Mutex mNotifyLock; + Condition mSignal; + sp mListener; + void* mCookie; + media_player_states mCurrentState; + int mDuration; + int mCurrentPosition; + int mSeekPosition; + bool mPrepareSync; + status_t mPrepareStatus; + int mStreamType; + bool mLoop; + float mLeftVolume; + float mRightVolume; + int mVideoWidth; + int mVideoHeight; + + friend class DeathNotifier; + + static Mutex sServiceLock; + static sp sMediaPlayerService; + static sp sDeathNotifier; + static SortedVector< wp > sObitRecipients; +}; + +}; // namespace android + +#endif // ANDROID_MEDIAPLAYER_H + diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h new file mode 100644 index 0000000..8991f08 --- /dev/null +++ b/include/media/mediarecorder.h @@ -0,0 +1,155 @@ +/* + ** 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_MEDIARECORDER_H +#define ANDROID_MEDIARECORDER_H + +#include +#include + +namespace android { + +class Surface; +class IMediaRecorder; +class ICamera; + +typedef void (*media_completion_f)(status_t status, void *cookie); + +/* Do not change these values without updating their counterparts + * in java/android/android/media/MediaRecorder.java! + */ +enum audio_source { + AUDIO_SOURCE_DEFAULT = 0, + AUDIO_SOURCE_MIC = 1, +}; + +enum video_source { + VIDEO_SOURCE_DEFAULT = 0, + VIDEO_SOURCE_CAMERA = 1, +}; + +//Please update java/android/android/media/MediaRecorder.java if the following is updated. +enum output_format { + OUTPUT_FORMAT_DEFAULT = 0, + OUTPUT_FORMAT_THREE_GPP, + OUTPUT_FORMAT_MPEG_4, + OUTPUT_FORMAT_RAW_AMR, + OUTPUT_FORMAT_LIST_END // must be last - used to validate format type +}; + +enum audio_encoder { + AUDIO_ENCODER_DEFAULT = 0, + AUDIO_ENCODER_AMR_NB = 1, +}; + +enum video_encoder { + VIDEO_ENCODER_DEFAULT = 0, + VIDEO_ENCODER_H263 = 1, + VIDEO_ENCODER_H264 = 2, + VIDEO_ENCODER_MPEG_4_SP = 3, +}; + +// Maximum frames per second is 24 +#define MEDIA_RECORDER_MAX_FRAME_RATE 24 + +/* + * The state machine of the media_recorder uses a set of different state names. + * The mapping between the media_recorder and the pvauthorengine is shown below: + * + * mediarecorder pvauthorengine + * ---------------------------------------------------------------- + * MEDIA_RECORDER_ERROR ERROR + * MEDIA_RECORDER_IDLE IDLE + * MEDIA_RECORDER_INITIALIZED OPENED + * MEDIA_RECORDER_DATASOURCE_CONFIGURED + * MEDIA_RECORDER_PREPARED INITIALIZED + * MEDIA_RECORDER_RECORDING RECORDING + */ +enum media_recorder_states { + MEDIA_RECORDER_ERROR = 0, + MEDIA_RECORDER_IDLE = 1 << 0, + MEDIA_RECORDER_INITIALIZED = 1 << 1, + MEDIA_RECORDER_DATASOURCE_CONFIGURED = 1 << 2, + MEDIA_RECORDER_PREPARED = 1 << 3, + MEDIA_RECORDER_RECORDING = 1 << 4, +}; + +// The "msg" code passed to the listener in notify. +enum { + MEDIA_RECORDER_EVENT_ERROR = 1 +}; + +enum { + MEDIA_RECORDER_ERROR_UNKNOWN = 1 +}; + +// ---------------------------------------------------------------------------- +// ref-counted object for callbacks +class MediaRecorderListener: virtual public RefBase +{ +public: + virtual void notify(int msg, int ext1, int ext2) = 0; +}; + +class MediaRecorder : public BnMediaPlayerClient +{ +public: + MediaRecorder(); + ~MediaRecorder(); + + status_t initCheck(); + status_t setCamera(const sp& camera); + status_t setPreviewSurface(const sp& surface); + status_t setVideoSource(int vs); + status_t setAudioSource(int as); + status_t setOutputFormat(int of); + status_t setVideoEncoder(int ve); + status_t setAudioEncoder(int ae); + status_t setOutputFile(const char* path); + status_t setOutputFile(int fd, int64_t offset, int64_t length); + status_t setVideoSize(int width, int height); + status_t setVideoFrameRate(int frames_per_second); + status_t setListener(const sp& listener); + status_t prepare(); + status_t getMaxAmplitude(int* max); + status_t start(); + status_t stop(); + status_t reset(); + status_t init(); + status_t close(); + status_t release(); + void notify(int msg, int ext1, int ext2); + +private: + void doCleanUp(); + status_t doReset(); + + sp mMediaRecorder; + sp mListener; + media_recorder_states mCurrentState; + bool mIsAudioSourceSet; + bool mIsVideoSourceSet; + bool mIsAudioEncoderSet; + bool mIsVideoEncoderSet; + bool mIsOutputFileSet; + Mutex mLock; + Mutex mNotifyLock; +}; + +}; // namespace android + +#endif // ANDROID_MEDIARECORDER_H diff --git a/include/media/mediascanner.h b/include/media/mediascanner.h new file mode 100644 index 0000000..fbef1db --- /dev/null +++ b/include/media/mediascanner.h @@ -0,0 +1,85 @@ +/* + * 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 MEDIASCANNER_H +#define MEDIASCANNER_H + +#include +#include + +namespace android { + +class MediaScannerClient; +class StringArray; + +class MediaScanner +{ +public: + MediaScanner(); + ~MediaScanner(); + + typedef bool (*ExceptionCheck)(void* env); + + status_t processFile(const char *path, const char *mimeType, MediaScannerClient& client); + status_t processDirectory(const char *path, const char* extensions, + MediaScannerClient& client, ExceptionCheck exceptionCheck, void* exceptionEnv); + void setLocale(const char* locale); + + // extracts album art as a block of data + char* extractAlbumArt(int fd); + + static void uninitializeForThread(); + +private: + status_t doProcessDirectory(char *path, int pathRemaining, const char* extensions, + MediaScannerClient& client, ExceptionCheck exceptionCheck, void* exceptionEnv); + void initializeForThread(); + + // current locale (like "ja_JP"), created/destroyed with strdup()/free() + char* mLocale; +}; + + +class MediaScannerClient +{ +public: + MediaScannerClient(); + virtual ~MediaScannerClient(); + void setLocale(const char* locale); + void beginFile(); + bool addStringTag(const char* name, const char* value); + void endFile(); + + virtual bool scanFile(const char* path, long long lastModified, long long fileSize) = 0; + virtual bool handleStringTag(const char* name, const char* value) = 0; + virtual bool setMimeType(const char* mimeType) = 0; + +protected: + void convertValues(uint32_t encoding); + +protected: + // cached name and value strings, for native encoding support. + StringArray* mNames; + StringArray* mValues; + + // default encoding based on MediaScanner::mLocale string + uint32_t mLocaleEncoding; +}; + +}; // namespace android + +#endif // MEDIASCANNER_H + diff --git a/include/media/thread_init.h b/include/media/thread_init.h new file mode 100644 index 0000000..2c0c1f1 --- /dev/null +++ b/include/media/thread_init.h @@ -0,0 +1,25 @@ +/* + * 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 THREAD_INIT_H +#define THREAD_INIT_H + +bool InitializeForThread(); +void UninitializeForThread(); +void keydestructor(void*); + +#endif /* THREAD_INIT_H*/ + diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h new file mode 100644 index 0000000..1991aa7 --- /dev/null +++ b/include/private/media/AudioTrackShared.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2007 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_AUDIO_TRACK_SHARED_H +#define ANDROID_AUDIO_TRACK_SHARED_H + +#include +#include + +#include + +namespace android { + +// ---------------------------------------------------------------------------- + +#define MAX_SAMPLE_RATE 65535 +#define THREAD_PRIORITY_AUDIO_CLIENT (ANDROID_PRIORITY_AUDIO) +// Maximum cumulated timeout milliseconds before restarting audioflinger thread +#define MAX_STARTUP_TIMEOUT_MS 3000 // Longer timeout period at startup to cope with A2DP init time +#define MAX_RUN_TIMEOUT_MS 1000 +#define WAIT_PERIOD_MS 10 + + +struct audio_track_cblk_t +{ + + // The data members are grouped so that members accessed frequently and in the same context + // are in the same line of data cache. + Mutex lock; + Condition cv; + volatile uint32_t user; + volatile uint32_t server; + uint32_t userBase; + uint32_t serverBase; + void* buffers; + uint32_t frameCount; + // Cache line boundary + uint32_t loopStart; + uint32_t loopEnd; + int loopCount; + volatile union { + uint16_t volume[2]; + uint32_t volumeLR; + }; + uint16_t sampleRate; + uint16_t channels; + int16_t flowControlFlag; // underrun (out) or overrrun (in) indication + uint8_t out; // out equals 1 for AudioTrack and 0 for AudioRecord + uint8_t forceReady; + uint16_t bufferTimeoutMs; // Maximum cumulated timeout before restarting audioflinger + uint16_t waitTimeMs; // Cumulated wait time + // Padding ensuring that data buffer starts on a cache line boundary (32 bytes). + // See AudioFlinger::TrackBase constructor + int32_t Padding[3]; + + audio_track_cblk_t(); + uint32_t stepUser(uint32_t frameCount); + bool stepServer(uint32_t frameCount); + void* buffer(uint32_t offset) const; + uint32_t framesAvailable(); + uint32_t framesAvailable_l(); + uint32_t framesReady(); +}; + + +// ---------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_AUDIO_TRACK_SHARED_H diff --git a/include/private/media/VideoFrame.h b/include/private/media/VideoFrame.h new file mode 100644 index 0000000..9c35274 --- /dev/null +++ b/include/private/media/VideoFrame.h @@ -0,0 +1,127 @@ +/* +** +** 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_VIDEO_FRAME_H +#define ANDROID_VIDEO_FRAME_H + +#include +#include +#include +#include + +namespace android { + +// A simple buffer to hold binary data +class MediaAlbumArt +{ +public: + MediaAlbumArt(): mSize(0), mData(0) {} + + explicit MediaAlbumArt(const char* url) { + mSize = 0; + mData = NULL; + FILE *in = fopen(url, "r"); + if (!in) { + return; + } + fseek(in, 0, SEEK_END); + mSize = ftell(in); // Allocating buffer of size equals to the external file size. + if (mSize == 0 || (mData = new uint8_t[mSize]) == NULL) { + fclose(in); + if (mSize != 0) { + mSize = 0; + } + return; + } + rewind(in); + if (fread(mData, 1, mSize, in) != mSize) { // Read failed. + delete[] mData; + mData = NULL; + mSize = 0; + return; + } + fclose(in); + } + + MediaAlbumArt(const MediaAlbumArt& copy) { + mSize = copy.mSize; + mData = NULL; // initialize it first + if (mSize > 0 && copy.mData != NULL) { + mData = new uint8_t[copy.mSize]; + if (mData != NULL) { + memcpy(mData, copy.mData, mSize); + } else { + mSize = 0; + } + } + } + + ~MediaAlbumArt() { + if (mData != 0) { + delete[] mData; + } + } + + // Intentional public access modifier: + // We have to know the internal structure in order to share it between + // processes? + uint32_t mSize; // Number of bytes in mData + uint8_t* mData; // Actual binary data +}; + +// Represents a color converted (RGB-based) video frame +// with bitmap pixels stored in FrameBuffer +class VideoFrame +{ +public: + VideoFrame(): mWidth(0), mHeight(0), mDisplayWidth(0), mDisplayHeight(0), mSize(0), mData(0) {} + + VideoFrame(const VideoFrame& copy) { + mWidth = copy.mWidth; + mHeight = copy.mHeight; + mDisplayWidth = copy.mDisplayWidth; + mDisplayHeight = copy.mDisplayHeight; + mSize = copy.mSize; + mData = NULL; // initialize it first + if (mSize > 0 && copy.mData != NULL) { + mData = new uint8_t[mSize]; + if (mData != NULL) { + memcpy(mData, copy.mData, mSize); + } else { + mSize = 0; + } + } + } + + ~VideoFrame() { + if (mData != 0) { + delete[] mData; + } + } + + // Intentional public access modifier: + uint32_t mWidth; + uint32_t mHeight; + uint32_t mDisplayWidth; + uint32_t mDisplayHeight; + uint32_t mSize; // Number of bytes in mData + uint8_t* mData; // Actual binary data +}; + +}; // namespace android + +#endif // ANDROID_VIDEO_FRAME_H diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h new file mode 100644 index 0000000..0c7ad46 --- /dev/null +++ b/include/private/opengles/gl_context.h @@ -0,0 +1,632 @@ +/* + * Copyright (C) 2006 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_OPENGLES_CONTEXT_H +#define ANDROID_OPENGLES_CONTEXT_H + +#include +#include +#include +#include +#ifdef HAVE_ANDROID_OS +#include +#endif + +#include + +#include +#include + +namespace android { + +const unsigned int OGLES_NUM_COMPRESSED_TEXTURE_FORMATS = 10; + +class EGLTextureObject; +class EGLSurfaceManager; +class EGLBufferObjectManager; + +namespace gl { + +struct ogles_context_t; +struct matrixx_t; +struct transform_t; +struct buffer_t; + +ogles_context_t* getGlContext(); + +template +static inline void swap(T& a, T& b) { + T t(a); a = b; b = t; +} +template +inline T max(T a, T b) { + return a +inline T max(T a, T b, T c) { + return max(a, max(b, c)); +} +template +inline T min(T a, T b) { + return a +inline T min(T a, T b, T c) { + return min(a, min(b, c)); +} +template +inline T min(T a, T b, T c, T d) { + return min(min(a,b), min(c,d)); +} + +// ---------------------------------------------------------------------------- +// vertices +// ---------------------------------------------------------------------------- + +struct vec3_t { + union { + struct { GLfixed x, y, z; }; + struct { GLfixed r, g, b; }; + struct { GLfixed S, T, R; }; + GLfixed v[3]; + }; +}; + +struct vec4_t { + union { + struct { GLfixed x, y, z, w; }; + struct { GLfixed r, g, b, a; }; + struct { GLfixed S, T, R, Q; }; + GLfixed v[4]; + }; +}; + +struct vertex_t { + enum { + // these constant matter for our clipping + CLIP_L = 0x0001, // clipping flags + CLIP_R = 0x0002, + CLIP_B = 0x0004, + CLIP_T = 0x0008, + CLIP_N = 0x0010, + CLIP_F = 0x0020, + + EYE = 0x0040, + RESERVED = 0x0080, + + USER_CLIP_0 = 0x0100, // user clipping flags + USER_CLIP_1 = 0x0200, + USER_CLIP_2 = 0x0400, + USER_CLIP_3 = 0x0800, + USER_CLIP_4 = 0x1000, + USER_CLIP_5 = 0x2000, + + LIT = 0x4000, // lighting has been applied + TT = 0x8000, // texture coords transformed + + FRUSTUM_CLIP_ALL= 0x003F, + USER_CLIP_ALL = 0x3F00, + CLIP_ALL = 0x3F3F, + }; + + // the fields below are arranged to minimize d-cache usage + // we group together, by cache-line, the fields most likely to be used + + union { + vec4_t obj; + vec4_t eye; + }; + vec4_t clip; + + uint32_t flags; + size_t index; // cache tag, and vertex index + GLfixed fog; + uint8_t locked; + uint8_t mru; + uint8_t reserved[2]; + vec4_t window; + + vec4_t color; + vec4_t texture[GGL_TEXTURE_UNIT_COUNT]; + uint32_t reserved1[4]; + + inline void clear() { + flags = index = locked = mru = 0; + } +}; + +struct point_size_t { + GGLcoord size; + GLboolean smooth; +}; + +struct line_width_t { + GGLcoord width; + GLboolean smooth; +}; + +struct polygon_offset_t { + GLfixed factor; + GLfixed units; + GLboolean enable; +}; + +// ---------------------------------------------------------------------------- +// arrays +// ---------------------------------------------------------------------------- + +struct array_t { + typedef void (*fetcher_t)(ogles_context_t*, GLfixed*, const GLvoid*); + fetcher_t fetch; + GLvoid const* physical_pointer; + GLint size; + GLsizei stride; + GLvoid const* pointer; + buffer_t const* bo; + uint16_t type; + GLboolean enable; + GLboolean pad; + GLsizei bounds; + void init(GLint, GLenum, GLsizei, const GLvoid *, const buffer_t*, GLsizei); + inline void resolve(); + inline const GLubyte* element(GLint i) const { + return (const GLubyte*)physical_pointer + i * stride; + } +}; + +struct array_machine_t { + array_t vertex; + array_t normal; + array_t color; + array_t texture[GGL_TEXTURE_UNIT_COUNT]; + uint8_t activeTexture; + uint8_t tmu; + uint16_t cull; + uint32_t flags; + GLenum indicesType; + buffer_t const* array_buffer; + buffer_t const* element_array_buffer; + + void (*compileElements)(ogles_context_t*, vertex_t*, GLint, GLsizei); + void (*compileElement)(ogles_context_t*, vertex_t*, GLint); + + void (*mvp_transform)(transform_t const*, vec4_t*, vec4_t const*); + void (*mv_transform)(transform_t const*, vec4_t*, vec4_t const*); + void (*tex_transform[2])(transform_t const*, vec4_t*, vec4_t const*); + void (*perspective)(ogles_context_t*c, vertex_t* v); + void (*clipVertex)(ogles_context_t* c, vertex_t* nv, + GGLfixed t, const vertex_t* s, const vertex_t* p); + void (*clipEye)(ogles_context_t* c, vertex_t* nv, + GGLfixed t, const vertex_t* s, const vertex_t* p); +}; + +struct vertex_cache_t { + enum { + // must be at least 4 + // 3 vertice for triangles + // or 2 + 2 for indexed triangles w/ cache contention + VERTEX_BUFFER_SIZE = 8, + // must be a power of two and at least 3 + VERTEX_CACHE_SIZE = 64, // 8 KB + + INDEX_BITS = 16, + INDEX_MASK = ((1LU<(pthread_getspecific(gGLKey)); + } +#endif + + +struct prims_t { + typedef ogles_context_t* GL; + void (*renderPoint)(GL, vertex_t*); + void (*renderLine)(GL, vertex_t*, vertex_t*); + void (*renderTriangle)(GL, vertex_t*, vertex_t*, vertex_t*); +}; + +struct ogles_context_t { + context_t rasterizer; + array_machine_t arrays __attribute__((aligned(32))); + texture_state_t textures; + transform_state_t transforms; + vertex_cache_t vc; + prims_t prims; + culling_t cull; + lighting_t lighting; + user_clip_planes_t clipPlanes; + compute_iterators_t lerp; __attribute__((aligned(32))); + vertex_t current; + vec4_t currentColorClamped; + vec3_t currentNormal; + viewport_t viewport; + point_size_t point; + line_width_t line; + polygon_offset_t polygonOffset; + fog_t fog; + uint32_t perspective : 1; + uint32_t transformTextures : 1; + EGLSurfaceManager* surfaceManager; + EGLBufferObjectManager* bufferObjectManager; + GLenum error; + + static inline ogles_context_t* get() { + return getGlThreadSpecific(); + } + +}; + +}; // namespace gl +}; // namespace android + +#endif // ANDROID_OPENGLES_CONTEXT_H + diff --git a/include/private/ui/LayerState.h b/include/private/ui/LayerState.h new file mode 100644 index 0000000..b6fcd80 --- /dev/null +++ b/include/private/ui/LayerState.h @@ -0,0 +1,75 @@ +/* + * 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_COMPOSER_LAYER_STATE_H +#define ANDROID_COMPOSER_LAYER_STATE_H + +#include +#include + +#include + +#include +#include + +#include + +namespace android { + +class Parcel; + +struct layer_state_t { + + layer_state_t() + : surface(0), what(0), + x(0), y(0), z(0), w(0), h(0), + alpha(0), tint(0), flags(0), mask(0), + reserved(0) + { + matrix.dsdx = matrix.dtdy = 1.0f; + matrix.dsdy = matrix.dtdx = 0.0f; + } + + status_t write(Parcel& output) const; + status_t read(const Parcel& input); + + struct matrix22_t { + float dsdx; + float dtdx; + float dsdy; + float dtdy; + }; + SurfaceID surface; + uint32_t what; + int32_t x; + int32_t y; + uint32_t z; + uint32_t w; + uint32_t h; + float alpha; + uint32_t tint; + uint8_t flags; + uint8_t mask; + uint8_t reserved; + matrix22_t matrix; + // non POD must be last. see write/read + Region transparentRegion; +}; + +}; // namespace android + +#endif // ANDROID_COMPOSER_LAYER_STATE_H + diff --git a/include/private/ui/SharedState.h b/include/private/ui/SharedState.h new file mode 100644 index 0000000..546d0ad --- /dev/null +++ b/include/private/ui/SharedState.h @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2007 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_UI_SHARED_STATE_H +#define ANDROID_UI_SHARED_STATE_H + +#include +#include + +#include + +namespace android { + +/* + * These structures are shared between the composer process and its clients + */ + +// --------------------------------------------------------------------------- + +struct surface_info_t { // 4 longs, 16 bytes + enum { + eBufferDirty = 0x01 + }; + uint16_t w; + uint16_t h; + uint16_t stride; + uint16_t bpr; + uint16_t reserved; + uint8_t format; + uint8_t flags; + ssize_t bits_offset; +}; + +// --------------------------------------------------------------------------- + +const uint32_t NUM_LAYERS_MAX = 31; + +enum { // layer_cblk_t swapState + eIndex = 0x00000001, + eFlipRequested = 0x00000002, + + eResizeBuffer0 = 0x00000004, + eResizeBuffer1 = 0x00000008, + eResizeRequested = eResizeBuffer0 | eResizeBuffer1, + + eBusy = 0x00000010, + eLocked = 0x00000020, + eNextFlipPending = 0x00000040, + eInvalidSurface = 0x00000080 +}; + +enum { // layer_cblk_t flags + eLayerNotPosted = 0x00000001, + eNoCopyBack = 0x00000002, + eReserved = 0x0000007C, + eBufferIndexShift = 7, + eBufferIndex = 1<>1)); + } + static inline int frontBuffer(uint32_t state) { + return 1 - backBuffer(state); + } +}; + +// --------------------------------------------------------------------------- + +struct per_client_cblk_t // 4KB max +{ + Mutex lock; + Condition cv; + layer_cblk_t layers[NUM_LAYERS_MAX] __attribute__((aligned(32))); + + enum { + BLOCKING = 0x00000001, + INSPECT = 0x00000002 + }; + + per_client_cblk_t(); + + // these functions are used by the clients + status_t validate(size_t i) const; + int32_t lock_layer(size_t i, uint32_t flags); + uint32_t unlock_layer_and_post(size_t i); + void unlock_layer(size_t i); +}; +// --------------------------------------------------------------------------- + +const uint32_t NUM_DISPLAY_MAX = 4; + +struct display_cblk_t +{ + uint16_t w; + uint16_t h; + uint8_t format; + uint8_t orientation; + uint8_t reserved[2]; + float fps; + float density; + float xdpi; + float ydpi; + uint32_t pad[2]; +}; + +struct surface_flinger_cblk_t // 4KB max +{ + surface_flinger_cblk_t(); + + uint8_t connected; + uint8_t reserved[3]; + uint32_t pad[7]; + + display_cblk_t displays[NUM_DISPLAY_MAX]; +}; + +// --------------------------------------------------------------------------- + +template struct CTA; +template<> struct CTA { }; + +// compile-time assertions. just to avoid catastrophes. +inline void compile_time_asserts() { + CTA sizeof__layer_cblk_t__eq_128; + (void)sizeof__layer_cblk_t__eq_128; // we don't want a warning + CTA sizeof__per_client_cblk_t__le_4096; + (void)sizeof__per_client_cblk_t__le_4096; // we don't want a warning + CTA sizeof__surface_flinger_cblk_t__le_4096; + (void)sizeof__surface_flinger_cblk_t__le_4096; // we don't want a warning +} + +}; // namespace android + +#endif // ANDROID_UI_SHARED_STATE_H + diff --git a/include/private/ui/SurfaceFlingerSynchro.h b/include/private/ui/SurfaceFlingerSynchro.h new file mode 100644 index 0000000..ff91b61 --- /dev/null +++ b/include/private/ui/SurfaceFlingerSynchro.h @@ -0,0 +1,76 @@ +/* + * 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_SURFACE_FLINGER_SYNCHRO_H +#define ANDROID_SURFACE_FLINGER_SYNCHRO_H + +#include +#include +#include +#include +#include + +namespace android { + +class SurfaceFlinger; + +class SurfaceFlingerSynchro +{ +public: + + // client constructor + SurfaceFlingerSynchro(const sp& flinger); + ~SurfaceFlingerSynchro(); + + // signal surfaceflinger for some work + status_t signal(); + +private: + class Barrier { + public: + Barrier(); + ~Barrier(); + void open(); + void close(); + void waitAndClose(); + status_t waitAndClose(nsecs_t timeout); + private: + enum { OPENED, CLOSED }; + mutable Mutex lock; + mutable Condition cv; + volatile int state; + }; + + friend class SurfaceFlinger; + + // server constructor + SurfaceFlingerSynchro(); + + void open(); + + // wait until there is some work to do + status_t wait(); + status_t wait(nsecs_t timeout); + + sp mSurfaceComposer; + Barrier mBarrier; +}; + +}; // namespace android + +#endif // ANDROID_SURFACE_FLINGER_SYNCHRO_H + diff --git a/include/private/utils/Static.h b/include/private/utils/Static.h new file mode 100644 index 0000000..f1439b7 --- /dev/null +++ b/include/private/utils/Static.h @@ -0,0 +1,58 @@ +/* + * 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. + */ + +// All static variables go here, to control initialization and +// destruction order in the library. + +#include +#include + +#ifndef LIBUTILS_NATIVE +#include +#include +#include +#include +#include +#endif + +namespace android { +// For TextStream.cpp +extern Vector gTextBuffers; + +// For String8.cpp +extern void initialize_string8(); +extern void terminate_string8(); + +// For String16.cpp +extern void initialize_string16(); +extern void terminate_string16(); + + + +#ifndef LIBUTILS_NATIVE + +// For ProcessState.cpp +extern Mutex gProcessMutex; +extern sp gProcess; + +// For ServiceManager.cpp +extern Mutex gDefaultServiceManagerLock; +extern sp gDefaultServiceManager; +extern sp gPermissionController; + +#endif + +} // namespace android diff --git a/include/private/utils/binder_module.h b/include/private/utils/binder_module.h new file mode 100644 index 0000000..fdf327e --- /dev/null +++ b/include/private/utils/binder_module.h @@ -0,0 +1,148 @@ +/* + * 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 _BINDER_MODULE_H_ +#define _BINDER_MODULE_H_ + +#ifdef __cplusplus +namespace android { +#endif + +#if defined(HAVE_ANDROID_OS) + +/* obtain structures and constants from the kernel header */ + +#include +#include + +#else + +/* Some parts of the simulator need fake versions of this + * stuff in order to compile. Really this should go away + * entirely... + */ + +#define BINDER_CURRENT_PROTOCOL_VERSION 7 + +#define BINDER_TYPE_BINDER 1 +#define BINDER_TYPE_WEAK_BINDER 2 +#define BINDER_TYPE_HANDLE 3 +#define BINDER_TYPE_WEAK_HANDLE 4 +#define BINDER_TYPE_FD 5 + +struct flat_binder_object { + unsigned long type; + unsigned long flags; + union { + void *binder; + signed long handle; + }; + void *cookie; +}; + +struct binder_write_read { + signed long write_size; + signed long write_consumed; + unsigned long write_buffer; + signed long read_size; + signed long read_consumed; + unsigned long read_buffer; +}; + +struct binder_transaction_data { + union { + size_t handle; + void *ptr; + } target; + void *cookie; + unsigned int code; + + unsigned int flags; + pid_t sender_pid; + uid_t sender_euid; + size_t data_size; + size_t offsets_size; + + union { + struct { + const void *buffer; + const void *offsets; + } ptr; + uint8_t buf[8]; + } data; +}; + +enum transaction_flags { + TF_ONE_WAY = 0x01, + TF_ROOT_OBJECT = 0x04, + TF_STATUS_CODE = 0x08, + TF_ACCEPT_FDS = 0x10, +}; + + +enum { + FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff, + FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100, +}; + +enum BinderDriverReturnProtocol { + BR_ERROR, + BR_OK, + BR_TRANSACTION, + BR_REPLY, + BR_ACQUIRE_RESULT, + BR_DEAD_REPLY, + BR_TRANSACTION_COMPLETE, + BR_INCREFS, + BR_ACQUIRE, + BR_RELEASE, + BR_DECREFS, + BR_ATTEMPT_ACQUIRE, + BR_NOOP, + BR_SPAWN_LOOPER, + BR_FINISHED, + BR_DEAD_BINDER, + BR_CLEAR_DEATH_NOTIFICATION_DONE, + BR_FAILED_REPLY, +}; + +enum BinderDriverCommandProtocol { + BC_TRANSACTION, + BC_REPLY, + BC_ACQUIRE_RESULT, + BC_FREE_BUFFER, + BC_INCREFS, + BC_ACQUIRE, + BC_RELEASE, + BC_DECREFS, + BC_INCREFS_DONE, + BC_ACQUIRE_DONE, + BC_ATTEMPT_ACQUIRE, + BC_REGISTER_LOOPER, + BC_ENTER_LOOPER, + BC_EXIT_LOOPER, + BC_REQUEST_DEATH_NOTIFICATION, + BC_CLEAR_DEATH_NOTIFICATION, + BC_DEAD_BINDER_DONE, +}; + +#endif + +#ifdef __cplusplus +} // namespace android +#endif + +#endif // _BINDER_MODULE_H_ diff --git a/include/private/utils/futex_synchro.h b/include/private/utils/futex_synchro.h new file mode 100644 index 0000000..ac2ab19 --- /dev/null +++ b/include/private/utils/futex_synchro.h @@ -0,0 +1,60 @@ +/* + * 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 _FUTEX_SYNCHRO_H +#define _FUTEX_SYNCHRO_H + +#ifndef HAVE_FUTEX +#error "HAVE_FUTEX not defined" +#endif + +#define FUTEX_WAIT_INFINITE (0) + +typedef struct futex_mutex_t futex_mutex_t; + +struct futex_mutex_t +{ + volatile int value; +}; + +typedef struct futex_cond_t futex_cond_t; + +struct futex_cond_t +{ + volatile int value; +}; + + +#if __cplusplus +extern "C" { +#endif + +void futex_mutex_init(futex_mutex_t *m); +int futex_mutex_lock(futex_mutex_t *m, unsigned msec); +void futex_mutex_unlock(futex_mutex_t *m); +int futex_mutex_trylock(futex_mutex_t *m); + +void futex_cond_init(futex_cond_t *c); +int futex_cond_wait(futex_cond_t *c, futex_mutex_t *m, unsigned msec); +void futex_cond_signal(futex_cond_t *c); +void futex_cond_broadcast(futex_cond_t *c); + +#if __cplusplus +} // extern "C" +#endif + +#endif // _FUTEX_SYNCHRO_H + diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk new file mode 100644 index 0000000..8020da2 --- /dev/null +++ b/media/libmedia/Android.mk @@ -0,0 +1,39 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + AudioTrack.cpp \ + IAudioFlinger.cpp \ + IAudioFlingerClient.cpp \ + IAudioTrack.cpp \ + IAudioRecord.cpp \ + AudioRecord.cpp \ + AudioSystem.cpp \ + mediaplayer.cpp \ + IMediaPlayerService.cpp \ + IMediaPlayerClient.cpp \ + IMediaPlayer.cpp \ + IMediaRecorder.cpp \ + mediarecorder.cpp \ + IMediaMetadataRetriever.cpp \ + mediametadataretriever.cpp \ + ToneGenerator.cpp \ + JetPlayer.cpp + +LOCAL_SHARED_LIBRARIES := \ + libui libcutils libutils libsonivox + +LOCAL_MODULE:= libmedia + +ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true) +LOCAL_LDLIBS += -ldl +endif + +ifneq ($(TARGET_SIMULATOR),true) +LOCAL_SHARED_LIBRARIES += libdl +endif + +LOCAL_C_INCLUDES := \ + $(call include-path-for, graphics corecg) + +include $(BUILD_SHARED_LIBRARY) diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp new file mode 100644 index 0000000..7594ff0 --- /dev/null +++ b/media/libmedia/AudioRecord.cpp @@ -0,0 +1,574 @@ +/* +** +** Copyright 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 "AudioRecord" + +#include +#include + +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) +#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) + +namespace android { + +// --------------------------------------------------------------------------- + +AudioRecord::AudioRecord() + : mStatus(NO_INIT) +{ +} + +AudioRecord::AudioRecord( + int streamType, + uint32_t sampleRate, + int format, + int channelCount, + int frameCount, + uint32_t flags, + callback_t cbf, + void* user, + int notificationFrames) + : mStatus(NO_INIT) +{ + mStatus = set(streamType, sampleRate, format, channelCount, + frameCount, flags, cbf, user, notificationFrames); +} + +AudioRecord::~AudioRecord() +{ + if (mStatus == NO_ERROR) { + // Make sure that callback function exits in the case where + // it is looping on buffer empty condition in obtainBuffer(). + // Otherwise the callback thread will never exit. + stop(); + if (mClientRecordThread != 0) { + mCblk->cv.signal(); + mClientRecordThread->requestExitAndWait(); + mClientRecordThread.clear(); + } + mAudioRecord.clear(); + IPCThreadState::self()->flushCommands(); + } +} + +status_t AudioRecord::set( + int streamType, + uint32_t sampleRate, + int format, + int channelCount, + int frameCount, + uint32_t flags, + callback_t cbf, + void* user, + int notificationFrames, + bool threadCanCallJava) +{ + + LOGV("set(): sampleRate %d, channelCount %d, frameCount %d",sampleRate, channelCount, frameCount); + if (mAudioFlinger != 0) { + return INVALID_OPERATION; + } + + const sp& audioFlinger = AudioSystem::get_audio_flinger(); + if (audioFlinger == 0) { + return NO_INIT; + } + + if (streamType == DEFAULT_INPUT) { + streamType = MIC_INPUT; + } + + if (sampleRate == 0) { + sampleRate = DEFAULT_SAMPLE_RATE; + } + // these below should probably come from the audioFlinger too... + if (format == 0) { + format = AudioSystem::PCM_16_BIT; + } + if (channelCount == 0) { + channelCount = 1; + } + + // validate parameters + if (format != AudioSystem::PCM_16_BIT) { + return BAD_VALUE; + } + if (channelCount != 1 && channelCount != 2) { + return BAD_VALUE; + } + + // validate framecount + size_t inputBuffSizeInBytes = -1; + if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &inputBuffSizeInBytes) + != NO_ERROR) { + LOGE("AudioSystem could not query the input buffer size."); + return NO_INIT; + } + if (inputBuffSizeInBytes == 0) { + LOGE("Recording parameters are not supported: sampleRate %d, channelCount %d, format %d", + sampleRate, channelCount, format); + return BAD_VALUE; + } + int frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? 2 : 1); + + // We use 2* size of input buffer for ping pong use of record buffer. + int minFrameCount = 2 * inputBuffSizeInBytes / frameSizeInBytes; + LOGV("AudioRecord::set() minFrameCount = %d", minFrameCount); + + if (frameCount == 0) { + frameCount = minFrameCount; + } else if (frameCount < minFrameCount) { + return BAD_VALUE; + } + + if (notificationFrames == 0) { + notificationFrames = frameCount/2; + } + + // open record channel + status_t status; + sp record = audioFlinger->openRecord(getpid(), streamType, + sampleRate, format, + channelCount, + frameCount, + ((uint16_t)flags) << 16, + &status); + if (record == 0) { + LOGE("AudioFlinger could not create record track, status: %d", status); + return status; + } + sp cblk = record->getCblk(); + if (cblk == 0) { + return NO_INIT; + } + if (cbf != 0) { + mClientRecordThread = new ClientRecordThread(*this, threadCanCallJava); + if (mClientRecordThread == 0) { + return NO_INIT; + } + } + + mStatus = NO_ERROR; + + mAudioFlinger = audioFlinger; + mAudioRecord = record; + mCblkMemory = cblk; + mCblk = static_cast(cblk->pointer()); + mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); + mCblk->out = 0; + mSampleRate = sampleRate; + mFormat = format; + // Update buffer size in case it has been limited by AudioFlinger during track creation + mFrameCount = mCblk->frameCount; + mChannelCount = channelCount; + mActive = 0; + mCbf = cbf; + mNotificationFrames = notificationFrames; + mRemainingFrames = notificationFrames; + mUserData = user; + // TODO: add audio hardware input latency here + mLatency = (1000*mFrameCount) / mSampleRate; + mMarkerPosition = 0; + mNewPosition = 0; + mUpdatePeriod = 0; + + return NO_ERROR; +} + +status_t AudioRecord::initCheck() const +{ + return mStatus; +} + +// ------------------------------------------------------------------------- + +uint32_t AudioRecord::latency() const +{ + return mLatency; +} + +uint32_t AudioRecord::sampleRate() const +{ + return mSampleRate; +} + +int AudioRecord::format() const +{ + return mFormat; +} + +int AudioRecord::channelCount() const +{ + return mChannelCount; +} + +uint32_t AudioRecord::frameCount() const +{ + return mFrameCount; +} + +int AudioRecord::frameSize() const +{ + return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t)); +} + +// ------------------------------------------------------------------------- + +status_t AudioRecord::start() +{ + status_t ret = NO_ERROR; + sp t = mClientRecordThread; + + LOGV("start"); + + if (t != 0) { + if (t->exitPending()) { + if (t->requestExitAndWait() == WOULD_BLOCK) { + LOGE("AudioRecord::start called from thread"); + return WOULD_BLOCK; + } + } + t->mLock.lock(); + } + + if (android_atomic_or(1, &mActive) == 0) { + mNewPosition = mCblk->user + mUpdatePeriod; + mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; + mCblk->waitTimeMs = 0; + if (t != 0) { + t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT); + } else { + setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT); + } + ret = mAudioRecord->start(); + } + + if (t != 0) { + t->mLock.unlock(); + } + + return ret; +} + +status_t AudioRecord::stop() +{ + sp t = mClientRecordThread; + + LOGV("stop"); + + if (t != 0) { + t->mLock.lock(); + } + + if (android_atomic_and(~1, &mActive) == 1) { + mAudioRecord->stop(); + if (t != 0) { + t->requestExit(); + } else { + setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL); + } + } + + if (t != 0) { + t->mLock.unlock(); + } + + return NO_ERROR; +} + +bool AudioRecord::stopped() const +{ + return !mActive; +} + +status_t AudioRecord::setMarkerPosition(uint32_t marker) +{ + if (mCbf == 0) return INVALID_OPERATION; + + mMarkerPosition = marker; + + return NO_ERROR; +} + +status_t AudioRecord::getMarkerPosition(uint32_t *marker) +{ + if (marker == 0) return BAD_VALUE; + + *marker = mMarkerPosition; + + return NO_ERROR; +} + +status_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod) +{ + if (mCbf == 0) return INVALID_OPERATION; + + uint32_t curPosition; + getPosition(&curPosition); + mNewPosition = curPosition + updatePeriod; + mUpdatePeriod = updatePeriod; + + return NO_ERROR; +} + +status_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) +{ + if (updatePeriod == 0) return BAD_VALUE; + + *updatePeriod = mUpdatePeriod; + + return NO_ERROR; +} + +status_t AudioRecord::getPosition(uint32_t *position) +{ + if (position == 0) return BAD_VALUE; + + *position = mCblk->user; + + return NO_ERROR; +} + + +// ------------------------------------------------------------------------- + +status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) +{ + int active; + int timeout = 0; + status_t result; + audio_track_cblk_t* cblk = mCblk; + uint32_t framesReq = audioBuffer->frameCount; + + audioBuffer->frameCount = 0; + audioBuffer->size = 0; + + uint32_t framesReady = cblk->framesReady(); + + if (framesReady == 0) { + Mutex::Autolock _l(cblk->lock); + goto start_loop_here; + while (framesReady == 0) { + active = mActive; + if (UNLIKELY(!active)) + return NO_MORE_BUFFERS; + if (UNLIKELY(!waitCount)) + return WOULD_BLOCK; + timeout = 0; + result = cblk->cv.waitRelative(cblk->lock, milliseconds(WAIT_PERIOD_MS)); + if (__builtin_expect(result!=NO_ERROR, false)) { + cblk->waitTimeMs += WAIT_PERIOD_MS; + if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) { + LOGW( "obtainBuffer timed out (is the CPU pegged?) " + "user=%08x, server=%08x", cblk->user, cblk->server); + timeout = 1; + cblk->waitTimeMs = 0; + } + if (--waitCount == 0) { + return TIMED_OUT; + } + } + // read the server count again + start_loop_here: + framesReady = cblk->framesReady(); + } + } + + LOGW_IF(timeout, + "*** SERIOUS WARNING *** obtainBuffer() timed out " + "but didn't need to be locked. We recovered, but " + "this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server); + + cblk->waitTimeMs = 0; + + if (framesReq > framesReady) { + framesReq = framesReady; + } + + uint32_t u = cblk->user; + uint32_t bufferEnd = cblk->userBase + cblk->frameCount; + + if (u + framesReq > bufferEnd) { + framesReq = bufferEnd - u; + } + + audioBuffer->flags = 0; + audioBuffer->channelCount= mChannelCount; + audioBuffer->format = mFormat; + audioBuffer->frameCount = framesReq; + audioBuffer->size = framesReq*mChannelCount*sizeof(int16_t); + audioBuffer->raw = (int8_t*)cblk->buffer(u); + active = mActive; + return active ? status_t(NO_ERROR) : status_t(STOPPED); +} + +void AudioRecord::releaseBuffer(Buffer* audioBuffer) +{ + audio_track_cblk_t* cblk = mCblk; + cblk->stepUser(audioBuffer->frameCount); +} + +// ------------------------------------------------------------------------- + +ssize_t AudioRecord::read(void* buffer, size_t userSize) +{ + ssize_t read = 0; + Buffer audioBuffer; + int8_t *dst = static_cast(buffer); + + if (ssize_t(userSize) < 0) { + // sanity-check. user is most-likely passing an error code. + LOGE("AudioRecord::read(buffer=%p, size=%u (%d)", + buffer, userSize, userSize); + return BAD_VALUE; + } + + LOGV("read size: %d", userSize); + + do { + + audioBuffer.frameCount = userSize/mChannelCount/sizeof(int16_t); + + // Calling obtainBuffer() with a negative wait count causes + // an (almost) infinite wait time. + status_t err = obtainBuffer(&audioBuffer, -1); + if (err < 0) { + // out of buffers, return #bytes written + if (err == status_t(NO_MORE_BUFFERS)) + break; + return ssize_t(err); + } + + size_t bytesRead = audioBuffer.size; + memcpy(dst, audioBuffer.i8, bytesRead); + + dst += bytesRead; + userSize -= bytesRead; + read += bytesRead; + + releaseBuffer(&audioBuffer); + } while (userSize); + + return read; +} + +// ------------------------------------------------------------------------- + +bool AudioRecord::processAudioBuffer(const sp& thread) +{ + Buffer audioBuffer; + uint32_t frames = mRemainingFrames; + size_t readSize; + + // Manage marker callback + if (mMarkerPosition > 0) { + if (mCblk->user >= mMarkerPosition) { + mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition); + mMarkerPosition = 0; + } + } + + // Manage new position callback + if (mUpdatePeriod > 0) { + while (mCblk->user >= mNewPosition) { + mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition); + mNewPosition += mUpdatePeriod; + } + } + + do { + audioBuffer.frameCount = frames; + // Calling obtainBuffer() with a wait count of 1 + // limits wait time to WAIT_PERIOD_MS. This prevents from being + // stuck here not being able to handle timed events (position, markers). + status_t err = obtainBuffer(&audioBuffer, 1); + if (err < NO_ERROR) { + if (err != TIMED_OUT) { + LOGE("Error obtaining an audio buffer, giving up."); + return false; + } + break; + } + if (err == status_t(STOPPED)) return false; + + size_t reqSize = audioBuffer.size; + mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer); + readSize = audioBuffer.size; + + // Sanity check on returned size + if (ssize_t(readSize) <= 0) break; + if (readSize > reqSize) readSize = reqSize; + + audioBuffer.size = readSize; + audioBuffer.frameCount = readSize/mChannelCount/sizeof(int16_t); + frames -= audioBuffer.frameCount; + + releaseBuffer(&audioBuffer); + + } while (frames); + + + // Manage overrun callback + if (mActive && (mCblk->framesAvailable_l() == 0)) { + LOGV("Overrun user: %x, server: %x, flowControlFlag %d", mCblk->user, mCblk->server, mCblk->flowControlFlag); + if (mCblk->flowControlFlag == 0) { + mCbf(EVENT_OVERRUN, mUserData, 0); + mCblk->flowControlFlag = 1; + } + } + + if (frames == 0) { + mRemainingFrames = mNotificationFrames; + } else { + mRemainingFrames = frames; + } + return true; +} + +// ========================================================================= + +AudioRecord::ClientRecordThread::ClientRecordThread(AudioRecord& receiver, bool bCanCallJava) + : Thread(bCanCallJava), mReceiver(receiver) +{ +} + +bool AudioRecord::ClientRecordThread::threadLoop() +{ + return mReceiver.processAudioBuffer(this); +} + +// ------------------------------------------------------------------------- + +}; // namespace android + diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp new file mode 100644 index 0000000..63dfc3b --- /dev/null +++ b/media/libmedia/AudioSystem.cpp @@ -0,0 +1,383 @@ +/* + * Copyright (C) 2006-2007 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_TAG "AudioSystem" +//#define LOG_NDEBUG 0 + +#include +#include +#include +#include + +namespace android { + +// client singleton for AudioFlinger binder interface +Mutex AudioSystem::gLock; +sp AudioSystem::gAudioFlinger; +sp AudioSystem::gAudioFlingerClient; +audio_error_callback AudioSystem::gAudioErrorCallback = NULL; +// Cached values +int AudioSystem::gOutSamplingRate[NUM_AUDIO_OUTPUT_TYPES]; +int AudioSystem::gOutFrameCount[NUM_AUDIO_OUTPUT_TYPES]; +uint32_t AudioSystem::gOutLatency[NUM_AUDIO_OUTPUT_TYPES]; +bool AudioSystem::gA2dpEnabled; +// Cached values for recording queries +uint32_t AudioSystem::gPrevInSamplingRate = 16000; +int AudioSystem::gPrevInFormat = AudioSystem::PCM_16_BIT; +int AudioSystem::gPrevInChannelCount = 1; +size_t AudioSystem::gInBuffSize = 0; + + +// establish binder interface to AudioFlinger service +const sp& AudioSystem::get_audio_flinger() +{ + Mutex::Autolock _l(gLock); + if (gAudioFlinger.get() == 0) { + sp sm = defaultServiceManager(); + sp binder; + do { + binder = sm->getService(String16("media.audio_flinger")); + if (binder != 0) + break; + LOGW("AudioFlinger not published, waiting..."); + usleep(500000); // 0.5 s + } while(true); + if (gAudioFlingerClient == NULL) { + gAudioFlingerClient = new AudioFlingerClient(); + } else { + if (gAudioErrorCallback) { + gAudioErrorCallback(NO_ERROR); + } + } + binder->linkToDeath(gAudioFlingerClient); + gAudioFlinger = interface_cast(binder); + gAudioFlinger->registerClient(gAudioFlingerClient); + // Cache frequently accessed parameters + for (int output = 0; output < NUM_AUDIO_OUTPUT_TYPES; output++) { + gOutFrameCount[output] = (int)gAudioFlinger->frameCount(output); + gOutSamplingRate[output] = (int)gAudioFlinger->sampleRate(output); + gOutLatency[output] = gAudioFlinger->latency(output); + } + gA2dpEnabled = gAudioFlinger->isA2dpEnabled(); + } + LOGE_IF(gAudioFlinger==0, "no AudioFlinger!?"); + return gAudioFlinger; +} + +// routing helper functions +status_t AudioSystem::speakerphone(bool state) { + uint32_t routes = state ? ROUTE_SPEAKER : ROUTE_EARPIECE; + return setRouting(MODE_IN_CALL, routes, ROUTE_ALL); +} + +status_t AudioSystem::isSpeakerphoneOn(bool* state) { + uint32_t routes = 0; + status_t s = getRouting(MODE_IN_CALL, &routes); + *state = !!(routes & ROUTE_SPEAKER); + return s; +} + +status_t AudioSystem::bluetoothSco(bool state) { + uint32_t mask = ROUTE_BLUETOOTH_SCO; + uint32_t routes = state ? mask : ROUTE_EARPIECE; + return setRouting(MODE_IN_CALL, routes, ROUTE_ALL); +} + +status_t AudioSystem::isBluetoothScoOn(bool* state) { + uint32_t routes = 0; + status_t s = getRouting(MODE_IN_CALL, &routes); + *state = !!(routes & ROUTE_BLUETOOTH_SCO); + return s; +} + +status_t AudioSystem::muteMicrophone(bool state) { + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + return af->setMicMute(state); +} + +status_t AudioSystem::isMicrophoneMuted(bool* state) { + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + *state = af->getMicMute(); + return NO_ERROR; +} + +status_t AudioSystem::setMasterVolume(float value) +{ + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + af->setMasterVolume(value); + return NO_ERROR; +} + +status_t AudioSystem::setMasterMute(bool mute) +{ + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + af->setMasterMute(mute); + return NO_ERROR; +} + +status_t AudioSystem::getMasterVolume(float* volume) +{ + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + *volume = af->masterVolume(); + return NO_ERROR; +} + +status_t AudioSystem::getMasterMute(bool* mute) +{ + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + *mute = af->masterMute(); + return NO_ERROR; +} + +status_t AudioSystem::setStreamVolume(int stream, float value) +{ + if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE; + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + af->setStreamVolume(stream, value); + return NO_ERROR; +} + +status_t AudioSystem::setStreamMute(int stream, bool mute) +{ + if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE; + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + af->setStreamMute(stream, mute); + return NO_ERROR; +} + +status_t AudioSystem::getStreamVolume(int stream, float* volume) +{ + if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE; + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + *volume = af->streamVolume(stream); + return NO_ERROR; +} + +status_t AudioSystem::getStreamMute(int stream, bool* mute) +{ + if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE; + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + *mute = af->streamMute(stream); + return NO_ERROR; +} + +status_t AudioSystem::setMode(int mode) +{ + if (mode >= NUM_MODES) return BAD_VALUE; + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + return af->setMode(mode); +} + +status_t AudioSystem::getMode(int* mode) +{ + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + *mode = af->getMode(); + return NO_ERROR; +} + +status_t AudioSystem::setRouting(int mode, uint32_t routes, uint32_t mask) +{ + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + return af->setRouting(mode, routes, mask); +} + +status_t AudioSystem::getRouting(int mode, uint32_t* routes) +{ + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + uint32_t r = af->getRouting(mode); + *routes = r; + return NO_ERROR; +} + +status_t AudioSystem::isMusicActive(bool* state) { + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + *state = af->isMusicActive(); + return NO_ERROR; +} + +// Temporary interface, do not use +// TODO: Replace with a more generic key:value get/set mechanism +status_t AudioSystem::setParameter(const char* key, const char* value) { + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + return af->setParameter(key, value); +} + +// convert volume steps to natural log scale + +// change this value to change volume scaling +static const float dBPerStep = 0.5f; +// shouldn't need to touch these +static const float dBConvert = -dBPerStep * 2.302585093f / 20.0f; +static const float dBConvertInverse = 1.0f / dBConvert; + +float AudioSystem::linearToLog(int volume) +{ + // float v = volume ? exp(float(100 - volume) * dBConvert) : 0; + // LOGD("linearToLog(%d)=%f", volume, v); + // return v; + return volume ? exp(float(100 - volume) * dBConvert) : 0; +} + +int AudioSystem::logToLinear(float volume) +{ + // int v = volume ? 100 - int(dBConvertInverse * log(volume) + 0.5) : 0; + // LOGD("logTolinear(%d)=%f", v, volume); + // return v; + return volume ? 100 - int(dBConvertInverse * log(volume) + 0.5) : 0; +} + +status_t AudioSystem::getOutputSamplingRate(int* samplingRate, int streamType) +{ + int output = getOutput(streamType); + + if (gOutSamplingRate[output] == 0) { + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + // gOutSamplingRate is updated by get_audio_flinger() + } + LOGV("getOutputSamplingRate() streamType %d, output %d, sampling rate %d", streamType, output, gOutSamplingRate[output]); + *samplingRate = gOutSamplingRate[output]; + + return NO_ERROR; +} + +status_t AudioSystem::getOutputFrameCount(int* frameCount, int streamType) +{ + int output = getOutput(streamType); + + if (gOutFrameCount[output] == 0) { + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + // gOutFrameCount is updated by get_audio_flinger() + } + LOGV("getOutputFrameCount() streamType %d, output %d, frame count %d", streamType, output, gOutFrameCount[output]); + + *frameCount = gOutFrameCount[output]; + return NO_ERROR; +} + +status_t AudioSystem::getOutputLatency(uint32_t* latency, int streamType) +{ + int output = getOutput(streamType); + + if (gOutLatency[output] == 0) { + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + // gOutLatency is updated by get_audio_flinger() + } + LOGV("getOutputLatency() streamType %d, output %d, latency %d", streamType, output, gOutLatency[output]); + + *latency = gOutLatency[output]; + + return NO_ERROR; +} + +status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, int format, int channelCount, + size_t* buffSize) +{ + // Do we have a stale gInBufferSize or are we requesting the input buffer size for new values + if ((gInBuffSize == 0) || (sampleRate != gPrevInSamplingRate) || (format != gPrevInFormat) + || (channelCount != gPrevInChannelCount)) { + // save the request params + gPrevInSamplingRate = sampleRate; + gPrevInFormat = format; + gPrevInChannelCount = channelCount; + + gInBuffSize = 0; + const sp& af = AudioSystem::get_audio_flinger(); + if (af == 0) { + return PERMISSION_DENIED; + } + gInBuffSize = af->getInputBufferSize(sampleRate, format, channelCount); + } + *buffSize = gInBuffSize; + + return NO_ERROR; +} + +// --------------------------------------------------------------------------- + +void AudioSystem::AudioFlingerClient::binderDied(const wp& who) { + Mutex::Autolock _l(AudioSystem::gLock); + AudioSystem::gAudioFlinger.clear(); + + for (int output = 0; output < NUM_AUDIO_OUTPUT_TYPES; output++) { + gOutFrameCount[output] = 0; + gOutSamplingRate[output] = 0; + gOutLatency[output] = 0; + } + AudioSystem::gInBuffSize = 0; + + if (gAudioErrorCallback) { + gAudioErrorCallback(DEAD_OBJECT); + } + LOGW("AudioFlinger server died!"); +} + +void AudioSystem::AudioFlingerClient::a2dpEnabledChanged(bool enabled) { + gA2dpEnabled = enabled; + LOGV("AudioFlinger A2DP enabled status changed! %d", enabled); +} + +void AudioSystem::setErrorCallback(audio_error_callback cb) { + Mutex::Autolock _l(AudioSystem::gLock); + gAudioErrorCallback = cb; +} + +int AudioSystem::getOutput(int streamType) +{ + if (streamType == DEFAULT) { + streamType = MUSIC; + } + if (gA2dpEnabled && routedToA2dpOutput(streamType)) { + return AUDIO_OUTPUT_A2DP; + } else { + return AUDIO_OUTPUT_HARDWARE; + } +} + +bool AudioSystem::routedToA2dpOutput(int streamType) { + switch(streamType) { + case MUSIC: + case VOICE_CALL: + case BLUETOOTH_SCO: + case SYSTEM: + return true; + default: + return false; + } +} + + + +}; // namespace android + diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp new file mode 100644 index 0000000..e79f336 --- /dev/null +++ b/media/libmedia/AudioTrack.cpp @@ -0,0 +1,1021 @@ +/* //device/extlibs/pv/android/AudioTrack.cpp +** +** Copyright 2007, 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 "AudioTrack" + +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) +#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) + +namespace android { + +// --------------------------------------------------------------------------- + +AudioTrack::AudioTrack() + : mStatus(NO_INIT) +{ +} + +AudioTrack::AudioTrack( + int streamType, + uint32_t sampleRate, + int format, + int channelCount, + int frameCount, + uint32_t flags, + callback_t cbf, + void* user, + int notificationFrames) + : mStatus(NO_INIT) +{ + mStatus = set(streamType, sampleRate, format, channelCount, + frameCount, flags, cbf, user, notificationFrames, 0); +} + +AudioTrack::AudioTrack( + int streamType, + uint32_t sampleRate, + int format, + int channelCount, + const sp& sharedBuffer, + uint32_t flags, + callback_t cbf, + void* user, + int notificationFrames) + : mStatus(NO_INIT) +{ + mStatus = set(streamType, sampleRate, format, channelCount, + 0, flags, cbf, user, notificationFrames, sharedBuffer); +} + +AudioTrack::~AudioTrack() +{ + LOGV_IF(mSharedBuffer != 0, "Destructor sharedBuffer: %p", mSharedBuffer->pointer()); + + if (mStatus == NO_ERROR) { + // Make sure that callback function exits in the case where + // it is looping on buffer full condition in obtainBuffer(). + // Otherwise the callback thread will never exit. + stop(); + if (mAudioTrackThread != 0) { + mCblk->cv.signal(); + mAudioTrackThread->requestExitAndWait(); + mAudioTrackThread.clear(); + } + mAudioTrack.clear(); + IPCThreadState::self()->flushCommands(); + } +} + +status_t AudioTrack::set( + int streamType, + uint32_t sampleRate, + int format, + int channelCount, + int frameCount, + uint32_t flags, + callback_t cbf, + void* user, + int notificationFrames, + const sp& sharedBuffer, + bool threadCanCallJava) +{ + + LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size()); + + if (mAudioFlinger != 0) { + LOGE("Track already in use"); + return INVALID_OPERATION; + } + + const sp& audioFlinger = AudioSystem::get_audio_flinger(); + if (audioFlinger == 0) { + LOGE("Could not get audioflinger"); + return NO_INIT; + } + int afSampleRate; + if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { + return NO_INIT; + } + int afFrameCount; + if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) { + return NO_INIT; + } + uint32_t afLatency; + if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) { + return NO_INIT; + } + + // handle default values first. + if (streamType == AudioSystem::DEFAULT) { + streamType = AudioSystem::MUSIC; + } + if (sampleRate == 0) { + sampleRate = afSampleRate; + } + // these below should probably come from the audioFlinger too... + if (format == 0) { + format = AudioSystem::PCM_16_BIT; + } + if (channelCount == 0) { + channelCount = 2; + } + + // validate parameters + if (((format != AudioSystem::PCM_8_BIT) || sharedBuffer != 0) && + (format != AudioSystem::PCM_16_BIT)) { + LOGE("Invalid format"); + return BAD_VALUE; + } + if (channelCount != 1 && channelCount != 2) { + LOGE("Invalid channel number"); + return BAD_VALUE; + } + + // Ensure that buffer depth covers at least audio hardware latency + uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate); + if (minBufCount < 2) minBufCount = 2; + + // When playing from shared buffer, playback will start even if last audioflinger + // block is partly filled. + if (sharedBuffer != 0 && minBufCount > 1) { + minBufCount--; + } + + int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate; + + if (sharedBuffer == 0) { + if (frameCount == 0) { + frameCount = minFrameCount; + } + if (notificationFrames == 0) { + notificationFrames = frameCount/2; + } + // Make sure that application is notified with sufficient margin + // before underrun + if (notificationFrames > frameCount/2) { + notificationFrames = frameCount/2; + } + } else { + // Ensure that buffer alignment matches channelcount + if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) { + LOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount); + return BAD_VALUE; + } + frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t); + } + + if (frameCount < minFrameCount) { + LOGE("Invalid buffer size: minFrameCount %d, frameCount %d", minFrameCount, frameCount); + return BAD_VALUE; + } + + // create the track + status_t status; + sp track = audioFlinger->createTrack(getpid(), + streamType, sampleRate, format, channelCount, frameCount, flags, sharedBuffer, &status); + + if (track == 0) { + LOGE("AudioFlinger could not create track, status: %d", status); + return status; + } + sp cblk = track->getCblk(); + if (cblk == 0) { + LOGE("Could not get control block"); + return NO_INIT; + } + if (cbf != 0) { + mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava); + if (mAudioTrackThread == 0) { + LOGE("Could not create callback thread"); + return NO_INIT; + } + } + + mStatus = NO_ERROR; + + mAudioFlinger = audioFlinger; + mAudioTrack = track; + mCblkMemory = cblk; + mCblk = static_cast(cblk->pointer()); + mCblk->out = 1; + // Update buffer size in case it has been limited by AudioFlinger during track creation + mFrameCount = mCblk->frameCount; + if (sharedBuffer == 0) { + mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); + } else { + mCblk->buffers = sharedBuffer->pointer(); + // Force buffer full condition as data is already present in shared memory + mCblk->stepUser(mFrameCount); + } + mCblk->volume[0] = mCblk->volume[1] = 0x1000; + mVolume[LEFT] = 1.0f; + mVolume[RIGHT] = 1.0f; + mSampleRate = sampleRate; + mStreamType = streamType; + mFormat = format; + mChannelCount = channelCount; + mSharedBuffer = sharedBuffer; + mMuted = false; + mActive = 0; + mCbf = cbf; + mNotificationFrames = notificationFrames; + mRemainingFrames = notificationFrames; + mUserData = user; + mLatency = afLatency + (1000*mFrameCount) / mSampleRate; + mLoopCount = 0; + mMarkerPosition = 0; + mNewPosition = 0; + mUpdatePeriod = 0; + + return NO_ERROR; +} + +status_t AudioTrack::initCheck() const +{ + return mStatus; +} + +// ------------------------------------------------------------------------- + +uint32_t AudioTrack::latency() const +{ + return mLatency; +} + +int AudioTrack::streamType() const +{ + return mStreamType; +} + +uint32_t AudioTrack::sampleRate() const +{ + return mSampleRate; +} + +int AudioTrack::format() const +{ + return mFormat; +} + +int AudioTrack::channelCount() const +{ + return mChannelCount; +} + +uint32_t AudioTrack::frameCount() const +{ + return mFrameCount; +} + +int AudioTrack::frameSize() const +{ + return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t)); +} + +sp& AudioTrack::sharedBuffer() +{ + return mSharedBuffer; +} + +// ------------------------------------------------------------------------- + +void AudioTrack::start() +{ + sp t = mAudioTrackThread; + + LOGV("start %p", this); + if (t != 0) { + if (t->exitPending()) { + if (t->requestExitAndWait() == WOULD_BLOCK) { + LOGE("AudioTrack::start called from thread"); + return; + } + } + t->mLock.lock(); + } + + if (android_atomic_or(1, &mActive) == 0) { + mNewPosition = mCblk->server + mUpdatePeriod; + mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS; + mCblk->waitTimeMs = 0; + if (t != 0) { + t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT); + } else { + setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT); + } + mAudioTrack->start(); + } + + if (t != 0) { + t->mLock.unlock(); + } +} + +void AudioTrack::stop() +{ + sp t = mAudioTrackThread; + + LOGV("stop %p", this); + if (t != 0) { + t->mLock.lock(); + } + + if (android_atomic_and(~1, &mActive) == 1) { + mAudioTrack->stop(); + // Cancel loops (If we are in the middle of a loop, playback + // would not stop until loopCount reaches 0). + setLoop(0, 0, 0); + // Force flush if a shared buffer is used otherwise audioflinger + // will not stop before end of buffer is reached. + if (mSharedBuffer != 0) { + flush(); + } + if (t != 0) { + t->requestExit(); + } else { + setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL); + } + } + + if (t != 0) { + t->mLock.unlock(); + } +} + +bool AudioTrack::stopped() const +{ + return !mActive; +} + +void AudioTrack::flush() +{ + LOGV("flush"); + + if (!mActive) { + mCblk->lock.lock(); + mAudioTrack->flush(); + // Release AudioTrack callback thread in case it was waiting for new buffers + // in AudioTrack::obtainBuffer() + mCblk->cv.signal(); + mCblk->lock.unlock(); + } +} + +void AudioTrack::pause() +{ + LOGV("pause"); + if (android_atomic_and(~1, &mActive) == 1) { + mActive = 0; + mAudioTrack->pause(); + } +} + +void AudioTrack::mute(bool e) +{ + mAudioTrack->mute(e); + mMuted = e; +} + +bool AudioTrack::muted() const +{ + return mMuted; +} + +void AudioTrack::setVolume(float left, float right) +{ + mVolume[LEFT] = left; + mVolume[RIGHT] = right; + + // write must be atomic + mCblk->volumeLR = (int32_t(int16_t(left * 0x1000)) << 16) | int16_t(right * 0x1000); +} + +void AudioTrack::getVolume(float* left, float* right) +{ + *left = mVolume[LEFT]; + *right = mVolume[RIGHT]; +} + +void AudioTrack::setSampleRate(int rate) +{ + int afSamplingRate; + + if (AudioSystem::getOutputSamplingRate(&afSamplingRate, mStreamType) != NO_ERROR) { + return; + } + // Resampler implementation limits input sampling rate to 2 x output sampling rate. + if (rate <= 0) rate = 1; + if (rate > afSamplingRate*2) rate = afSamplingRate*2; + if (rate > MAX_SAMPLE_RATE) rate = MAX_SAMPLE_RATE; + + mCblk->sampleRate = rate; +} + +uint32_t AudioTrack::getSampleRate() +{ + return uint32_t(mCblk->sampleRate); +} + +status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount) +{ + audio_track_cblk_t* cblk = mCblk; + + + Mutex::Autolock _l(cblk->lock); + + if (loopCount == 0) { + cblk->loopStart = UINT_MAX; + cblk->loopEnd = UINT_MAX; + cblk->loopCount = 0; + mLoopCount = 0; + return NO_ERROR; + } + + if (loopStart >= loopEnd || + loopEnd - loopStart > mFrameCount) { + LOGE("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %d", loopStart, loopEnd, loopCount, mFrameCount, cblk->user); + return BAD_VALUE; + } + + if ((mSharedBuffer != 0) && (loopEnd > mFrameCount)) { + LOGE("setLoop invalid value: loop markers beyond data: loopStart %d, loopEnd %d, framecount %d", + loopStart, loopEnd, mFrameCount); + return BAD_VALUE; + } + + cblk->loopStart = loopStart; + cblk->loopEnd = loopEnd; + cblk->loopCount = loopCount; + mLoopCount = loopCount; + + return NO_ERROR; +} + +status_t AudioTrack::getLoop(uint32_t *loopStart, uint32_t *loopEnd, int *loopCount) +{ + if (loopStart != 0) { + *loopStart = mCblk->loopStart; + } + if (loopEnd != 0) { + *loopEnd = mCblk->loopEnd; + } + if (loopCount != 0) { + if (mCblk->loopCount < 0) { + *loopCount = -1; + } else { + *loopCount = mCblk->loopCount; + } + } + + return NO_ERROR; +} + +status_t AudioTrack::setMarkerPosition(uint32_t marker) +{ + if (mCbf == 0) return INVALID_OPERATION; + + mMarkerPosition = marker; + + return NO_ERROR; +} + +status_t AudioTrack::getMarkerPosition(uint32_t *marker) +{ + if (marker == 0) return BAD_VALUE; + + *marker = mMarkerPosition; + + return NO_ERROR; +} + +status_t AudioTrack::setPositionUpdatePeriod(uint32_t updatePeriod) +{ + if (mCbf == 0) return INVALID_OPERATION; + + uint32_t curPosition; + getPosition(&curPosition); + mNewPosition = curPosition + updatePeriod; + mUpdatePeriod = updatePeriod; + + return NO_ERROR; +} + +status_t AudioTrack::getPositionUpdatePeriod(uint32_t *updatePeriod) +{ + if (updatePeriod == 0) return BAD_VALUE; + + *updatePeriod = mUpdatePeriod; + + return NO_ERROR; +} + +status_t AudioTrack::setPosition(uint32_t position) +{ + Mutex::Autolock _l(mCblk->lock); + + if (!stopped()) return INVALID_OPERATION; + + if (position > mCblk->user) return BAD_VALUE; + + mCblk->server = position; + mCblk->forceReady = 1; + + return NO_ERROR; +} + +status_t AudioTrack::getPosition(uint32_t *position) +{ + if (position == 0) return BAD_VALUE; + + *position = mCblk->server; + + return NO_ERROR; +} + +status_t AudioTrack::reload() +{ + if (!stopped()) return INVALID_OPERATION; + + flush(); + + mCblk->stepUser(mFrameCount); + + return NO_ERROR; +} + +// ------------------------------------------------------------------------- + +status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) +{ + int active; + int timeout = 0; + status_t result; + audio_track_cblk_t* cblk = mCblk; + uint32_t framesReq = audioBuffer->frameCount; + + audioBuffer->frameCount = 0; + audioBuffer->size = 0; + + uint32_t framesAvail = cblk->framesAvailable(); + + if (framesAvail == 0) { + Mutex::Autolock _l(cblk->lock); + goto start_loop_here; + while (framesAvail == 0) { + active = mActive; + if (UNLIKELY(!active)) { + LOGV("Not active and NO_MORE_BUFFERS"); + return NO_MORE_BUFFERS; + } + if (UNLIKELY(!waitCount)) + return WOULD_BLOCK; + timeout = 0; + result = cblk->cv.waitRelative(cblk->lock, milliseconds(WAIT_PERIOD_MS)); + if (__builtin_expect(result!=NO_ERROR, false)) { + cblk->waitTimeMs += WAIT_PERIOD_MS; + if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) { + // timing out when a loop has been set and we have already written upto loop end + // is a normal condition: no need to wake AudioFlinger up. + if (cblk->user < cblk->loopEnd) { + LOGW( "obtainBuffer timed out (is the CPU pegged?) %p " + "user=%08x, server=%08x", this, cblk->user, cblk->server); + //unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140) + cblk->lock.unlock(); + mAudioTrack->start(); + cblk->lock.lock(); + timeout = 1; + } + cblk->waitTimeMs = 0; + } + + if (--waitCount == 0) { + return TIMED_OUT; + } + } + // read the server count again + start_loop_here: + framesAvail = cblk->framesAvailable_l(); + } + } + + cblk->waitTimeMs = 0; + + if (framesReq > framesAvail) { + framesReq = framesAvail; + } + + uint32_t u = cblk->user; + uint32_t bufferEnd = cblk->userBase + cblk->frameCount; + + if (u + framesReq > bufferEnd) { + framesReq = bufferEnd - u; + } + + LOGW_IF(timeout, + "*** SERIOUS WARNING *** obtainBuffer() timed out " + "but didn't need to be locked. We recovered, but " + "this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server); + + audioBuffer->flags = mMuted ? Buffer::MUTE : 0; + audioBuffer->channelCount= mChannelCount; + audioBuffer->format = AudioSystem::PCM_16_BIT; + audioBuffer->frameCount = framesReq; + audioBuffer->size = framesReq*mChannelCount*sizeof(int16_t); + audioBuffer->raw = (int8_t *)cblk->buffer(u); + active = mActive; + return active ? status_t(NO_ERROR) : status_t(STOPPED); +} + +void AudioTrack::releaseBuffer(Buffer* audioBuffer) +{ + audio_track_cblk_t* cblk = mCblk; + cblk->stepUser(audioBuffer->frameCount); +} + +// ------------------------------------------------------------------------- + +ssize_t AudioTrack::write(const void* buffer, size_t userSize) +{ + + if (mSharedBuffer != 0) return INVALID_OPERATION; + + if (ssize_t(userSize) < 0) { + // sanity-check. user is most-likely passing an error code. + LOGE("AudioTrack::write(buffer=%p, size=%u (%d)", + buffer, userSize, userSize); + return BAD_VALUE; + } + + LOGV("write %p: %d bytes, mActive=%d", this, userSize, mActive); + + ssize_t written = 0; + const int8_t *src = (const int8_t *)buffer; + Buffer audioBuffer; + + do { + audioBuffer.frameCount = userSize/mChannelCount; + if (mFormat == AudioSystem::PCM_16_BIT) { + audioBuffer.frameCount >>= 1; + } + // Calling obtainBuffer() with a negative wait count causes + // an (almost) infinite wait time. + status_t err = obtainBuffer(&audioBuffer, -1); + if (err < 0) { + // out of buffers, return #bytes written + if (err == status_t(NO_MORE_BUFFERS)) + break; + return ssize_t(err); + } + + size_t toWrite; + if (mFormat == AudioSystem::PCM_8_BIT) { + // Divide capacity by 2 to take expansion into account + toWrite = audioBuffer.size>>1; + // 8 to 16 bit conversion + int count = toWrite; + int16_t *dst = (int16_t *)(audioBuffer.i8); + while(count--) { + *dst++ = (int16_t)(*src++^0x80) << 8; + } + }else { + toWrite = audioBuffer.size; + memcpy(audioBuffer.i8, src, toWrite); + src += toWrite; + } + userSize -= toWrite; + written += toWrite; + + releaseBuffer(&audioBuffer); + } while (userSize); + + return written; +} + +// ------------------------------------------------------------------------- + +bool AudioTrack::processAudioBuffer(const sp& thread) +{ + Buffer audioBuffer; + uint32_t frames; + size_t writtenSize; + + // Manage underrun callback + if (mActive && (mCblk->framesReady() == 0)) { + LOGV("Underrun user: %x, server: %x, flowControlFlag %d", mCblk->user, mCblk->server, mCblk->flowControlFlag); + if (mCblk->flowControlFlag == 0) { + mCbf(EVENT_UNDERRUN, mUserData, 0); + if (mCblk->server == mCblk->frameCount) { + mCbf(EVENT_BUFFER_END, mUserData, 0); + } + mCblk->flowControlFlag = 1; + if (mSharedBuffer != 0) return false; + } + } + + // Manage loop end callback + while (mLoopCount > mCblk->loopCount) { + int loopCount = -1; + mLoopCount--; + if (mLoopCount >= 0) loopCount = mLoopCount; + + mCbf(EVENT_LOOP_END, mUserData, (void *)&loopCount); + } + + // Manage marker callback + if(mMarkerPosition > 0) { + if (mCblk->server >= mMarkerPosition) { + mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition); + mMarkerPosition = 0; + } + } + + // Manage new position callback + if(mUpdatePeriod > 0) { + while (mCblk->server >= mNewPosition) { + mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition); + mNewPosition += mUpdatePeriod; + } + } + + // If Shared buffer is used, no data is requested from client. + if (mSharedBuffer != 0) { + frames = 0; + } else { + frames = mRemainingFrames; + } + + do { + + audioBuffer.frameCount = frames; + + // Calling obtainBuffer() with a wait count of 1 + // limits wait time to WAIT_PERIOD_MS. This prevents from being + // stuck here not being able to handle timed events (position, markers, loops). + status_t err = obtainBuffer(&audioBuffer, 1); + if (err < NO_ERROR) { + if (err != TIMED_OUT) { + LOGE("Error obtaining an audio buffer, giving up."); + return false; + } + break; + } + if (err == status_t(STOPPED)) return false; + + // Divide buffer size by 2 to take into account the expansion + // due to 8 to 16 bit conversion: the callback must fill only half + // of the destination buffer + if (mFormat == AudioSystem::PCM_8_BIT) { + audioBuffer.size >>= 1; + } + + size_t reqSize = audioBuffer.size; + mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer); + writtenSize = audioBuffer.size; + + // Sanity check on returned size + if (ssize_t(writtenSize) <= 0) break; + if (writtenSize > reqSize) writtenSize = reqSize; + + if (mFormat == AudioSystem::PCM_8_BIT) { + // 8 to 16 bit conversion + const int8_t *src = audioBuffer.i8 + writtenSize-1; + int count = writtenSize; + int16_t *dst = audioBuffer.i16 + writtenSize-1; + while(count--) { + *dst-- = (int16_t)(*src--^0x80) << 8; + } + writtenSize <<= 1; + } + + audioBuffer.size = writtenSize; + audioBuffer.frameCount = writtenSize/mChannelCount/sizeof(int16_t); + frames -= audioBuffer.frameCount; + + releaseBuffer(&audioBuffer); + } + while (frames); + + if (frames == 0) { + mRemainingFrames = mNotificationFrames; + } else { + mRemainingFrames = frames; + } + return true; +} + +status_t AudioTrack::dump(int fd, const Vector& args) const +{ + + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + + result.append(" AudioTrack::dump\n"); + snprintf(buffer, 255, " stream type(%d), left - right volume(%f, %f)\n", mStreamType, mVolume[0], mVolume[1]); + result.append(buffer); + snprintf(buffer, 255, " format(%d), channel count(%d), frame count(%d)\n", mFormat, mChannelCount, mFrameCount); + result.append(buffer); + snprintf(buffer, 255, " sample rate(%d), status(%d), muted(%d)\n", mSampleRate, mStatus, mMuted); + result.append(buffer); + snprintf(buffer, 255, " active(%d), latency (%d)\n", mActive, mLatency); + result.append(buffer); + ::write(fd, result.string(), result.size()); + return NO_ERROR; +} + +// ========================================================================= + +AudioTrack::AudioTrackThread::AudioTrackThread(AudioTrack& receiver, bool bCanCallJava) + : Thread(bCanCallJava), mReceiver(receiver) +{ +} + +bool AudioTrack::AudioTrackThread::threadLoop() +{ + return mReceiver.processAudioBuffer(this); +} + +status_t AudioTrack::AudioTrackThread::readyToRun() +{ + return NO_ERROR; +} + +void AudioTrack::AudioTrackThread::onFirstRef() +{ +} + +// ========================================================================= + +audio_track_cblk_t::audio_track_cblk_t() + : user(0), server(0), userBase(0), serverBase(0), buffers(0), frameCount(0), + loopStart(UINT_MAX), loopEnd(UINT_MAX), loopCount(0), volumeLR(0), flowControlFlag(1), forceReady(0) +{ +} + +uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount) +{ + uint32_t u = this->user; + + u += frameCount; + // Ensure that user is never ahead of server for AudioRecord + if (out) { + // If stepServer() has been called once, switch to normal obtainBuffer() timeout period + if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS-1) { + bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; + } + } else if (u > this->server) { + LOGW("stepServer occured after track reset"); + u = this->server; + } + + if (u >= userBase + this->frameCount) { + userBase += this->frameCount; + } + + this->user = u; + + // Clear flow control error condition as new data has been written/read to/from buffer. + flowControlFlag = 0; + + return u; +} + +bool audio_track_cblk_t::stepServer(uint32_t frameCount) +{ + // the code below simulates lock-with-timeout + // we MUST do this to protect the AudioFlinger server + // as this lock is shared with the client. + status_t err; + + err = lock.tryLock(); + if (err == -EBUSY) { // just wait a bit + usleep(1000); + err = lock.tryLock(); + } + if (err != NO_ERROR) { + // probably, the client just died. + return false; + } + + uint32_t s = this->server; + + s += frameCount; + if (out) { + // Mark that we have read the first buffer so that next time stepUser() is called + // we switch to normal obtainBuffer() timeout period + if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) { + bufferTimeoutMs = MAX_RUN_TIMEOUT_MS - 1; + } + // It is possible that we receive a flush() + // while the mixer is processing a block: in this case, + // stepServer() is called After the flush() has reset u & s and + // we have s > u + if (s > this->user) { + LOGW("stepServer occured after track reset"); + s = this->user; + } + } + + if (s >= loopEnd) { + LOGW_IF(s > loopEnd, "stepServer: s %u > loopEnd %u", s, loopEnd); + s = loopStart; + if (--loopCount == 0) { + loopEnd = UINT_MAX; + loopStart = UINT_MAX; + } + } + if (s >= serverBase + this->frameCount) { + serverBase += this->frameCount; + } + + this->server = s; + + cv.signal(); + lock.unlock(); + return true; +} + +void* audio_track_cblk_t::buffer(uint32_t offset) const +{ + return (int16_t *)this->buffers + (offset-userBase)*this->channels; +} + +uint32_t audio_track_cblk_t::framesAvailable() +{ + Mutex::Autolock _l(lock); + return framesAvailable_l(); +} + +uint32_t audio_track_cblk_t::framesAvailable_l() +{ + uint32_t u = this->user; + uint32_t s = this->server; + + if (out) { + uint32_t limit = (s < loopStart) ? s : loopStart; + return limit + frameCount - u; + } else { + return frameCount + u - s; + } +} + +uint32_t audio_track_cblk_t::framesReady() +{ + uint32_t u = this->user; + uint32_t s = this->server; + + if (out) { + if (u < loopEnd) { + return u - s; + } else { + Mutex::Autolock _l(lock); + if (loopCount >= 0) { + return (loopEnd - loopStart)*loopCount + u - s; + } else { + return UINT_MAX; + } + } + } else { + return s - u; + } +} + +// ------------------------------------------------------------------------- + +}; // namespace android + diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp new file mode 100644 index 0000000..5cbb25c --- /dev/null +++ b/media/libmedia/IAudioFlinger.cpp @@ -0,0 +1,553 @@ +/* //device/extlibs/pv/android/IAudioflinger.cpp +** +** Copyright 2007, 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_TAG "IAudioFlinger" +#include + +#include +#include + +#include + +#include + +namespace android { + +enum { + CREATE_TRACK = IBinder::FIRST_CALL_TRANSACTION, + OPEN_RECORD, + SAMPLE_RATE, + CHANNEL_COUNT, + FORMAT, + FRAME_COUNT, + LATENCY, + SET_MASTER_VOLUME, + SET_MASTER_MUTE, + MASTER_VOLUME, + MASTER_MUTE, + SET_STREAM_VOLUME, + SET_STREAM_MUTE, + STREAM_VOLUME, + STREAM_MUTE, + SET_MODE, + GET_MODE, + SET_ROUTING, + GET_ROUTING, + SET_MIC_MUTE, + GET_MIC_MUTE, + IS_MUSIC_ACTIVE, + SET_PARAMETER, + REGISTER_CLIENT, + GET_INPUTBUFFERSIZE, + WAKE_UP, + IS_A2DP_ENABLED +}; + +class BpAudioFlinger : public BpInterface +{ +public: + BpAudioFlinger(const sp& impl) + : BpInterface(impl) + { + } + + virtual sp createTrack( + pid_t pid, + int streamType, + uint32_t sampleRate, + int format, + int channelCount, + int frameCount, + uint32_t flags, + const sp& sharedBuffer, + status_t *status) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(pid); + data.writeInt32(streamType); + data.writeInt32(sampleRate); + data.writeInt32(format); + data.writeInt32(channelCount); + data.writeInt32(frameCount); + data.writeInt32(flags); + data.writeStrongBinder(sharedBuffer->asBinder()); + status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply); + if (lStatus != NO_ERROR) { + LOGE("createTrack error: %s", strerror(-lStatus)); + } + lStatus = reply.readInt32(); + if (status) { + *status = lStatus; + } + return interface_cast(reply.readStrongBinder()); + } + + virtual sp openRecord( + pid_t pid, + int streamType, + uint32_t sampleRate, + int format, + int channelCount, + int frameCount, + uint32_t flags, + status_t *status) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(pid); + data.writeInt32(streamType); + data.writeInt32(sampleRate); + data.writeInt32(format); + data.writeInt32(channelCount); + data.writeInt32(frameCount); + data.writeInt32(flags); + remote()->transact(OPEN_RECORD, data, &reply); + status_t lStatus = reply.readInt32(); + if (status) { + *status = lStatus; + } + return interface_cast(reply.readStrongBinder()); + } + + virtual uint32_t sampleRate(int output) const + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(output); + remote()->transact(SAMPLE_RATE, data, &reply); + return reply.readInt32(); + } + + virtual int channelCount(int output) const + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(output); + remote()->transact(CHANNEL_COUNT, data, &reply); + return reply.readInt32(); + } + + virtual int format(int output) const + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(output); + remote()->transact(FORMAT, data, &reply); + return reply.readInt32(); + } + + virtual size_t frameCount(int output) const + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(output); + remote()->transact(FRAME_COUNT, data, &reply); + return reply.readInt32(); + } + + virtual uint32_t latency(int output) const + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(output); + remote()->transact(LATENCY, data, &reply); + return reply.readInt32(); + } + + virtual status_t setMasterVolume(float value) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeFloat(value); + remote()->transact(SET_MASTER_VOLUME, data, &reply); + return reply.readInt32(); + } + + virtual status_t setMasterMute(bool muted) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(muted); + remote()->transact(SET_MASTER_MUTE, data, &reply); + return reply.readInt32(); + } + + virtual float masterVolume() const + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + remote()->transact(MASTER_VOLUME, data, &reply); + return reply.readFloat(); + } + + virtual bool masterMute() const + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + remote()->transact(MASTER_MUTE, data, &reply); + return reply.readInt32(); + } + + virtual status_t setStreamVolume(int stream, float value) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(stream); + data.writeFloat(value); + remote()->transact(SET_STREAM_VOLUME, data, &reply); + return reply.readInt32(); + } + + virtual status_t setStreamMute(int stream, bool muted) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(stream); + data.writeInt32(muted); + remote()->transact(SET_STREAM_MUTE, data, &reply); + return reply.readInt32(); + } + + virtual float streamVolume(int stream) const + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(stream); + remote()->transact(STREAM_VOLUME, data, &reply); + return reply.readFloat(); + } + + virtual bool streamMute(int stream) const + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(stream); + remote()->transact(STREAM_MUTE, data, &reply); + return reply.readInt32(); + } + + virtual status_t setRouting(int mode, uint32_t routes, uint32_t mask) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(mode); + data.writeInt32(routes); + data.writeInt32(mask); + remote()->transact(SET_ROUTING, data, &reply); + return reply.readInt32(); + } + + virtual uint32_t getRouting(int mode) const + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(mode); + remote()->transact(GET_ROUTING, data, &reply); + return reply.readInt32(); + } + + virtual status_t setMode(int mode) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(mode); + remote()->transact(SET_MODE, data, &reply); + return reply.readInt32(); + } + + virtual int getMode() const + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + remote()->transact(GET_MODE, data, &reply); + return reply.readInt32(); + } + + virtual status_t setMicMute(bool state) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(state); + remote()->transact(SET_MIC_MUTE, data, &reply); + return reply.readInt32(); + } + + virtual bool getMicMute() const + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + remote()->transact(GET_MIC_MUTE, data, &reply); + return reply.readInt32(); + } + + virtual bool isMusicActive() const + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + remote()->transact(IS_MUSIC_ACTIVE, data, &reply); + return reply.readInt32(); + } + + virtual status_t setParameter(const char* key, const char* value) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeCString(key); + data.writeCString(value); + remote()->transact(SET_PARAMETER, data, &reply); + return reply.readInt32(); + } + + virtual void registerClient(const sp& client) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeStrongBinder(client->asBinder()); + remote()->transact(REGISTER_CLIENT, data, &reply); + } + + virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(sampleRate); + data.writeInt32(format); + data.writeInt32(channelCount); + remote()->transact(GET_INPUTBUFFERSIZE, data, &reply); + return reply.readInt32(); + } + + virtual void wakeUp() + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + remote()->transact(WAKE_UP, data, &reply); + return; + } + + virtual bool isA2dpEnabled() const + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + remote()->transact(IS_A2DP_ENABLED, data, &reply); + return (bool)reply.readInt32(); + } +}; + +IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger"); + +// ---------------------------------------------------------------------- + +#define CHECK_INTERFACE(interface, data, reply) \ + do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ + LOGW("Call incorrectly routed to " #interface); \ + return PERMISSION_DENIED; \ + } } while (0) + +status_t BnAudioFlinger::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch(code) { + case CREATE_TRACK: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + pid_t pid = data.readInt32(); + int streamType = data.readInt32(); + uint32_t sampleRate = data.readInt32(); + int format = data.readInt32(); + int channelCount = data.readInt32(); + size_t bufferCount = data.readInt32(); + uint32_t flags = data.readInt32(); + sp buffer = interface_cast(data.readStrongBinder()); + status_t status; + sp track = createTrack(pid, + streamType, sampleRate, format, + channelCount, bufferCount, flags, buffer, &status); + reply->writeInt32(status); + reply->writeStrongBinder(track->asBinder()); + return NO_ERROR; + } break; + case OPEN_RECORD: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + pid_t pid = data.readInt32(); + int streamType = data.readInt32(); + uint32_t sampleRate = data.readInt32(); + int format = data.readInt32(); + int channelCount = data.readInt32(); + size_t bufferCount = data.readInt32(); + uint32_t flags = data.readInt32(); + status_t status; + sp record = openRecord(pid, streamType, + sampleRate, format, channelCount, bufferCount, flags, &status); + reply->writeInt32(status); + reply->writeStrongBinder(record->asBinder()); + return NO_ERROR; + } break; + case SAMPLE_RATE: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + int output = data.readInt32(); + reply->writeInt32( sampleRate(output) ); + return NO_ERROR; + } break; + case CHANNEL_COUNT: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + int output = data.readInt32(); + reply->writeInt32( channelCount(output) ); + return NO_ERROR; + } break; + case FORMAT: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + int output = data.readInt32(); + reply->writeInt32( format(output) ); + return NO_ERROR; + } break; + case FRAME_COUNT: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + int output = data.readInt32(); + reply->writeInt32( frameCount(output) ); + return NO_ERROR; + } break; + case LATENCY: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + int output = data.readInt32(); + reply->writeInt32( latency(output) ); + return NO_ERROR; + } break; + case SET_MASTER_VOLUME: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + reply->writeInt32( setMasterVolume(data.readFloat()) ); + return NO_ERROR; + } break; + case SET_MASTER_MUTE: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + reply->writeInt32( setMasterMute(data.readInt32()) ); + return NO_ERROR; + } break; + case MASTER_VOLUME: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + reply->writeFloat( masterVolume() ); + return NO_ERROR; + } break; + case MASTER_MUTE: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + reply->writeInt32( masterMute() ); + return NO_ERROR; + } break; + case SET_STREAM_VOLUME: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + int stream = data.readInt32(); + reply->writeInt32( setStreamVolume(stream, data.readFloat()) ); + return NO_ERROR; + } break; + case SET_STREAM_MUTE: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + int stream = data.readInt32(); + reply->writeInt32( setStreamMute(stream, data.readInt32()) ); + return NO_ERROR; + } break; + case STREAM_VOLUME: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + int stream = data.readInt32(); + reply->writeFloat( streamVolume(stream) ); + return NO_ERROR; + } break; + case STREAM_MUTE: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + int stream = data.readInt32(); + reply->writeInt32( streamMute(stream) ); + return NO_ERROR; + } break; + case SET_ROUTING: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + int mode = data.readInt32(); + uint32_t routes = data.readInt32(); + uint32_t mask = data.readInt32(); + reply->writeInt32( setRouting(mode, routes, mask) ); + return NO_ERROR; + } break; + case GET_ROUTING: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + int mode = data.readInt32(); + reply->writeInt32( getRouting(mode) ); + return NO_ERROR; + } break; + case SET_MODE: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + int mode = data.readInt32(); + reply->writeInt32( setMode(mode) ); + return NO_ERROR; + } break; + case GET_MODE: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + reply->writeInt32( getMode() ); + return NO_ERROR; + } break; + case SET_MIC_MUTE: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + int state = data.readInt32(); + reply->writeInt32( setMicMute(state) ); + return NO_ERROR; + } break; + case GET_MIC_MUTE: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + reply->writeInt32( getMicMute() ); + return NO_ERROR; + } break; + case IS_MUSIC_ACTIVE: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + reply->writeInt32( isMusicActive() ); + return NO_ERROR; + } break; + case SET_PARAMETER: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + const char *key = data.readCString(); + const char *value = data.readCString(); + reply->writeInt32( setParameter(key, value) ); + return NO_ERROR; + } break; + case REGISTER_CLIENT: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + sp client = interface_cast(data.readStrongBinder()); + registerClient(client); + return NO_ERROR; + } break; + case GET_INPUTBUFFERSIZE: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + uint32_t sampleRate = data.readInt32(); + int format = data.readInt32(); + int channelCount = data.readInt32(); + reply->writeInt32( getInputBufferSize(sampleRate, format, channelCount) ); + return NO_ERROR; + } break; + case WAKE_UP: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + wakeUp(); + return NO_ERROR; + } break; + case IS_A2DP_ENABLED: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + reply->writeInt32( (int)isA2dpEnabled() ); + return NO_ERROR; + } break; + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +// ---------------------------------------------------------------------------- + +}; // namespace android diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp new file mode 100644 index 0000000..5feb11f --- /dev/null +++ b/media/libmedia/IAudioFlingerClient.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2009 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_TAG "IAudioFlingerClient" +#include + +#include +#include + +#include + +#include + +namespace android { + +enum { + AUDIO_OUTPUT_CHANGED = IBinder::FIRST_CALL_TRANSACTION +}; + +class BpAudioFlingerClient : public BpInterface +{ +public: + BpAudioFlingerClient(const sp& impl) + : BpInterface(impl) + { + } + + void a2dpEnabledChanged(bool enabled) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor()); + data.writeInt32((int)enabled); + remote()->transact(AUDIO_OUTPUT_CHANGED, data, &reply); + } +}; + +IMPLEMENT_META_INTERFACE(AudioFlingerClient, "android.media.IAudioFlingerClient"); + +// ---------------------------------------------------------------------- + +#define CHECK_INTERFACE(interface, data, reply) \ + do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ + LOGW("Call incorrectly routed to " #interface); \ + return PERMISSION_DENIED; \ + } } while (0) + +status_t BnAudioFlingerClient::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch(code) { + case AUDIO_OUTPUT_CHANGED: { + CHECK_INTERFACE(IAudioFlingerClient, data, reply); + bool enabled = (bool)data.readInt32(); + a2dpEnabledChanged(enabled); + return NO_ERROR; + } break; + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +// ---------------------------------------------------------------------------- + +}; // namespace android diff --git a/media/libmedia/IAudioRecord.cpp b/media/libmedia/IAudioRecord.cpp new file mode 100644 index 0000000..6e42dac --- /dev/null +++ b/media/libmedia/IAudioRecord.cpp @@ -0,0 +1,100 @@ +/* +** +** Copyright 2007, 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. +*/ + +#include +#include + +#include + +#include + +namespace android { + +enum { + GET_CBLK = IBinder::FIRST_CALL_TRANSACTION, + START, + STOP +}; + +class BpAudioRecord : public BpInterface +{ +public: + BpAudioRecord(const sp& impl) + : BpInterface(impl) + { + } + + virtual status_t start() + { + Parcel data, reply; + data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor()); + remote()->transact(START, data, &reply); + return reply.readInt32(); + } + + virtual void stop() + { + Parcel data, reply; + data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor()); + remote()->transact(STOP, data, &reply); + } + + virtual sp getCblk() const + { + Parcel data, reply; + data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor()); + remote()->transact(GET_CBLK, data, &reply); + return interface_cast(reply.readStrongBinder()); + } +}; + +IMPLEMENT_META_INTERFACE(AudioRecord, "android.media.IAudioRecord"); + +// ---------------------------------------------------------------------- + +#define CHECK_INTERFACE(interface, data, reply) \ + do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ + LOGW("Call incorrectly routed to " #interface); \ + return PERMISSION_DENIED; \ + } } while (0) + +status_t BnAudioRecord::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch(code) { + case GET_CBLK: { + CHECK_INTERFACE(IAudioRecord, data, reply); + reply->writeStrongBinder(getCblk()->asBinder()); + return NO_ERROR; + } break; + case START: { + CHECK_INTERFACE(IAudioRecord, data, reply); + reply->writeInt32(start()); + return NO_ERROR; + } break; + case STOP: { + CHECK_INTERFACE(IAudioRecord, data, reply); + stop(); + return NO_ERROR; + } break; + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +}; // namespace android + diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp new file mode 100644 index 0000000..abc202d --- /dev/null +++ b/media/libmedia/IAudioTrack.cpp @@ -0,0 +1,140 @@ +/* //device/extlibs/pv/android/IAudioTrack.cpp +** +** Copyright 2007, 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. +*/ + +#include +#include + +#include + +#include + +namespace android { + +enum { + GET_CBLK = IBinder::FIRST_CALL_TRANSACTION, + START, + STOP, + FLUSH, + MUTE, + PAUSE +}; + +class BpAudioTrack : public BpInterface +{ +public: + BpAudioTrack(const sp& impl) + : BpInterface(impl) + { + } + + virtual status_t start() + { + Parcel data, reply; + data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); + remote()->transact(START, data, &reply); + return reply.readInt32(); + } + + virtual void stop() + { + Parcel data, reply; + data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); + remote()->transact(STOP, data, &reply); + } + + virtual void flush() + { + Parcel data, reply; + data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); + remote()->transact(FLUSH, data, &reply); + } + + virtual void mute(bool e) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); + data.writeInt32(e); + remote()->transact(MUTE, data, &reply); + } + + virtual void pause() + { + Parcel data, reply; + data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); + remote()->transact(PAUSE, data, &reply); + } + + virtual sp getCblk() const + { + Parcel data, reply; + data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); + remote()->transact(GET_CBLK, data, &reply); + return interface_cast(reply.readStrongBinder()); + } +}; + +IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack"); + +// ---------------------------------------------------------------------- + +#define CHECK_INTERFACE(interface, data, reply) \ + do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ + LOGW("Call incorrectly routed to " #interface); \ + return PERMISSION_DENIED; \ + } } while (0) + +status_t BnAudioTrack::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch(code) { + case GET_CBLK: { + CHECK_INTERFACE(IAudioTrack, data, reply); + reply->writeStrongBinder(getCblk()->asBinder()); + return NO_ERROR; + } break; + case START: { + CHECK_INTERFACE(IAudioTrack, data, reply); + reply->writeInt32(start()); + return NO_ERROR; + } break; + case STOP: { + CHECK_INTERFACE(IAudioTrack, data, reply); + stop(); + return NO_ERROR; + } break; + case FLUSH: { + CHECK_INTERFACE(IAudioTrack, data, reply); + flush(); + return NO_ERROR; + } break; + case MUTE: { + CHECK_INTERFACE(IAudioTrack, data, reply); + mute( data.readInt32() ); + return NO_ERROR; + } break; + case PAUSE: { + CHECK_INTERFACE(IAudioTrack, data, reply); + pause(); + return NO_ERROR; + } + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +}; // namespace android + diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp new file mode 100644 index 0000000..85b5944 --- /dev/null +++ b/media/libmedia/IMediaMetadataRetriever.cpp @@ -0,0 +1,218 @@ +/* +** +** 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. +*/ + +#include +#include +#include +#include +#include + +namespace android { + +enum { + DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, + SET_DATA_SOURCE_URL, + SET_DATA_SOURCE_FD, + SET_MODE, + GET_MODE, + CAPTURE_FRAME, + EXTARCT_ALBUM_ART, + EXTRACT_METADATA, +}; + +class BpMediaMetadataRetriever: public BpInterface +{ +public: + BpMediaMetadataRetriever(const sp& impl) + : BpInterface(impl) + { + } + + // disconnect from media metadata retriever service + void disconnect() + { + Parcel data, reply; + data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); + remote()->transact(DISCONNECT, data, &reply); + } + + status_t setDataSource(const char* srcUrl) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); + data.writeCString(srcUrl); + remote()->transact(SET_DATA_SOURCE_URL, data, &reply); + return reply.readInt32(); + } + + status_t setDataSource(int fd, int64_t offset, int64_t length) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); + data.writeFileDescriptor(fd); + data.writeInt64(offset); + data.writeInt64(length); + remote()->transact(SET_DATA_SOURCE_FD, data, &reply); + return reply.readInt32(); + } + + status_t setMode(int mode) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); + data.writeInt32(mode); + remote()->transact(SET_MODE, data, &reply); + return reply.readInt32(); + } + + status_t getMode(int* mode) const + { + Parcel data, reply; + data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); + remote()->transact(GET_MODE, data, &reply); + *mode = reply.readInt32(); + return reply.readInt32(); + } + + sp captureFrame() + { + Parcel data, reply; + data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); + remote()->transact(CAPTURE_FRAME, data, &reply); + status_t ret = reply.readInt32(); + if (ret != NO_ERROR) { + return NULL; + } + return interface_cast(reply.readStrongBinder()); + } + + sp extractAlbumArt() + { + Parcel data, reply; + data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); + remote()->transact(EXTARCT_ALBUM_ART, data, &reply); + status_t ret = reply.readInt32(); + if (ret != NO_ERROR) { + return NULL; + } + return interface_cast(reply.readStrongBinder()); + } + + const char* extractMetadata(int keyCode) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); + data.writeInt32(keyCode); + remote()->transact(EXTRACT_METADATA, data, &reply); + status_t ret = reply.readInt32(); + if (ret != NO_ERROR) { + return NULL; + } + return reply.readCString(); + } +}; + +IMPLEMENT_META_INTERFACE(MediaMetadataRetriever, "android.hardware.IMediaMetadataRetriever"); + +// ---------------------------------------------------------------------- + +#define CHECK_INTERFACE(interface, data, reply) \ + do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ + LOGW("Call incorrectly routed to " #interface); \ + return PERMISSION_DENIED; \ + } } while (0) + +status_t BnMediaMetadataRetriever::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch (code) { + case DISCONNECT: { + CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); + disconnect(); + return NO_ERROR; + } break; + case SET_DATA_SOURCE_URL: { + CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); + const char* srcUrl = data.readCString(); + reply->writeInt32(setDataSource(srcUrl)); + return NO_ERROR; + } break; + case SET_DATA_SOURCE_FD: { + CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); + int fd = dup(data.readFileDescriptor()); + int64_t offset = data.readInt64(); + int64_t length = data.readInt64(); + reply->writeInt32(setDataSource(fd, offset, length)); + return NO_ERROR; + } break; + case SET_MODE: { + CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); + int mode = data.readInt32(); + reply->writeInt32(setMode(mode)); + return NO_ERROR; + } break; + case GET_MODE: { + CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); + int mode; + status_t status = getMode(&mode); + reply->writeInt32(mode); + reply->writeInt32(status); + return NO_ERROR; + } break; + case CAPTURE_FRAME: { + CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); + sp bitmap = captureFrame(); + if (bitmap != 0) { // Don't send NULL across the binder interface + reply->writeInt32(NO_ERROR); + reply->writeStrongBinder(bitmap->asBinder()); + } else { + reply->writeInt32(UNKNOWN_ERROR); + } + return NO_ERROR; + } break; + case EXTARCT_ALBUM_ART: { + CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); + sp albumArt = extractAlbumArt(); + if (albumArt != 0) { // Don't send NULL across the binder interface + reply->writeInt32(NO_ERROR); + reply->writeStrongBinder(albumArt->asBinder()); + } else { + reply->writeInt32(UNKNOWN_ERROR); + } + return NO_ERROR; + } break; + case EXTRACT_METADATA: { + CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); + int keyCode = data.readInt32(); + const char* value = extractMetadata(keyCode); + if (value != NULL) { // Don't send NULL across the binder interface + reply->writeInt32(NO_ERROR); + reply->writeCString(value); + } else { + reply->writeInt32(UNKNOWN_ERROR); + } + return NO_ERROR; + } break; + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +// ---------------------------------------------------------------------------- + +}; // namespace android + diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp new file mode 100644 index 0000000..f37519f --- /dev/null +++ b/media/libmedia/IMediaPlayer.cpp @@ -0,0 +1,275 @@ +/* +** +** Copyright 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. +*/ + +#include +#include + +#include + +#include +#include + +namespace android { + +enum { + DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, + SET_VIDEO_SURFACE, + PREPARE_ASYNC, + START, + STOP, + IS_PLAYING, + PAUSE, + SEEK_TO, + GET_CURRENT_POSITION, + GET_DURATION, + RESET, + SET_AUDIO_STREAM_TYPE, + SET_LOOPING, + SET_VOLUME +}; + +class BpMediaPlayer: public BpInterface +{ +public: + BpMediaPlayer(const sp& impl) + : BpInterface(impl) + { + } + + // disconnect from media player service + void disconnect() + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + remote()->transact(DISCONNECT, data, &reply); + } + + status_t setVideoSurface(const sp& surface) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + data.writeStrongBinder(surface->asBinder()); + remote()->transact(SET_VIDEO_SURFACE, data, &reply); + return reply.readInt32(); + } + + status_t prepareAsync() + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + remote()->transact(PREPARE_ASYNC, data, &reply); + return reply.readInt32(); + } + + status_t start() + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + remote()->transact(START, data, &reply); + return reply.readInt32(); + } + + status_t stop() + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + remote()->transact(STOP, data, &reply); + return reply.readInt32(); + } + + status_t isPlaying(bool* state) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + remote()->transact(IS_PLAYING, data, &reply); + *state = reply.readInt32(); + return reply.readInt32(); + } + + status_t pause() + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + remote()->transact(PAUSE, data, &reply); + return reply.readInt32(); + } + + status_t seekTo(int msec) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + data.writeInt32(msec); + remote()->transact(SEEK_TO, data, &reply); + return reply.readInt32(); + } + + status_t getCurrentPosition(int* msec) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + remote()->transact(GET_CURRENT_POSITION, data, &reply); + *msec = reply.readInt32(); + return reply.readInt32(); + } + + status_t getDuration(int* msec) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + remote()->transact(GET_DURATION, data, &reply); + *msec = reply.readInt32(); + return reply.readInt32(); + } + + status_t reset() + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + remote()->transact(RESET, data, &reply); + return reply.readInt32(); + } + + status_t setAudioStreamType(int type) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + data.writeInt32(type); + remote()->transact(SET_AUDIO_STREAM_TYPE, data, &reply); + return reply.readInt32(); + } + + status_t setLooping(int loop) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + data.writeInt32(loop); + remote()->transact(SET_LOOPING, data, &reply); + return reply.readInt32(); + } + + status_t setVolume(float leftVolume, float rightVolume) + { + Parcel data, reply; + data.writeFloat(leftVolume); + data.writeFloat(rightVolume); + remote()->transact(SET_VOLUME, data, &reply); + return reply.readInt32(); + } +}; + +IMPLEMENT_META_INTERFACE(MediaPlayer, "android.hardware.IMediaPlayer"); + +// ---------------------------------------------------------------------- + +#define CHECK_INTERFACE(interface, data, reply) \ + do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ + LOGW("Call incorrectly routed to " #interface); \ + return PERMISSION_DENIED; \ + } } while (0) + +status_t BnMediaPlayer::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch(code) { + case DISCONNECT: { + CHECK_INTERFACE(IMediaPlayer, data, reply); + disconnect(); + return NO_ERROR; + } break; + case SET_VIDEO_SURFACE: { + CHECK_INTERFACE(IMediaPlayer, data, reply); + sp surface = interface_cast(data.readStrongBinder()); + reply->writeInt32(setVideoSurface(surface)); + return NO_ERROR; + } break; + case PREPARE_ASYNC: { + CHECK_INTERFACE(IMediaPlayer, data, reply); + reply->writeInt32(prepareAsync()); + return NO_ERROR; + } break; + case START: { + CHECK_INTERFACE(IMediaPlayer, data, reply); + reply->writeInt32(start()); + return NO_ERROR; + } break; + case STOP: { + CHECK_INTERFACE(IMediaPlayer, data, reply); + reply->writeInt32(stop()); + return NO_ERROR; + } break; + case IS_PLAYING: { + CHECK_INTERFACE(IMediaPlayer, data, reply); + bool state; + status_t ret = isPlaying(&state); + reply->writeInt32(state); + reply->writeInt32(ret); + return NO_ERROR; + } break; + case PAUSE: { + CHECK_INTERFACE(IMediaPlayer, data, reply); + reply->writeInt32(pause()); + return NO_ERROR; + } break; + case SEEK_TO: { + CHECK_INTERFACE(IMediaPlayer, data, reply); + reply->writeInt32(seekTo(data.readInt32())); + return NO_ERROR; + } break; + case GET_CURRENT_POSITION: { + CHECK_INTERFACE(IMediaPlayer, data, reply); + int msec; + status_t ret = getCurrentPosition(&msec); + reply->writeInt32(msec); + reply->writeInt32(ret); + return NO_ERROR; + } break; + case GET_DURATION: { + CHECK_INTERFACE(IMediaPlayer, data, reply); + int msec; + status_t ret = getDuration(&msec); + reply->writeInt32(msec); + reply->writeInt32(ret); + return NO_ERROR; + } break; + case RESET: { + CHECK_INTERFACE(IMediaPlayer, data, reply); + reply->writeInt32(reset()); + return NO_ERROR; + } break; + case SET_AUDIO_STREAM_TYPE: { + CHECK_INTERFACE(IMediaPlayer, data, reply); + reply->writeInt32(setAudioStreamType(data.readInt32())); + return NO_ERROR; + } break; + case SET_LOOPING: { + CHECK_INTERFACE(IMediaPlayer, data, reply); + reply->writeInt32(setLooping(data.readInt32())); + return NO_ERROR; + } break; + case SET_VOLUME: { + reply->writeInt32(setVolume(data.readFloat(), data.readFloat())); + return NO_ERROR; + } break; + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +// ---------------------------------------------------------------------------- + +}; // namespace android + diff --git a/media/libmedia/IMediaPlayerClient.cpp b/media/libmedia/IMediaPlayerClient.cpp new file mode 100644 index 0000000..65022cd --- /dev/null +++ b/media/libmedia/IMediaPlayerClient.cpp @@ -0,0 +1,77 @@ +/* +** +** Copyright 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. +*/ + +#include +#include +#include + +#include + +namespace android { + +enum { + NOTIFY = IBinder::FIRST_CALL_TRANSACTION, +}; + +class BpMediaPlayerClient: public BpInterface +{ +public: + BpMediaPlayerClient(const sp& impl) + : BpInterface(impl) + { + } + + virtual void notify(int msg, int ext1, int ext2) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayerClient::getInterfaceDescriptor()); + data.writeInt32(msg); + data.writeInt32(ext1); + data.writeInt32(ext2); + remote()->transact(NOTIFY, data, &reply, IBinder::FLAG_ONEWAY); + } +}; + +IMPLEMENT_META_INTERFACE(MediaPlayerClient, "android.hardware.IMediaPlayerClient"); + +// ---------------------------------------------------------------------- + +#define CHECK_INTERFACE(interface, data, reply) \ + do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ + LOGW("Call incorrectly routed to " #interface); \ + return PERMISSION_DENIED; \ + } } while (0) + +status_t BnMediaPlayerClient::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch(code) { + case NOTIFY: { + CHECK_INTERFACE(IMediaPlayerClient, data, reply); + int msg = data.readInt32(); + int ext1 = data.readInt32(); + int ext2 = data.readInt32(); + notify(msg, ext1, ext2); + return NO_ERROR; + } break; + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +}; // namespace android + diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp new file mode 100644 index 0000000..370e3fb --- /dev/null +++ b/media/libmedia/IMediaPlayerService.cpp @@ -0,0 +1,198 @@ +/* +** +** Copyright 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. +*/ + +#include +#include +#include + +#include +#include +#include + +namespace android { + +enum { + CREATE_URL = IBinder::FIRST_CALL_TRANSACTION, + CREATE_FD, + DECODE_URL, + DECODE_FD, + CREATE_MEDIA_RECORDER, + CREATE_METADATA_RETRIEVER, +}; + +class BpMediaPlayerService: public BpInterface +{ +public: + BpMediaPlayerService(const sp& impl) + : BpInterface(impl) + { + } + + virtual sp createMetadataRetriever(pid_t pid) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); + data.writeInt32(pid); + remote()->transact(CREATE_METADATA_RETRIEVER, data, &reply); + return interface_cast(reply.readStrongBinder()); + } + + virtual sp create(pid_t pid, const sp& client, const char* url) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); + data.writeInt32(pid); + data.writeStrongBinder(client->asBinder()); + data.writeCString(url); + remote()->transact(CREATE_URL, data, &reply); + return interface_cast(reply.readStrongBinder()); + } + + virtual sp createMediaRecorder(pid_t pid) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); + data.writeInt32(pid); + remote()->transact(CREATE_MEDIA_RECORDER, data, &reply); + return interface_cast(reply.readStrongBinder()); + } + + virtual sp create(pid_t pid, const sp& client, int fd, int64_t offset, int64_t length) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); + data.writeInt32(pid); + data.writeStrongBinder(client->asBinder()); + data.writeFileDescriptor(fd); + data.writeInt64(offset); + data.writeInt64(length); + remote()->transact(CREATE_FD, data, &reply); + return interface_cast(reply.readStrongBinder()); + } + + virtual sp decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); + data.writeCString(url); + remote()->transact(DECODE_URL, data, &reply); + *pSampleRate = uint32_t(reply.readInt32()); + *pNumChannels = reply.readInt32(); + *pFormat = reply.readInt32(); + return interface_cast(reply.readStrongBinder()); + } + + virtual sp decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); + data.writeFileDescriptor(fd); + data.writeInt64(offset); + data.writeInt64(length); + remote()->transact(DECODE_FD, data, &reply); + *pSampleRate = uint32_t(reply.readInt32()); + *pNumChannels = reply.readInt32(); + *pFormat = reply.readInt32(); + return interface_cast(reply.readStrongBinder()); + } +}; + +IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.hardware.IMediaPlayerService"); + +// ---------------------------------------------------------------------- + +#define CHECK_INTERFACE(interface, data, reply) \ + do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ + LOGW("Call incorrectly routed to " #interface); \ + return PERMISSION_DENIED; \ + } } while (0) + +status_t BnMediaPlayerService::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch(code) { + case CREATE_URL: { + CHECK_INTERFACE(IMediaPlayerService, data, reply); + pid_t pid = data.readInt32(); + sp client = interface_cast(data.readStrongBinder()); + const char* url = data.readCString(); + sp player = create(pid, client, url); + reply->writeStrongBinder(player->asBinder()); + return NO_ERROR; + } break; + case CREATE_FD: { + CHECK_INTERFACE(IMediaPlayerService, data, reply); + pid_t pid = data.readInt32(); + sp client = interface_cast(data.readStrongBinder()); + int fd = dup(data.readFileDescriptor()); + int64_t offset = data.readInt64(); + int64_t length = data.readInt64(); + sp player = create(pid, client, fd, offset, length); + reply->writeStrongBinder(player->asBinder()); + return NO_ERROR; + } break; + case DECODE_URL: { + CHECK_INTERFACE(IMediaPlayerService, data, reply); + const char* url = data.readCString(); + uint32_t sampleRate; + int numChannels; + int format; + sp player = decode(url, &sampleRate, &numChannels, &format); + reply->writeInt32(sampleRate); + reply->writeInt32(numChannels); + reply->writeInt32(format); + reply->writeStrongBinder(player->asBinder()); + return NO_ERROR; + } break; + case DECODE_FD: { + CHECK_INTERFACE(IMediaPlayerService, data, reply); + int fd = dup(data.readFileDescriptor()); + int64_t offset = data.readInt64(); + int64_t length = data.readInt64(); + uint32_t sampleRate; + int numChannels; + int format; + sp player = decode(fd, offset, length, &sampleRate, &numChannels, &format); + reply->writeInt32(sampleRate); + reply->writeInt32(numChannels); + reply->writeInt32(format); + reply->writeStrongBinder(player->asBinder()); + return NO_ERROR; + } break; + case CREATE_MEDIA_RECORDER: { + CHECK_INTERFACE(IMediaPlayerService, data, reply); + pid_t pid = data.readInt32(); + sp recorder = createMediaRecorder(pid); + reply->writeStrongBinder(recorder->asBinder()); + return NO_ERROR; + } break; + case CREATE_METADATA_RETRIEVER: { + CHECK_INTERFACE(IMediaPlayerService, data, reply); + pid_t pid = data.readInt32(); + sp retriever = createMetadataRetriever(pid); + reply->writeStrongBinder(retriever->asBinder()); + return NO_ERROR; + } break; + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +// ---------------------------------------------------------------------------- + +}; // namespace android + diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp new file mode 100644 index 0000000..f187bf5 --- /dev/null +++ b/media/libmedia/IMediaRecorder.cpp @@ -0,0 +1,417 @@ +/* + ** + ** 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 "IMediaRecorder" +#include +#include +#include +#include +#include +#include + +namespace android { + +enum { + RELEASE = IBinder::FIRST_CALL_TRANSACTION, + INIT, + CLOSE, + RESET, + STOP, + START, + PREPARE, + GET_MAX_AMPLITUDE, + SET_VIDEO_SOURCE, + SET_AUDIO_SOURCE, + SET_OUTPUT_FORMAT, + SET_VIDEO_ENCODER, + SET_AUDIO_ENCODER, + SET_OUTPUT_FILE_PATH, + SET_OUTPUT_FILE_FD, + SET_VIDEO_SIZE, + SET_VIDEO_FRAMERATE, + SET_PREVIEW_SURFACE, + SET_CAMERA, + SET_LISTENER +}; + +class BpMediaRecorder: public BpInterface +{ +public: + BpMediaRecorder(const sp& impl) + : BpInterface(impl) + { + } + + status_t setCamera(const sp& camera) + { + LOGV("setCamera(%p)", camera.get()); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + data.writeStrongBinder(camera->asBinder()); + remote()->transact(SET_CAMERA, data, &reply); + return reply.readInt32(); + } + + status_t setPreviewSurface(const sp& surface) + { + LOGV("setPreviewSurface(%p)", surface.get()); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + data.writeStrongBinder(surface->asBinder()); + remote()->transact(SET_PREVIEW_SURFACE, data, &reply); + return reply.readInt32(); + } + + status_t init() + { + LOGV("init"); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + remote()->transact(INIT, data, &reply); + return reply.readInt32(); + } + + status_t setVideoSource(int vs) + { + LOGV("setVideoSource(%d)", vs); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + data.writeInt32(vs); + remote()->transact(SET_VIDEO_SOURCE, data, &reply); + return reply.readInt32(); + } + + status_t setAudioSource(int as) + { + LOGV("setAudioSource(%d)", as); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + data.writeInt32(as); + remote()->transact(SET_AUDIO_SOURCE, data, &reply); + return reply.readInt32(); + } + + status_t setOutputFormat(int of) + { + LOGV("setOutputFormat(%d)", of); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + data.writeInt32(of); + remote()->transact(SET_OUTPUT_FORMAT, data, &reply); + return reply.readInt32(); + } + + status_t setVideoEncoder(int ve) + { + LOGV("setVideoEncoder(%d)", ve); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + data.writeInt32(ve); + remote()->transact(SET_VIDEO_ENCODER, data, &reply); + return reply.readInt32(); + } + + status_t setAudioEncoder(int ae) + { + LOGV("setAudioEncoder(%d)", ae); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + data.writeInt32(ae); + remote()->transact(SET_AUDIO_ENCODER, data, &reply); + return reply.readInt32(); + } + + status_t setOutputFile(const char* path) + { + LOGV("setOutputFile(%s)", path); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + data.writeCString(path); + remote()->transact(SET_OUTPUT_FILE_PATH, data, &reply); + return reply.readInt32(); + } + + status_t setOutputFile(int fd, int64_t offset, int64_t length) { + LOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + data.writeFileDescriptor(fd); + data.writeInt64(offset); + data.writeInt64(length); + remote()->transact(SET_OUTPUT_FILE_FD, data, &reply); + return reply.readInt32(); + } + + status_t setVideoSize(int width, int height) + { + LOGV("setVideoSize(%dx%d)", width, height); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + data.writeInt32(width); + data.writeInt32(height); + remote()->transact(SET_VIDEO_SIZE, data, &reply); + return reply.readInt32(); + } + + status_t setVideoFrameRate(int frames_per_second) + { + LOGV("setVideoFrameRate(%d)", frames_per_second); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + data.writeInt32(frames_per_second); + remote()->transact(SET_VIDEO_FRAMERATE, data, &reply); + return reply.readInt32(); + } + + status_t setListener(const sp& listener) + { + LOGV("setListener(%p)", listener.get()); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + data.writeStrongBinder(listener->asBinder()); + remote()->transact(SET_LISTENER, data, &reply); + return reply.readInt32(); + } + + status_t prepare() + { + LOGV("prepare"); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + remote()->transact(PREPARE, data, &reply); + return reply.readInt32(); + } + + status_t getMaxAmplitude(int* max) + { + LOGV("getMaxAmplitude"); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + remote()->transact(GET_MAX_AMPLITUDE, data, &reply); + *max = reply.readInt32(); + return reply.readInt32(); + } + + status_t start() + { + LOGV("start"); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + remote()->transact(START, data, &reply); + return reply.readInt32(); + } + + status_t stop() + { + LOGV("stop"); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + remote()->transact(STOP, data, &reply); + return reply.readInt32(); + } + + status_t reset() + { + LOGV("reset"); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + remote()->transact(RESET, data, &reply); + return reply.readInt32(); + } + + status_t close() + { + LOGV("close"); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + remote()->transact(CLOSE, data, &reply); + return reply.readInt32(); + } + + status_t release() + { + LOGV("release"); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + remote()->transact(RELEASE, data, &reply); + return reply.readInt32(); + } +}; + +IMPLEMENT_META_INTERFACE(MediaRecorder, "android.hardware.IMediaRecorder"); + +// ---------------------------------------------------------------------- + +#define CHECK_INTERFACE(interface, data, reply) \ + do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ + LOGW("Call incorrectly routed to " #interface); \ + return PERMISSION_DENIED; \ + } } while (0) + +status_t BnMediaRecorder::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch(code) { + case RELEASE: { + LOGV("RELEASE"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + reply->writeInt32(release()); + return NO_ERROR; + } break; + case INIT: { + LOGV("INIT"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + reply->writeInt32(init()); + return NO_ERROR; + } break; + case CLOSE: { + LOGV("CLOSE"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + reply->writeInt32(close()); + return NO_ERROR; + } break; + case RESET: { + LOGV("RESET"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + reply->writeInt32(reset()); + return NO_ERROR; + } break; + case STOP: { + LOGV("STOP"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + reply->writeInt32(stop()); + return NO_ERROR; + } break; + case START: { + LOGV("START"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + reply->writeInt32(start()); + return NO_ERROR; + } break; + case PREPARE: { + LOGV("PREPARE"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + reply->writeInt32(prepare()); + return NO_ERROR; + } break; + case GET_MAX_AMPLITUDE: { + LOGV("GET_MAX_AMPLITUDE"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + int max = 0; + status_t ret = getMaxAmplitude(&max); + reply->writeInt32(max); + reply->writeInt32(ret); + return NO_ERROR; + } break; + case SET_VIDEO_SOURCE: { + LOGV("SET_VIDEO_SOURCE"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + int vs = data.readInt32(); + reply->writeInt32(setVideoSource(vs)); + return NO_ERROR; + } break; + case SET_AUDIO_SOURCE: { + LOGV("SET_AUDIO_SOURCE"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + int as = data.readInt32(); + reply->writeInt32(setAudioSource(as)); + return NO_ERROR; + } break; + case SET_OUTPUT_FORMAT: { + LOGV("SET_OUTPUT_FORMAT"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + int of = data.readInt32(); + reply->writeInt32(setOutputFormat(of)); + return NO_ERROR; + } break; + case SET_VIDEO_ENCODER: { + LOGV("SET_VIDEO_ENCODER"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + int ve = data.readInt32(); + reply->writeInt32(setVideoEncoder(ve)); + return NO_ERROR; + } break; + case SET_AUDIO_ENCODER: { + LOGV("SET_AUDIO_ENCODER"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + int ae = data.readInt32(); + reply->writeInt32(setAudioEncoder(ae)); + return NO_ERROR; + + } break; + case SET_OUTPUT_FILE_PATH: { + LOGV("SET_OUTPUT_FILE_PATH"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + const char* path = data.readCString(); + reply->writeInt32(setOutputFile(path)); + return NO_ERROR; + } break; + case SET_OUTPUT_FILE_FD: { + LOGV("SET_OUTPUT_FILE_FD"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + int fd = dup(data.readFileDescriptor()); + int64_t offset = data.readInt64(); + int64_t length = data.readInt64(); + reply->writeInt32(setOutputFile(fd, offset, length)); + return NO_ERROR; + } break; + case SET_VIDEO_SIZE: { + LOGV("SET_VIDEO_SIZE"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + int width = data.readInt32(); + int height = data.readInt32(); + reply->writeInt32(setVideoSize(width, height)); + return NO_ERROR; + } break; + case SET_VIDEO_FRAMERATE: { + LOGV("SET_VIDEO_FRAMERATE"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + int frames_per_second = data.readInt32(); + reply->writeInt32(setVideoFrameRate(frames_per_second)); + return NO_ERROR; + } break; + case SET_LISTENER: { + LOGV("SET_LISTENER"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + sp listener = + interface_cast(data.readStrongBinder()); + reply->writeInt32(setListener(listener)); + return NO_ERROR; + } break; + case SET_PREVIEW_SURFACE: { + LOGV("SET_PREVIEW_SURFACE"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + sp surface = interface_cast(data.readStrongBinder()); + reply->writeInt32(setPreviewSurface(surface)); + return NO_ERROR; + } break; + case SET_CAMERA: { + LOGV("SET_CAMERA"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + sp camera = interface_cast(data.readStrongBinder()); + reply->writeInt32(setCamera(camera)); + return NO_ERROR; + } break; + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +// ---------------------------------------------------------------------------- + +}; // namespace android diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp new file mode 100644 index 0000000..2c62104 --- /dev/null +++ b/media/libmedia/JetPlayer.cpp @@ -0,0 +1,489 @@ +/* + * 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 "JetPlayer-C" + +#include +#include + +#include + + +#ifdef HAVE_GETTID +static pid_t myTid() { return gettid(); } +#else +static pid_t myTid() { return getpid(); } +#endif + + +namespace android +{ + +static const int MIX_NUM_BUFFERS = 4; +static const S_EAS_LIB_CONFIG* pLibConfig = NULL; + +//------------------------------------------------------------------------------------------------- +JetPlayer::JetPlayer(jobject javaJetPlayer, int maxTracks, int trackBufferSize) : + mEventCallback(NULL), + mJavaJetPlayerRef(javaJetPlayer), + mTid(-1), + mRender(false), + mPaused(false), + mMaxTracks(maxTracks), + mEasData(NULL), + mEasJetFileLoc(NULL), + mAudioTrack(NULL), + mTrackBufferSize(trackBufferSize) +{ + LOGV("JetPlayer constructor"); + mPreviousJetStatus.currentUserID = -1; + mPreviousJetStatus.segmentRepeatCount = -1; + mPreviousJetStatus.numQueuedSegments = -1; + mPreviousJetStatus.paused = true; +} + +//------------------------------------------------------------------------------------------------- +JetPlayer::~JetPlayer() +{ + LOGV("~JetPlayer"); + release(); + +} + +//------------------------------------------------------------------------------------------------- +int JetPlayer::init() +{ + //Mutex::Autolock lock(&mMutex); + + EAS_RESULT result; + + // retrieve the EAS library settings + if (pLibConfig == NULL) + pLibConfig = EAS_Config(); + if (pLibConfig == NULL) { + LOGE("JetPlayer::init(): EAS library configuration could not be retrieved, aborting."); + return EAS_FAILURE; + } + + // init the EAS library + result = EAS_Init(&mEasData); + if( result != EAS_SUCCESS) { + LOGE("JetPlayer::init(): Error initializing Sonivox EAS library, aborting."); + mState = EAS_STATE_ERROR; + return result; + } + // init the JET library with the default app event controller range + result = JET_Init(mEasData, NULL, sizeof(S_JET_CONFIG)); + if( result != EAS_SUCCESS) { + LOGE("JetPlayer::init(): Error initializing JET library, aborting."); + mState = EAS_STATE_ERROR; + return result; + } + + // create the output AudioTrack + mAudioTrack = new AudioTrack(); + mAudioTrack->set(AudioSystem::MUSIC, //TODO parametrize this + pLibConfig->sampleRate, + 1, // format = PCM 16bits per sample, + pLibConfig->numChannels, + mTrackBufferSize, + 0); + + // create render and playback thread + { + Mutex::Autolock l(mMutex); + LOGV("JetPlayer::init(): trying to start render thread"); + createThreadEtc(renderThread, this, "jetRenderThread", ANDROID_PRIORITY_AUDIO); + mCondition.wait(mMutex); + } + if (mTid > 0) { + // render thread started, we're ready + LOGV("JetPlayer::init(): render thread(%d) successfully started.", mTid); + mState = EAS_STATE_READY; + } else { + LOGE("JetPlayer::init(): failed to start render thread."); + mState = EAS_STATE_ERROR; + return EAS_FAILURE; + } + + return EAS_SUCCESS; +} + +void JetPlayer::setEventCallback(jetevent_callback eventCallback) +{ + Mutex::Autolock l(mMutex); + mEventCallback = eventCallback; +} + +//------------------------------------------------------------------------------------------------- +int JetPlayer::release() +{ + LOGV("JetPlayer::release()"); + Mutex::Autolock lock(mMutex); + mPaused = true; + mRender = false; + if (mEasData) { + JET_Pause(mEasData); + JET_CloseFile(mEasData); + JET_Shutdown(mEasData); + EAS_Shutdown(mEasData); + } + if (mEasJetFileLoc) { + free(mEasJetFileLoc); + mEasJetFileLoc = NULL; + } + if (mAudioTrack) { + mAudioTrack->stop(); + mAudioTrack->flush(); + delete mAudioTrack; + mAudioTrack = NULL; + } + if (mAudioBuffer) { + delete mAudioBuffer; + mAudioBuffer = NULL; + } + mEasData = NULL; + + return EAS_SUCCESS; +} + + +//------------------------------------------------------------------------------------------------- +int JetPlayer::renderThread(void* p) { + + return ((JetPlayer*)p)->render(); +} + +//------------------------------------------------------------------------------------------------- +int JetPlayer::render() { + EAS_RESULT result = EAS_FAILURE; + EAS_I32 count; + int temp; + bool audioStarted = false; + + LOGV("JetPlayer::render(): entering"); + + // allocate render buffer + mAudioBuffer = + new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * MIX_NUM_BUFFERS]; + if (!mAudioBuffer) { + LOGE("JetPlayer::render(): mAudioBuffer allocate failed"); + goto threadExit; + } + + // signal main thread that we started + { + Mutex::Autolock l(mMutex); + mTid = myTid(); + LOGV("JetPlayer::render(): render thread(%d) signal", mTid); + mCondition.signal(); + } + + while (1) { + mMutex.lock(); // [[[[[[[[ LOCK --------------------------------------- + + // nothing to render, wait for client thread to wake us up + while (!mRender) + { + LOGV("JetPlayer::render(): signal wait"); + if (audioStarted) { + mAudioTrack->pause(); + // we have to restart the playback once we start rendering again + audioStarted = false; + } + mCondition.wait(mMutex); + LOGV("JetPlayer::render(): signal rx'd"); + } + + // render midi data into the input buffer + int num_output = 0; + EAS_PCM* p = mAudioBuffer; + for (int i = 0; i < MIX_NUM_BUFFERS; i++) { + result = EAS_Render(mEasData, p, pLibConfig->mixBufferSize, &count); + if (result != EAS_SUCCESS) { + LOGE("JetPlayer::render(): EAS_Render returned error %ld", result); + } + p += count * pLibConfig->numChannels; + num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM); + + // send events that were generated (if any) to the event callback + fireEventsFromJetQueue(); + } + + // update playback state + //LOGV("JetPlayer::render(): updating state"); + JET_Status(mEasData, &mJetStatus); + fireUpdateOnStatusChange(); + mPaused = mJetStatus.paused; + + mMutex.unlock(); // UNLOCK ]]]]]]]] ----------------------------------- + + // check audio output track + if (mAudioTrack == NULL) { + LOGE("JetPlayer::render(): output AudioTrack was not created"); + goto threadExit; + } + + // Write data to the audio hardware + //LOGV("JetPlayer::render(): writing to audio output"); + if ((temp = mAudioTrack->write(mAudioBuffer, num_output)) < 0) { + LOGE("JetPlayer::render(): Error in writing:%d",temp); + return temp; + } + + // start audio output if necessary + if (!audioStarted) { + LOGV("JetPlayer::render(): starting audio playback"); + mAudioTrack->start(); + audioStarted = true; + } + + }//while (1) + +threadExit: + mAudioTrack->flush(); + if (mAudioBuffer) { + delete [] mAudioBuffer; + mAudioBuffer = NULL; + } + mMutex.lock(); + mTid = -1; + mCondition.signal(); + mMutex.unlock(); + return result; +} + + +//------------------------------------------------------------------------------------------------- +// fire up an update if any of the status fields has changed +// precondition: mMutex locked +void JetPlayer::fireUpdateOnStatusChange() +{ + if( (mJetStatus.currentUserID != mPreviousJetStatus.currentUserID) + ||(mJetStatus.segmentRepeatCount != mPreviousJetStatus.segmentRepeatCount) ) { + if(mEventCallback) { + mEventCallback( + JetPlayer::JET_USERID_UPDATE, + mJetStatus.currentUserID, + mJetStatus.segmentRepeatCount, + mJavaJetPlayerRef); + } + mPreviousJetStatus.currentUserID = mJetStatus.currentUserID; + mPreviousJetStatus.segmentRepeatCount = mJetStatus.segmentRepeatCount; + } + + if(mJetStatus.numQueuedSegments != mPreviousJetStatus.numQueuedSegments) { + if(mEventCallback) { + mEventCallback( + JetPlayer::JET_NUMQUEUEDSEGMENT_UPDATE, + mJetStatus.numQueuedSegments, + -1, + mJavaJetPlayerRef); + } + mPreviousJetStatus.numQueuedSegments = mJetStatus.numQueuedSegments; + } + + if(mJetStatus.paused != mPreviousJetStatus.paused) { + if(mEventCallback) { + mEventCallback(JetPlayer::JET_PAUSE_UPDATE, + mJetStatus.paused, + -1, + mJavaJetPlayerRef); + } + mPreviousJetStatus.paused = mJetStatus.paused; + } + +} + + +//------------------------------------------------------------------------------------------------- +// fire up all the JET events in the JET engine queue (until the queue is empty) +// precondition: mMutex locked +void JetPlayer::fireEventsFromJetQueue() +{ + if(!mEventCallback) { + // no callback, just empty the event queue + while (JET_GetEvent(mEasData, NULL, NULL)) { } + return; + } + + EAS_U32 rawEvent; + while (JET_GetEvent(mEasData, &rawEvent, NULL)) { + mEventCallback( + JetPlayer::JET_EVENT, + rawEvent, + -1, + mJavaJetPlayerRef); + } +} + + +//------------------------------------------------------------------------------------------------- +int JetPlayer::loadFromFile(const char* path) +{ + LOGV("JetPlayer::loadFromFile(): path=%s", path); + + Mutex::Autolock lock(mMutex); + + mEasJetFileLoc = (EAS_FILE_LOCATOR) malloc(sizeof(EAS_FILE)); + memset(mJetFilePath, 0, 256); + strncpy(mJetFilePath, path, strlen(path)); + mEasJetFileLoc->path = mJetFilePath; + + mEasJetFileLoc->fd = 0; + mEasJetFileLoc->length = 0; + mEasJetFileLoc->offset = 0; + + EAS_RESULT result = JET_OpenFile(mEasData, mEasJetFileLoc); + if(result != EAS_SUCCESS) + mState = EAS_STATE_ERROR; + else + mState = EAS_STATE_OPEN; + return( result ); +} + + +//------------------------------------------------------------------------------------------------- +int JetPlayer::loadFromFD(const int fd, const long long offset, const long long length) +{ + LOGV("JetPlayer::loadFromFD(): fd=%d offset=%lld length=%lld", fd, offset, length); + + Mutex::Autolock lock(mMutex); + + mEasJetFileLoc = (EAS_FILE_LOCATOR) malloc(sizeof(EAS_FILE)); + mEasJetFileLoc->fd = fd; + mEasJetFileLoc->offset = offset; + mEasJetFileLoc->length = length; + mEasJetFileLoc->path = NULL; + + EAS_RESULT result = JET_OpenFile(mEasData, mEasJetFileLoc); + if(result != EAS_SUCCESS) + mState = EAS_STATE_ERROR; + else + mState = EAS_STATE_OPEN; + return( result ); +} + + +//------------------------------------------------------------------------------------------------- +int JetPlayer::closeFile() +{ + Mutex::Autolock lock(mMutex); + return JET_CloseFile(mEasData); +} + + +//------------------------------------------------------------------------------------------------- +int JetPlayer::play() +{ + LOGV("JetPlayer::play(): entering"); + Mutex::Autolock lock(mMutex); + + EAS_RESULT result = JET_Play(mEasData); + + mPaused = false; + mRender = true; + + JET_Status(mEasData, &mJetStatus); + this->dumpJetStatus(&mJetStatus); + + fireUpdateOnStatusChange(); + + // wake up render thread + LOGV("JetPlayer::play(): wakeup render thread"); + mCondition.signal(); + + return result; +} + +//------------------------------------------------------------------------------------------------- +int JetPlayer::pause() +{ + Mutex::Autolock lock(mMutex); + mPaused = true; + EAS_RESULT result = JET_Pause(mEasData); + + mRender = false; + + JET_Status(mEasData, &mJetStatus); + this->dumpJetStatus(&mJetStatus); + fireUpdateOnStatusChange(); + + + return result; +} + + +//------------------------------------------------------------------------------------------------- +int JetPlayer::queueSegment(int segmentNum, int libNum, int repeatCount, int transpose, + EAS_U32 muteFlags, EAS_U8 userID) +{ + LOGV("JetPlayer::queueSegment segmentNum=%d, libNum=%d, repeatCount=%d, transpose=%d", + segmentNum, libNum, repeatCount, transpose); + Mutex::Autolock lock(mMutex); + return JET_QueueSegment(mEasData, segmentNum, libNum, repeatCount, transpose, muteFlags, userID); +} + +//------------------------------------------------------------------------------------------------- +int JetPlayer::setMuteFlags(EAS_U32 muteFlags, bool sync) +{ + Mutex::Autolock lock(mMutex); + return JET_SetMuteFlags(mEasData, muteFlags, sync); +} + +//------------------------------------------------------------------------------------------------- +int JetPlayer::setMuteFlag(int trackNum, bool muteFlag, bool sync) +{ + Mutex::Autolock lock(mMutex); + return JET_SetMuteFlag(mEasData, trackNum, muteFlag, sync); +} + +//------------------------------------------------------------------------------------------------- +int JetPlayer::triggerClip(int clipId) +{ + LOGV("JetPlayer::triggerClip clipId=%d", clipId); + Mutex::Autolock lock(mMutex); + return JET_TriggerClip(mEasData, clipId); +} + +//------------------------------------------------------------------------------------------------- +int JetPlayer::clearQueue() +{ + LOGV("JetPlayer::clearQueue"); + Mutex::Autolock lock(mMutex); + return JET_Clear_Queue(mEasData); +} + +//------------------------------------------------------------------------------------------------- +void JetPlayer::dump() +{ + LOGE("JetPlayer dump: JET file=%s", mEasJetFileLoc->path); +} + +void JetPlayer::dumpJetStatus(S_JET_STATUS* pJetStatus) +{ + if(pJetStatus!=NULL) + LOGV(">> current JET player status: userID=%d segmentRepeatCount=%d numQueuedSegments=%d paused=%d", + pJetStatus->currentUserID, pJetStatus->segmentRepeatCount, + pJetStatus->numQueuedSegments, pJetStatus->paused); + else + LOGE(">> JET player status is NULL"); +} + + +} // end namespace android + diff --git a/media/libmedia/MODULE_LICENSE_APACHE2 b/media/libmedia/MODULE_LICENSE_APACHE2 new file mode 100644 index 0000000..e69de29 diff --git a/media/libmedia/NOTICE b/media/libmedia/NOTICE new file mode 100644 index 0000000..c5b1efa --- /dev/null +++ b/media/libmedia/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2005-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. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp new file mode 100644 index 0000000..5416629 --- /dev/null +++ b/media/libmedia/ToneGenerator.cpp @@ -0,0 +1,730 @@ +/* + * 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 "ToneGenerator" +#include + +#include +#include +#include +#include +#include +#include +#include "media/ToneGenerator.h" + +namespace android { + +// Descriptors for all available tones (See ToneGenerator::ToneDescriptor class declaration for details) +const ToneGenerator::ToneDescriptor + ToneGenerator::toneDescriptors[NUM_TONES] = { + // waveFreq[] segments[] repeatCnt + { { 1336, 941, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_0 + { { 1209, 697, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_1 + { { 1336, 697, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_2 + { { 1477, 697, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_3 + { { 1209, 770, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_4 + { { 1336, 770, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_5 + { { 1477, 770, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_6 + { { 1209, 852, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_7 + { { 1336, 852, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_8 + { { 1477, 852, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_9 + { { 1209, 941, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_S + { { 1477, 941, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_P + { { 1633, 697, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_A + { { 1633, 770, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_B + { { 1633, 852, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_C + { { 1633, 941, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_D + { { 425, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_DIAL + { { 425, 0 }, { 500, 500, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_BUSY + { { 425, 0 }, { 200, 200, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_CONGESTION + { { 425, 0 }, { 200, 0 }, 0 }, // TONE_SUP_RADIO_ACK + { { 425, 0 }, { 200, 200, 0 }, 2 }, // TONE_SUP_RADIO_NOTAVAIL + { { 950, 1400, 1800, 0 }, { 330, 1000, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_ERROR + { { 425, 0 }, { 200, 600, 200, 3000, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_CALL_WAITING + { { 425, 0 }, { 1000, 4000, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_RINGTONE + { { 400, 1200, 0 }, { 40, 0 }, 0 }, // TONE_PROP_BEEP + { { 1200, 0 }, { 100, 100, 0 }, 1 }, // TONE_PROP_ACK + { { 300, 400, 500, 0 }, { 400, 0 }, 0 }, // TONE_PROP_NACK + { { 400, 1200, 0 }, { 200, 0 }, 0 }, // TONE_PROP_PROMPT + { { 400, 1200, 0 }, { 40, 200, 40, 0 }, 0 } // TONE_PROP_BEEP2 + }; + +//////////////////////////////////////////////////////////////////////////////// +// ToneGenerator class Implementation +//////////////////////////////////////////////////////////////////////////////// + + +//---------------------------------- public methods ---------------------------- + + +//////////////////////////////////////////////////////////////////////////////// +// +// Method: ToneGenerator::ToneGenerator() +// +// Description: Constructor. Initializes the tone sequencer, intantiates required sine wave +// generators, instantiates output audio track. +// +// Input: +// toneType: Type of tone generated (values in enum tone_type) +// streamType: Type of stream used for tone playback (enum AudioTrack::stream_type) +// volume: volume applied to tone (0.0 to 1.0) +// +// Output: +// none +// +//////////////////////////////////////////////////////////////////////////////// +ToneGenerator::ToneGenerator(int streamType, float volume) { + + LOGV("ToneGenerator constructor: streamType=%d, volume=%f\n", streamType, volume); + + mState = TONE_IDLE; + + if (AudioSystem::getOutputSamplingRate(&mSamplingRate, streamType) != NO_ERROR) { + LOGE("Unable to marshal AudioFlinger"); + return; + } + mStreamType = streamType; + mVolume = volume; + mpAudioTrack = 0; + mpToneDesc = 0; + mpNewToneDesc = 0; + // Generate tone by chunks of 20 ms to keep cadencing precision + mProcessSize = (mSamplingRate * 20) / 1000; + + if (initAudioTrack()) { + LOGV("ToneGenerator INIT OK, time: %d\n", (unsigned int)(systemTime()/1000000)); + } else { + LOGV("!!!ToneGenerator INIT FAILED!!!\n"); + } +} + + + + +//////////////////////////////////////////////////////////////////////////////// +// +// Method: ToneGenerator::~ToneGenerator() +// +// Description: Destructor. Stop sound playback and delete audio track if +// needed and delete sine wave generators. +// +// Input: +// none +// +// Output: +// none +// +//////////////////////////////////////////////////////////////////////////////// +ToneGenerator::~ToneGenerator() { + LOGV("ToneGenerator destructor\n"); + + if (mpAudioTrack) { + stopTone(); + LOGV("Delete Track: %p\n", mpAudioTrack); + delete mpAudioTrack; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +// Method: ToneGenerator::startTone() +// +// Description: Starts tone playback. +// +// Input: +// none +// +// Output: +// none +// +//////////////////////////////////////////////////////////////////////////////// +bool ToneGenerator::startTone(int toneType) { + bool lResult = false; + + if (toneType >= NUM_TONES) + return lResult; + + if (mState == TONE_IDLE) { + LOGV("startTone: try to re-init AudioTrack"); + if (!initAudioTrack()) { + return lResult; + } + } + + LOGV("startTone\n"); + + mLock.lock(); + + // Get descriptor for requested tone + mpNewToneDesc = &toneDescriptors[toneType]; + + if (mState == TONE_INIT) { + if (prepareWave()) { + LOGV("Immediate start, time %d\n", (unsigned int)(systemTime()/1000000)); + lResult = true; + mState = TONE_STARTING; + mLock.unlock(); + mpAudioTrack->start(); + mLock.lock(); + if (mState == TONE_STARTING) { + LOGV("Wait for start callback"); + if (mWaitCbkCond.waitRelative(mLock, seconds(1)) != NO_ERROR) { + LOGE("--- Immediate start timed out"); + mState = TONE_IDLE; + lResult = false; + } + } + } else { + mState == TONE_IDLE; + } + } else { + LOGV("Delayed start\n"); + + mState = TONE_RESTARTING; + if (mWaitCbkCond.waitRelative(mLock, seconds(1)) == NO_ERROR) { + if (mState != TONE_IDLE) { + lResult = true; + } + LOGV("cond received"); + } else { + LOGE("--- Delayed start timed out"); + mState = TONE_IDLE; + } + } + mLock.unlock(); + + LOGV_IF(lResult, "Tone started, time %d\n", (unsigned int)(systemTime()/1000000)); + LOGW_IF(!lResult, "Tone start failed!!!, time %d\n", (unsigned int)(systemTime()/1000000)); + + return lResult; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// Method: ToneGenerator::stopTone() +// +// Description: Stops tone playback. +// +// Input: +// none +// +// Output: +// none +// +//////////////////////////////////////////////////////////////////////////////// +void ToneGenerator::stopTone() { + LOGV("stopTone"); + + mLock.lock(); + if (mState == TONE_PLAYING || mState == TONE_STARTING || mState == TONE_RESTARTING) { + mState = TONE_STOPPING; + LOGV("waiting cond"); + status_t lStatus = mWaitCbkCond.waitRelative(mLock, seconds(1)); + if (lStatus == NO_ERROR) { + LOGV("track stop complete, time %d", (unsigned int)(systemTime()/1000000)); + } else { + LOGE("--- Stop timed out"); + mState = TONE_IDLE; + mpAudioTrack->stop(); + } + } + + clearWaveGens(); + + mLock.unlock(); +} + +//---------------------------------- private methods --------------------------- + + + + +//////////////////////////////////////////////////////////////////////////////// +// +// Method: ToneGenerator::initAudioTrack() +// +// Description: Allocates and configures AudioTrack used for PCM output. +// +// Input: +// none +// +// Output: +// none +// +//////////////////////////////////////////////////////////////////////////////// +bool ToneGenerator::initAudioTrack() { + + if (mpAudioTrack) { + delete mpAudioTrack; + mpAudioTrack = 0; + } + + // Open audio track in mono, PCM 16bit, default sampling rate, default buffer size + mpAudioTrack + = new AudioTrack(mStreamType, 0, AudioSystem::PCM_16_BIT, 1, 0, 0, audioCallback, this, 0); + + if (mpAudioTrack == 0) { + LOGE("AudioTrack allocation failed"); + goto initAudioTrack_exit; + } + LOGV("Create Track: %p\n", mpAudioTrack); + + if (mpAudioTrack->initCheck() != NO_ERROR) { + LOGE("AudioTrack->initCheck failed"); + goto initAudioTrack_exit; + } + + mpAudioTrack->setVolume(mVolume, mVolume); + + mState = TONE_INIT; + + return true; + +initAudioTrack_exit: + + // Cleanup + if (mpAudioTrack) { + LOGV("Delete Track I: %p\n", mpAudioTrack); + delete mpAudioTrack; + mpAudioTrack = 0; + } + + return false; +} + + +//////////////////////////////////////////////////////////////////////////////// +// +// Method: ToneGenerator::audioCallback() +// +// Description: AudioTrack callback implementation. Generates a block of +// PCM samples +// and manages tone generator sequencer: tones pulses, tone duration... +// +// Input: +// user reference (pointer to our ToneGenerator) +// info audio buffer descriptor +// +// Output: +// returned value: always true. +// +//////////////////////////////////////////////////////////////////////////////// +void ToneGenerator::audioCallback(int event, void* user, void *info) { + + if (event != AudioTrack::EVENT_MORE_DATA) return; + + const AudioTrack::Buffer *buffer = static_cast(info); + ToneGenerator *lpToneGen = static_cast(user); + short *lpOut = buffer->i16; + unsigned int lNumSmp = buffer->size/sizeof(short); + + if (buffer->size == 0) return; + + + // Clear output buffer: WaveGenerator accumulates into lpOut buffer + memset(lpOut, 0, buffer->size); + + while (lNumSmp) { + unsigned int lReqSmp = lNumSmp < lpToneGen->mProcessSize*2 ? lNumSmp : lpToneGen->mProcessSize; + unsigned int lGenSmp; + unsigned int lWaveCmd = WaveGenerator::WAVEGEN_CONT; + bool lSignal = false; + + lpToneGen->mLock.lock(); + + // Update pcm frame count and end time (current time at the end of this process) + lpToneGen->mTotalSmp += lReqSmp; + + // Update tone gen state machine and select wave gen command + switch (lpToneGen->mState) { + case TONE_PLAYING: + lWaveCmd = WaveGenerator::WAVEGEN_CONT; + break; + case TONE_STARTING: + LOGV("Starting Cbk"); + + lWaveCmd = WaveGenerator::WAVEGEN_START; + break; + case TONE_STOPPING: + case TONE_RESTARTING: + LOGV("Stop/restart Cbk"); + + lWaveCmd = WaveGenerator::WAVEGEN_STOP; + lpToneGen->mNextSegSmp = TONEGEN_INF; // forced to skip state machine management below + break; + default: + LOGV("Extra Cbk"); + goto audioCallback_EndLoop; + } + + + // Exit if tone sequence is over + if (lpToneGen->mpToneDesc->segments[lpToneGen->mCurSegment] == 0) { + if (lpToneGen->mState == TONE_PLAYING) { + lpToneGen->mState = TONE_STOPPING; + } + goto audioCallback_EndLoop; + } + + if (lpToneGen->mTotalSmp > lpToneGen->mNextSegSmp) { + // Time to go to next sequence segment + + LOGV("End Segment, time: %d\n", (unsigned int)(systemTime()/1000000)); + + lGenSmp = lReqSmp; + + if (lpToneGen->mCurSegment & 0x0001) { + // If odd segment, OFF -> ON transition : reset wave generator + lWaveCmd = WaveGenerator::WAVEGEN_START; + + LOGV("OFF->ON, lGenSmp: %d, lReqSmp: %d\n", lGenSmp, lReqSmp); + } else { + // If even segment, ON -> OFF transition : ramp volume down + lWaveCmd = WaveGenerator::WAVEGEN_STOP; + + LOGV("ON->OFF, lGenSmp: %d, lReqSmp: %d\n", lGenSmp, lReqSmp); + } + + // Pre increment segment index and handle loop if last segment reached + if (lpToneGen->mpToneDesc->segments[++lpToneGen->mCurSegment] == 0) { + LOGV("Last Seg: %d\n", lpToneGen->mCurSegment); + + // Pre increment loop count and restart if total count not reached. Stop sequence otherwise + if (++lpToneGen->mCurCount <= lpToneGen->mpToneDesc->repeatCnt) { + LOGV("Repeating Count: %d\n", lpToneGen->mCurCount); + + lpToneGen->mCurSegment = 0; + + LOGV("New segment %d, Next Time: %d\n", lpToneGen->mCurSegment, + (lpToneGen->mNextSegSmp*1000)/lpToneGen->mSamplingRate); + + } else { + LOGV("End repeat, time: %d\n", (unsigned int)(systemTime()/1000000)); + + // Cancel OFF->ON transition in case previous segment tone state was OFF + if (!(lpToneGen->mCurSegment & 0x0001)) { + lGenSmp = 0; + } + } + } else { + LOGV("New segment %d, Next Time: %d\n", lpToneGen->mCurSegment, + (lpToneGen->mNextSegSmp*1000)/lpToneGen->mSamplingRate); + } + + // Update next segment transition position. No harm to do it also for last segment as lpToneGen->mNextSegSmp won't be used any more + lpToneGen->mNextSegSmp + += (lpToneGen->mpToneDesc->segments[lpToneGen->mCurSegment] * lpToneGen->mSamplingRate) / 1000; + + } else { + // Inside a segment keep tone ON or OFF + if (lpToneGen->mCurSegment & 0x0001) { + lGenSmp = 0; // If odd segment, tone is currently OFF + } else { + lGenSmp = lReqSmp; // If event segment, tone is currently ON + } + } + + if (lGenSmp) { + // If samples must be generated, call all active wave generators and acumulate waves in lpOut + unsigned int lWaveIdx; + + for (lWaveIdx = 0; lWaveIdx < (unsigned int)lpToneGen->mWaveGens.size(); lWaveIdx++) { + WaveGenerator *lpWaveGen = lpToneGen->mWaveGens[lWaveIdx]; + lpWaveGen->getSamples(lpOut, lGenSmp, lWaveCmd); + } + } + + lNumSmp -= lReqSmp; + lpOut += lReqSmp; + +audioCallback_EndLoop: + + switch (lpToneGen->mState) { + case TONE_RESTARTING: + LOGV("Cbk restarting track\n"); + if (lpToneGen->prepareWave()) { + lpToneGen->mState = TONE_STARTING; + } else { + LOGW("Cbk restarting prepareWave() failed\n"); + lpToneGen->mState = TONE_IDLE; + lpToneGen->mpAudioTrack->stop(); + // Force loop exit + lNumSmp = 0; + } + lSignal = true; + break; + case TONE_STOPPING: + lpToneGen->mState = TONE_INIT; + LOGV("Cbk Stopping track\n"); + lSignal = true; + lpToneGen->mpAudioTrack->stop(); + + // Force loop exit + lNumSmp = 0; + break; + case TONE_STARTING: + LOGV("Cbk starting track\n"); + lpToneGen->mState = TONE_PLAYING; + lSignal = true; + break; + default: + break; + } + + if (lSignal) + lpToneGen->mWaitCbkCond.signal(); + lpToneGen->mLock.unlock(); + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// +// Method: ToneGenerator::prepareWave() +// +// Description: Prepare wave generators and reset tone sequencer state machine. +// mpNewToneDesc must have been initialized befoire calling this function. +// Input: +// none +// +// Output: +// returned value: true if wave generators have been created, false otherwise +// +//////////////////////////////////////////////////////////////////////////////// +bool ToneGenerator::prepareWave() { + unsigned int lCnt = 0; + unsigned int lNumWaves; + + if (!mpNewToneDesc) { + return false; + } + // Remove existing wave generators if any + clearWaveGens(); + + mpToneDesc = mpNewToneDesc; + + // Get total number of sine waves: needed to adapt sine wave gain. + lNumWaves = numWaves(); + + // Instantiate as many wave generators as listed in descriptor + while (lCnt < lNumWaves) { + ToneGenerator::WaveGenerator *lpWaveGen = + new ToneGenerator::WaveGenerator((unsigned short)mSamplingRate, + mpToneDesc->waveFreq[lCnt], + TONEGEN_GAIN/lNumWaves); + if (lpWaveGen == 0) { + goto prepareWave_exit; + } + + mWaveGens.push(lpWaveGen); + LOGV("Create sine: %d\n", mpToneDesc->waveFreq[lCnt]); + lCnt++; + } + + // Initialize tone sequencer + mTotalSmp = 0; + mCurSegment = 0; + mCurCount = 0; + mNextSegSmp = (mpToneDesc->segments[0] * mSamplingRate) / 1000; + + return true; + +prepareWave_exit: + + clearWaveGens(); + + return false; +} + + +//////////////////////////////////////////////////////////////////////////////// +// +// Method: ToneGenerator::numWaves() +// +// Description: Count number of sine waves needed to generate tone (e.g 2 for DTMF). +// +// Input: +// none +// +// Output: +// returned value: nummber of sine waves +// +//////////////////////////////////////////////////////////////////////////////// +unsigned int ToneGenerator::numWaves() { + unsigned int lCnt = 0; + + while (mpToneDesc->waveFreq[lCnt]) { + lCnt++; + } + + return lCnt; +} + + +//////////////////////////////////////////////////////////////////////////////// +// +// Method: ToneGenerator::clearWaveGens() +// +// Description: Removes all wave generators. +// +// Input: +// none +// +// Output: +// none +// +//////////////////////////////////////////////////////////////////////////////// +void ToneGenerator::clearWaveGens() { + LOGV("Clearing mWaveGens:"); + + while (!mWaveGens.isEmpty()) { + delete mWaveGens.top(); + mWaveGens.pop(); + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// WaveGenerator::WaveGenerator class Implementation +//////////////////////////////////////////////////////////////////////////////// + +//---------------------------------- public methods ---------------------------- + +//////////////////////////////////////////////////////////////////////////////// +// +// Method: WaveGenerator::WaveGenerator() +// +// Description: Constructor. +// +// Input: +// samplingRate: Output sampling rate in Hz +// frequency: Frequency of the sine wave to generate in Hz +// volume: volume (0.0 to 1.0) +// +// Output: +// none +// +//////////////////////////////////////////////////////////////////////////////// +ToneGenerator::WaveGenerator::WaveGenerator(unsigned short samplingRate, + unsigned short frequency, float volume) { + double d0; + double F_div_Fs; // frequency / samplingRate + + F_div_Fs = frequency / (double)samplingRate; + d0 = - (float)GEN_AMP * sin(2 * M_PI * F_div_Fs); + mS2_0 = (short)d0; + mS1 = 0; + mS2 = mS2_0; + + mAmplitude_Q15 = (short)(32767. * 32767. * volume / GEN_AMP); + // take some margin for amplitude fluctuation + if (mAmplitude_Q15 > 32500) + mAmplitude_Q15 = 32500; + + d0 = 32768.0 * cos(2 * M_PI * F_div_Fs); // Q14*2*cos() + if (d0 > 32767) + d0 = 32767; + mA1_Q14 = (short) d0; + + LOGV("WaveGenerator init, mA1_Q14: %d, mS2_0: %d, mAmplitude_Q15: %d\n", + mA1_Q14, mS2_0, mAmplitude_Q15); +} + +//////////////////////////////////////////////////////////////////////////////// +// +// Method: WaveGenerator::~WaveGenerator() +// +// Description: Destructor. +// +// Input: +// none +// +// Output: +// none +// +//////////////////////////////////////////////////////////////////////////////// +ToneGenerator::WaveGenerator::~WaveGenerator() { +} + +//////////////////////////////////////////////////////////////////////////////// +// +// Method: WaveGenerator::getSamples() +// +// Description: Generates count samples of a sine wave and accumulates +// result in outBuffer. +// +// Input: +// outBuffer: Output buffer where to accumulate samples. +// count: number of samples to produce. +// command: special action requested (see enum gen_command). +// +// Output: +// none +// +//////////////////////////////////////////////////////////////////////////////// +void ToneGenerator::WaveGenerator::getSamples(short *outBuffer, + unsigned int count, unsigned int command) { + long lS1, lS2; + long lA1, lAmplitude; + long Sample; // current sample + + // init local + if (command == WAVEGEN_START) { + lS1 = (long)0; + lS2 = (long)mS2_0; + } else { + lS1 = (long)mS1; + lS2 = (long)mS2; + } + lA1 = (long)mA1_Q14; + lAmplitude = (long)mAmplitude_Q15; + + if (command == WAVEGEN_STOP) { + lAmplitude <<= 16; + if (count == 0) { + return; + } + long dec = lAmplitude/count; + // loop generation + while (count--) { + Sample = ((lA1 * lS1) >> S_Q14) - lS2; + // shift delay + lS2 = lS1; + lS1 = Sample; + Sample = ((lAmplitude>>16) * Sample) >> S_Q15; + *(outBuffer++) += (short)Sample; // put result in buffer + lAmplitude -= dec; + } + } else { + // loop generation + while (count--) { + Sample = ((lA1 * lS1) >> S_Q14) - lS2; + // shift delay + lS2 = lS1; + lS1 = Sample; + Sample = (lAmplitude * Sample) >> S_Q15; + *(outBuffer++) += (short)Sample; // put result in buffer + } + } + + // save status + mS1 = (short)lS1; + mS2 = (short)lS2; +} + +} // end namespace android + diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp new file mode 100644 index 0000000..09afc6c --- /dev/null +++ b/media/libmedia/mediametadataretriever.cpp @@ -0,0 +1,188 @@ +/* +** +** Copyright 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 "MediaMetadataRetriever" + +#include +#include +#include +#include +#include +#include + +namespace android { + +// client singleton for binder interface to service +Mutex MediaMetadataRetriever::sServiceLock; +sp MediaMetadataRetriever::sService; +sp MediaMetadataRetriever::sDeathNotifier; + +const sp& MediaMetadataRetriever::getService() +{ + Mutex::Autolock lock(sServiceLock); + if (sService.get() == 0) { + sp sm = defaultServiceManager(); + sp binder; + do { + binder = sm->getService(String16("media.player")); + if (binder != 0) { + break; + } + LOGW("MediaPlayerService not published, waiting..."); + usleep(500000); // 0.5 s + } while(true); + if (sDeathNotifier == NULL) { + sDeathNotifier = new DeathNotifier(); + } + binder->linkToDeath(sDeathNotifier); + sService = interface_cast(binder); + } + LOGE_IF(sService == 0, "no MediaPlayerService!?"); + return sService; +} + +MediaMetadataRetriever::MediaMetadataRetriever() +{ + LOGV("constructor"); + const sp& service(getService()); + if (service == 0) { + LOGE("failed to obtain MediaMetadataRetrieverService"); + return; + } + sp retriever(service->createMetadataRetriever(getpid())); + if (retriever == 0) { + LOGE("failed to create IMediaMetadataRetriever object from server"); + } + mRetriever = retriever; +} + +MediaMetadataRetriever::~MediaMetadataRetriever() +{ + LOGV("destructor"); + disconnect(); + IPCThreadState::self()->flushCommands(); +} + +void MediaMetadataRetriever::disconnect() +{ + LOGV("disconnect"); + sp retriever; + { + Mutex::Autolock _l(mLock); + retriever = mRetriever; + mRetriever.clear(); + } + if (retriever != 0) { + retriever->disconnect(); + } +} + +status_t MediaMetadataRetriever::setDataSource(const char* srcUrl) +{ + LOGV("setDataSource"); + if (mRetriever == 0) { + LOGE("retriever is not initialized"); + return INVALID_OPERATION; + } + if (srcUrl == NULL) { + LOGE("data source is a null pointer"); + return UNKNOWN_ERROR; + } + LOGV("data source (%s)", srcUrl); + return mRetriever->setDataSource(srcUrl); +} + +status_t MediaMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length) +{ + LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length); + if (mRetriever == 0) { + LOGE("retriever is not initialized"); + return INVALID_OPERATION; + } + if (fd < 0 || offset < 0 || length < 0) { + LOGE("Invalid negative argument"); + return UNKNOWN_ERROR; + } + return mRetriever->setDataSource(fd, offset, length); +} + +status_t MediaMetadataRetriever::setMode(int mode) +{ + LOGV("setMode(%d)", mode); + if (mRetriever == 0) { + LOGE("retriever is not initialized"); + return INVALID_OPERATION; + } + return mRetriever->setMode(mode); +} + +status_t MediaMetadataRetriever::getMode(int* mode) +{ + LOGV("getMode"); + if (mRetriever == 0) { + LOGE("retriever is not initialized"); + return INVALID_OPERATION; + } + return mRetriever->getMode(mode); +} + +sp MediaMetadataRetriever::captureFrame() +{ + LOGV("captureFrame"); + if (mRetriever == 0) { + LOGE("retriever is not initialized"); + return NULL; + } + return mRetriever->captureFrame(); +} + +const char* MediaMetadataRetriever::extractMetadata(int keyCode) +{ + LOGV("extractMetadata(%d)", keyCode); + if (mRetriever == 0) { + LOGE("retriever is not initialized"); + return NULL; + } + return mRetriever->extractMetadata(keyCode); +} + +sp MediaMetadataRetriever::extractAlbumArt() +{ + LOGV("extractAlbumArt"); + if (mRetriever == 0) { + LOGE("retriever is not initialized"); + return NULL; + } + return mRetriever->extractAlbumArt(); +} + +void MediaMetadataRetriever::DeathNotifier::binderDied(const wp& who) { + Mutex::Autolock lock(MediaMetadataRetriever::sServiceLock); + MediaMetadataRetriever::sService.clear(); + LOGW("MediaMetadataRetriever server died!"); +} + +MediaMetadataRetriever::DeathNotifier::~DeathNotifier() +{ + Mutex::Autolock lock(sServiceLock); + if (sService != 0) { + sService->asBinder()->unlinkToDeath(this); + } +} + +}; // namespace android diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp new file mode 100644 index 0000000..bd8579c --- /dev/null +++ b/media/libmedia/mediaplayer.cpp @@ -0,0 +1,624 @@ +/* mediaplayer.cpp +** +** Copyright 2006, 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 "MediaPlayer" +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + +namespace android { + +// client singleton for binder interface to service +Mutex MediaPlayer::sServiceLock; +sp MediaPlayer::sMediaPlayerService; +sp MediaPlayer::sDeathNotifier; +SortedVector< wp > MediaPlayer::sObitRecipients; + +// establish binder interface to service +const sp& MediaPlayer::getMediaPlayerService() +{ + Mutex::Autolock _l(sServiceLock); + if (sMediaPlayerService.get() == 0) { + sp sm = defaultServiceManager(); + sp binder; + do { + binder = sm->getService(String16("media.player")); + if (binder != 0) + break; + LOGW("MediaPlayerService not published, waiting..."); + usleep(500000); // 0.5 s + } while(true); + if (sDeathNotifier == NULL) { + sDeathNotifier = new DeathNotifier(); + } + binder->linkToDeath(sDeathNotifier); + sMediaPlayerService = interface_cast(binder); + } + LOGE_IF(sMediaPlayerService==0, "no MediaPlayerService!?"); + return sMediaPlayerService; +} + +void MediaPlayer::addObitRecipient(const wp& recipient) +{ + Mutex::Autolock _l(sServiceLock); + sObitRecipients.add(recipient); +} + +void MediaPlayer::removeObitRecipient(const wp& recipient) +{ + Mutex::Autolock _l(sServiceLock); + sObitRecipients.remove(recipient); +} + +MediaPlayer::MediaPlayer() +{ + LOGV("constructor"); + mListener = NULL; + mCookie = NULL; + mDuration = -1; + mStreamType = AudioSystem::MUSIC; + mCurrentPosition = -1; + mSeekPosition = -1; + mCurrentState = MEDIA_PLAYER_IDLE; + mPrepareSync = false; + mPrepareStatus = NO_ERROR; + mLoop = false; + mLeftVolume = mRightVolume = 1.0; + mVideoWidth = mVideoHeight = 0; +} + +void MediaPlayer::onFirstRef() +{ + addObitRecipient(this); +} + +MediaPlayer::~MediaPlayer() +{ + LOGV("destructor"); + removeObitRecipient(this); + disconnect(); + IPCThreadState::self()->flushCommands(); +} + +void MediaPlayer::disconnect() +{ + LOGV("disconnect"); + sp p; + { + Mutex::Autolock _l(mLock); + p = mPlayer; + mPlayer.clear(); + } + + if (p != 0) { + p->disconnect(); + } +} + +// always call with lock held +void MediaPlayer::clear_l() +{ + mDuration = -1; + mCurrentPosition = -1; + mSeekPosition = -1; + mVideoWidth = mVideoHeight = 0; +} + +status_t MediaPlayer::setListener(const sp& listener) +{ + LOGV("setListener"); + Mutex::Autolock _l(mLock); + mListener = listener; + return NO_ERROR; +} + + +status_t MediaPlayer::setDataSource(const sp& player) +{ + status_t err = UNKNOWN_ERROR; + sp p; + { // scope for the lock + Mutex::Autolock _l(mLock); + + if ( !( mCurrentState & ( MEDIA_PLAYER_IDLE | MEDIA_PLAYER_STATE_ERROR ) ) ) { + LOGE("setDataSource called in state %d", mCurrentState); + return INVALID_OPERATION; + } + + clear_l(); + p = mPlayer; + mPlayer = player; + if (player != 0) { + mCurrentState = MEDIA_PLAYER_INITIALIZED; + err = NO_ERROR; + } else { + LOGE("Unable to to create media player"); + } + } + + if (p != 0) { + p->disconnect(); + } + + return err; +} + +status_t MediaPlayer::setDataSource(const char *url) +{ + LOGV("setDataSource(%s)", url); + status_t err = BAD_VALUE; + if (url != NULL) { + const sp& service(getMediaPlayerService()); + if (service != 0) { + sp player(service->create(getpid(), this, url)); + err = setDataSource(player); + } + } + return err; +} + +status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length) +{ + LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length); + status_t err = UNKNOWN_ERROR; + const sp& service(getMediaPlayerService()); + if (service != 0) { + sp player(service->create(getpid(), this, fd, offset, length)); + err = setDataSource(player); + } + return err; +} + +status_t MediaPlayer::setVideoSurface(const sp& surface) +{ + LOGV("setVideoSurface"); + Mutex::Autolock _l(mLock); + if (mPlayer == 0) return NO_INIT; + return mPlayer->setVideoSurface(surface->getISurface()); +} + +// must call with lock held +status_t MediaPlayer::prepareAsync_l() +{ + if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) { + mPlayer->setAudioStreamType(mStreamType); + mCurrentState = MEDIA_PLAYER_PREPARING; + return mPlayer->prepareAsync(); + } + LOGE("prepareAsync called in state %d", mCurrentState); + return INVALID_OPERATION; +} + +status_t MediaPlayer::prepare() +{ + LOGV("prepare"); + Mutex::Autolock _l(mLock); + if (mPrepareSync) return -EALREADY; + mPrepareSync = true; + status_t ret = prepareAsync_l(); + if (ret != NO_ERROR) return ret; + + if (mPrepareSync) { + mSignal.wait(mLock); // wait for prepare done + mPrepareSync = false; + } + LOGV("prepare complete - status=%d", mPrepareStatus); + return mPrepareStatus; +} + +status_t MediaPlayer::prepareAsync() +{ + LOGV("prepareAsync"); + Mutex::Autolock _l(mLock); + return prepareAsync_l(); +} + +status_t MediaPlayer::start() +{ + LOGV("start"); + Mutex::Autolock _l(mLock); + if (mCurrentState & MEDIA_PLAYER_STARTED) + return NO_ERROR; + if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED | + MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) { + mPlayer->setLooping(mLoop); + mPlayer->setVolume(mLeftVolume, mRightVolume); + mCurrentState = MEDIA_PLAYER_STARTED; + status_t ret = mPlayer->start(); + if (ret != NO_ERROR) { + mCurrentState = MEDIA_PLAYER_STATE_ERROR; + } else { + if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) { + LOGV("playback completed immediately following start()"); + } + } + return ret; + } + LOGE("start called in state %d", mCurrentState); + return INVALID_OPERATION; +} + +status_t MediaPlayer::stop() +{ + LOGV("stop"); + Mutex::Autolock _l(mLock); + if (mCurrentState & MEDIA_PLAYER_STOPPED) return NO_ERROR; + if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | + MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) ) { + status_t ret = mPlayer->stop(); + if (ret != NO_ERROR) { + mCurrentState = MEDIA_PLAYER_STATE_ERROR; + } else { + mCurrentState = MEDIA_PLAYER_STOPPED; + } + return ret; + } + LOGE("stop called in state %d", mCurrentState); + return INVALID_OPERATION; +} + +status_t MediaPlayer::pause() +{ + LOGV("pause"); + Mutex::Autolock _l(mLock); + if (mCurrentState & MEDIA_PLAYER_PAUSED) + return NO_ERROR; + if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER_STARTED)) { + status_t ret = mPlayer->pause(); + if (ret != NO_ERROR) { + mCurrentState = MEDIA_PLAYER_STATE_ERROR; + } else { + mCurrentState = MEDIA_PLAYER_PAUSED; + } + return ret; + } + LOGE("pause called in state %d", mCurrentState); + return INVALID_OPERATION; +} + +bool MediaPlayer::isPlaying() +{ + Mutex::Autolock _l(mLock); + if (mPlayer != 0) { + bool temp = false; + mPlayer->isPlaying(&temp); + LOGV("isPlaying: %d", temp); + if ((mCurrentState & MEDIA_PLAYER_STARTED) && ! temp) { + LOGE("internal/external state mismatch corrected"); + mCurrentState = MEDIA_PLAYER_PAUSED; + } + return temp; + } + LOGV("isPlaying: no active player"); + return false; +} + +status_t MediaPlayer::getVideoWidth(int *w) +{ + LOGV("getVideoWidth"); + Mutex::Autolock _l(mLock); + if (mPlayer == 0) return INVALID_OPERATION; + *w = mVideoWidth; + return NO_ERROR; +} + +status_t MediaPlayer::getVideoHeight(int *h) +{ + LOGV("getVideoHeight"); + Mutex::Autolock _l(mLock); + if (mPlayer == 0) return INVALID_OPERATION; + *h = mVideoHeight; + return NO_ERROR; +} + +status_t MediaPlayer::getCurrentPosition(int *msec) +{ + LOGV("getCurrentPosition"); + Mutex::Autolock _l(mLock); + if (mPlayer != 0) { + if (mCurrentPosition >= 0) { + LOGV("Using cached seek position: %d", mCurrentPosition); + *msec = mCurrentPosition; + return NO_ERROR; + } + return mPlayer->getCurrentPosition(msec); + } + return INVALID_OPERATION; +} + +status_t MediaPlayer::getDuration_l(int *msec) +{ + LOGV("getDuration"); + bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE)); + if (mPlayer != 0 && isValidState) { + status_t ret = NO_ERROR; + if (mDuration <= 0) + ret = mPlayer->getDuration(&mDuration); + if (msec) + *msec = mDuration; + return ret; + } + LOGE("Attempt to call getDuration without a valid mediaplayer"); + return INVALID_OPERATION; +} + +status_t MediaPlayer::getDuration(int *msec) +{ + Mutex::Autolock _l(mLock); + return getDuration_l(msec); +} + +status_t MediaPlayer::seekTo_l(int msec) +{ + LOGV("seekTo %d", msec); + if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) { + if ( msec < 0 ) { + LOGW("Attempt to seek to invalid position: %d", msec); + msec = 0; + } else if ((mDuration > 0) && (msec > mDuration)) { + LOGW("Attempt to seek to past end of file: request = %d, EOF = %d", msec, mDuration); + msec = mDuration; + } + // cache duration + mCurrentPosition = msec; + if (mSeekPosition < 0) { + getDuration_l(NULL); + mSeekPosition = msec; + return mPlayer->seekTo(msec); + } + else { + LOGV("Seek in progress - queue up seekTo[%d]", msec); + return NO_ERROR; + } + } + LOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(), mCurrentState); + return INVALID_OPERATION; +} + +status_t MediaPlayer::seekTo(int msec) +{ + Mutex::Autolock _l(mLock); + return seekTo_l(msec); +} + +status_t MediaPlayer::reset() +{ + LOGV("reset"); + Mutex::Autolock _l(mLock); + mLoop = false; + if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR; + mPrepareSync = false; + if (mPlayer != 0) { + status_t ret = mPlayer->reset(); + if (ret != NO_ERROR) { + LOGE("reset() failed with return code (%d)", ret); + mCurrentState = MEDIA_PLAYER_STATE_ERROR; + } else { + mCurrentState = MEDIA_PLAYER_IDLE; + } + return ret; + } + clear_l(); + return NO_ERROR; +} + +status_t MediaPlayer::setAudioStreamType(int type) +{ + LOGV("MediaPlayer::setAudioStreamType"); + Mutex::Autolock _l(mLock); + if (mStreamType == type) return NO_ERROR; + if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | + MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) { + // Can't change the stream type after prepare + LOGE("setAudioStream called in state %d", mCurrentState); + return INVALID_OPERATION; + } + // cache + mStreamType = type; + return OK; +} + +status_t MediaPlayer::setLooping(int loop) +{ + LOGV("MediaPlayer::setLooping"); + Mutex::Autolock _l(mLock); + mLoop = (loop != 0); + if (mPlayer != 0) { + return mPlayer->setLooping(loop); + } + return OK; +} + +bool MediaPlayer::isLooping() { + LOGV("isLooping"); + Mutex::Autolock _l(mLock); + if (mPlayer != 0) { + return mLoop; + } + LOGV("isLooping: no active player"); + return false; +} + +status_t MediaPlayer::setVolume(float leftVolume, float rightVolume) +{ + LOGV("MediaPlayer::setVolume(%f, %f)", leftVolume, rightVolume); + Mutex::Autolock _l(mLock); + mLeftVolume = leftVolume; + mRightVolume = rightVolume; + if (mPlayer != 0) { + return mPlayer->setVolume(leftVolume, rightVolume); + } + return OK; +} + +void MediaPlayer::notify(int msg, int ext1, int ext2) +{ + LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2); + bool send = true; + + // TODO: In the future, we might be on the same thread if the app is + // running in the same process as the media server. In that case, + // this will deadlock. + mLock.lock(); + if (mPlayer == 0) { + LOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2); + mLock.unlock(); // release the lock when done. + return; + } + + switch (msg) { + case MEDIA_NOP: // interface test message + break; + case MEDIA_PREPARED: + LOGV("prepared"); + mCurrentState = MEDIA_PLAYER_PREPARED; + if (mPrepareSync) { + LOGV("signal application thread"); + mPrepareSync = false; + mPrepareStatus = NO_ERROR; + mSignal.signal(); + } + break; + case MEDIA_PLAYBACK_COMPLETE: + LOGV("playback complete"); + if (!mLoop) { + mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE; + } + break; + case MEDIA_ERROR: + // Always log errors + LOGE("error (%d, %d)", ext1, ext2); + mCurrentState = MEDIA_PLAYER_STATE_ERROR; + if (mPrepareSync) + { + LOGV("signal application thread"); + mPrepareSync = false; + mPrepareStatus = ext1; + mSignal.signal(); + send = false; + } + break; + case MEDIA_SEEK_COMPLETE: + LOGV("Received seek complete"); + if (mSeekPosition != mCurrentPosition) { + LOGV("Executing queued seekTo(%d)", mSeekPosition); + mSeekPosition = -1; + seekTo_l(mCurrentPosition); + } + else { + LOGV("All seeks complete - return to regularly scheduled program"); + mCurrentPosition = mSeekPosition = -1; + } + break; + case MEDIA_BUFFERING_UPDATE: + LOGV("buffering %d", ext1); + break; + case MEDIA_SET_VIDEO_SIZE: + LOGV("New video size %d x %d", ext1, ext2); + mVideoWidth = ext1; + mVideoHeight = ext2; + break; + default: + LOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2); + break; + } + + sp listener = mListener; + mLock.unlock(); + + // this prevents re-entrant calls into client code + if ((listener != 0) && send) { + Mutex::Autolock _l(mNotifyLock); + LOGV("callback application"); + listener->notify(msg, ext1, ext2); + LOGV("back from callback"); + } +} + +void MediaPlayer::DeathNotifier::binderDied(const wp& who) { + LOGW("MediaPlayer server died!"); + + // Need to do this with the lock held + SortedVector< wp > list; + { + Mutex::Autolock _l(MediaPlayer::sServiceLock); + MediaPlayer::sMediaPlayerService.clear(); + list = sObitRecipients; + } + + // Notify application when media server dies. + // Don't hold the static lock during callback in case app + // makes a call that needs the lock. + size_t count = list.size(); + for (size_t iter = 0; iter < count; ++iter) { + sp player = list[iter].promote(); + if ((player != 0) && (player->mPlayer != 0)) { + player->notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0); + } + } +} + +MediaPlayer::DeathNotifier::~DeathNotifier() +{ + Mutex::Autolock _l(sServiceLock); + sObitRecipients.clear(); + if (sMediaPlayerService != 0) { + sMediaPlayerService->asBinder()->unlinkToDeath(this); + } +} + +/*static*/ sp MediaPlayer::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) +{ + LOGV("decode(%s)", url); + sp p; + const sp& service = getMediaPlayerService(); + if (service != 0) { + p = sMediaPlayerService->decode(url, pSampleRate, pNumChannels, pFormat); + } else { + LOGE("Unable to locate media service"); + } + return p; + +} + +/*static*/ sp MediaPlayer::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 p; + const sp& service = getMediaPlayerService(); + if (service != 0) { + p = sMediaPlayerService->decode(fd, offset, length, pSampleRate, pNumChannels, pFormat); + } else { + LOGE("Unable to locate media service"); + } + return p; + +} + +}; // namespace android diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp new file mode 100644 index 0000000..98aac39 --- /dev/null +++ b/media/libmedia/mediarecorder.cpp @@ -0,0 +1,617 @@ +/* + ** + ** 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 "MediaRecorder" +#include +#include +#include +#include +#include +#include + +namespace android { + +status_t MediaRecorder::setCamera(const sp& camera) +{ + LOGV("setCamera(%p)", camera.get()); + if(mMediaRecorder == NULL) { + LOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + if (!(mCurrentState & MEDIA_RECORDER_IDLE)) { + LOGE("setCamera called in an invalid state(%d)", mCurrentState); + return INVALID_OPERATION; + } + + status_t ret = mMediaRecorder->setCamera(camera); + if (OK != ret) { + LOGV("setCamera failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return UNKNOWN_ERROR; + } + return ret; +} + +status_t MediaRecorder::setPreviewSurface(const sp& surface) +{ + LOGV("setPreviewSurface(%p)", surface.get()); + if(mMediaRecorder == NULL) { + LOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { + LOGE("setPreviewSurface called in an invalid state(%d)", mCurrentState); + return INVALID_OPERATION; + } + if (!mIsVideoSourceSet) { + LOGE("try to set preview surface without setting the video source first"); + return INVALID_OPERATION; + } + + status_t ret = mMediaRecorder->setPreviewSurface(surface->getISurface()); + if (OK != ret) { + LOGV("setPreviewSurface failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return UNKNOWN_ERROR; + } + return ret; +} + +status_t MediaRecorder::init() +{ + LOGV("init"); + if(mMediaRecorder == NULL) { + LOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + if (!(mCurrentState & MEDIA_RECORDER_IDLE)) { + LOGE("init called in an invalid state(%d)", mCurrentState); + return INVALID_OPERATION; + } + + status_t ret = mMediaRecorder->init(); + if (OK != ret) { + LOGV("init failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return UNKNOWN_ERROR; + } + + ret = mMediaRecorder->setListener(this); + if (OK != ret) { + LOGV("setListener failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return UNKNOWN_ERROR; + } + + mCurrentState = MEDIA_RECORDER_INITIALIZED; + return ret; +} + +status_t MediaRecorder::setVideoSource(int vs) +{ + LOGV("setVideoSource(%d)", vs); + if(mMediaRecorder == NULL) { + LOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + if (mIsVideoSourceSet) { + LOGE("video source has already been set"); + return INVALID_OPERATION; + } + if (mCurrentState & MEDIA_RECORDER_IDLE) { + LOGV("Call init() since the media recorder is not initialized yet"); + status_t ret = init(); + if (OK != ret) { + return ret; + } + } + if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { + LOGE("setVideoSource called in an invalid state(%d)", mCurrentState); + return INVALID_OPERATION; + } + + status_t ret = mMediaRecorder->setVideoSource(vs); + if (OK != ret) { + LOGV("setVideoSource failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return UNKNOWN_ERROR; + } + mIsVideoSourceSet = true; + return ret; +} + +status_t MediaRecorder::setAudioSource(int as) +{ + LOGV("setAudioSource(%d)", as); + if(mMediaRecorder == NULL) { + LOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + if (mCurrentState & MEDIA_RECORDER_IDLE) { + LOGV("Call init() since the media recorder is not initialized yet"); + status_t ret = init(); + if (OK != ret) { + return ret; + } + } + if (mIsAudioSourceSet) { + LOGE("audio source has already been set"); + return INVALID_OPERATION; + } + if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { + LOGE("setAudioSource called in an invalid state(%d)", mCurrentState); + return INVALID_OPERATION; + } + + status_t ret = mMediaRecorder->setAudioSource(as); + if (OK != ret) { + LOGV("setAudioSource failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return UNKNOWN_ERROR; + } + mIsAudioSourceSet = true; + return ret; +} + +status_t MediaRecorder::setOutputFormat(int of) +{ + LOGV("setOutputFormat(%d)", of); + if(mMediaRecorder == NULL) { + LOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { + LOGE("setOutputFormat called in an invalid state: %d", mCurrentState); + return INVALID_OPERATION; + } + if (mIsVideoSourceSet && of >= OUTPUT_FORMAT_RAW_AMR) { + LOGE("output format (%d) is meant for audio recording only and incompatible with video recording", of); + return INVALID_OPERATION; + } + + status_t ret = mMediaRecorder->setOutputFormat(of); + if (OK != ret) { + LOGE("setOutputFormat failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return UNKNOWN_ERROR; + } + mCurrentState = MEDIA_RECORDER_DATASOURCE_CONFIGURED; + return ret; +} + +status_t MediaRecorder::setVideoEncoder(int ve) +{ + LOGV("setVideoEncoder(%d)", ve); + if(mMediaRecorder == NULL) { + LOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + if (!mIsVideoSourceSet) { + LOGE("try to set the video encoder without setting the video source first"); + return INVALID_OPERATION; + } + if (mIsVideoEncoderSet) { + LOGE("video encoder has already been set"); + return INVALID_OPERATION; + } + if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { + LOGE("setVideoEncoder called in an invalid state(%d)", mCurrentState); + return INVALID_OPERATION; + } + + status_t ret = mMediaRecorder->setVideoEncoder(ve); + if (OK != ret) { + LOGV("setVideoEncoder failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return UNKNOWN_ERROR; + } + mIsVideoEncoderSet = true; + return ret; +} + +status_t MediaRecorder::setAudioEncoder(int ae) +{ + LOGV("setAudioEncoder(%d)", ae); + if(mMediaRecorder == NULL) { + LOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + if (!mIsAudioSourceSet) { + LOGE("try to set the audio encoder without setting the audio source first"); + return INVALID_OPERATION; + } + if (mIsAudioEncoderSet) { + LOGE("audio encoder has already been set"); + return INVALID_OPERATION; + } + if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { + LOGE("setAudioEncoder called in an invalid state(%d)", mCurrentState); + return INVALID_OPERATION; + } + + status_t ret = mMediaRecorder->setAudioEncoder(ae); + if (OK != ret) { + LOGV("setAudioEncoder failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return UNKNOWN_ERROR; + } + mIsAudioEncoderSet = true; + return ret; +} + +status_t MediaRecorder::setOutputFile(const char* path) +{ + LOGV("setOutputFile(%s)", path); + if(mMediaRecorder == NULL) { + LOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + if (mIsOutputFileSet) { + LOGE("output file has already been set"); + return INVALID_OPERATION; + } + if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { + LOGE("setOutputFile called in an invalid state(%d)", mCurrentState); + return INVALID_OPERATION; + } + + status_t ret = mMediaRecorder->setOutputFile(path); + if (OK != ret) { + LOGV("setOutputFile failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return UNKNOWN_ERROR; + } + mIsOutputFileSet = true; + return ret; +} + +status_t MediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length) +{ + LOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length); + if(mMediaRecorder == NULL) { + LOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + if (mIsOutputFileSet) { + LOGE("output file has already been set"); + return INVALID_OPERATION; + } + if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { + LOGE("setOutputFile called in an invalid state(%d)", mCurrentState); + return INVALID_OPERATION; + } + + status_t ret = mMediaRecorder->setOutputFile(fd, offset, length); + if (OK != ret) { + LOGV("setOutputFile failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return UNKNOWN_ERROR; + } + mIsOutputFileSet = true; + return ret; +} + +status_t MediaRecorder::setVideoSize(int width, int height) +{ + LOGV("setVideoSize(%d, %d)", width, height); + if(mMediaRecorder == NULL) { + LOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { + LOGE("setVideoSize called in an invalid state: %d", mCurrentState); + return INVALID_OPERATION; + } + if (!mIsVideoSourceSet) { + LOGE("try to set video size without setting video source first"); + return INVALID_OPERATION; + } + + status_t ret = mMediaRecorder->setVideoSize(width, height); + if (OK != ret) { + LOGE("setVideoSize failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return UNKNOWN_ERROR; + } + return ret; +} + +status_t MediaRecorder::setVideoFrameRate(int frames_per_second) +{ + LOGV("setVideoFrameRate(%d)", frames_per_second); + if(mMediaRecorder == NULL) { + LOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { + LOGE("setVideoFrameRate called in an invalid state: %d", mCurrentState); + return INVALID_OPERATION; + } + if (!mIsVideoSourceSet) { + LOGE("try to set video frame rate without setting video source first"); + return INVALID_OPERATION; + } + + status_t ret = mMediaRecorder->setVideoFrameRate(frames_per_second); + if (OK != ret) { + LOGE("setVideoFrameRate failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return UNKNOWN_ERROR; + } + return ret; +} + +status_t MediaRecorder::prepare() +{ + LOGV("prepare"); + if(mMediaRecorder == NULL) { + LOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { + LOGE("prepare called in an invalid state: %d", mCurrentState); + return INVALID_OPERATION; + } + if (mIsAudioSourceSet != mIsAudioEncoderSet) { + if (mIsAudioSourceSet) { + LOGE("audio source is set, but audio encoder is not set"); + } else { // must not happen, since setAudioEncoder checks this already + LOGE("audio encoder is set, but audio source is not set"); + } + return INVALID_OPERATION; + } + + if (mIsVideoSourceSet != mIsVideoEncoderSet) { + if (mIsVideoSourceSet) { + LOGE("video source is set, but video encoder is not set"); + } else { // must not happen, since setVideoEncoder checks this already + LOGE("video encoder is set, but video source is not set"); + } + return INVALID_OPERATION; + } + + status_t ret = mMediaRecorder->prepare(); + if (OK != ret) { + LOGE("prepare failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return UNKNOWN_ERROR; + } + mCurrentState = MEDIA_RECORDER_PREPARED; + return ret; +} + +status_t MediaRecorder::getMaxAmplitude(int* max) +{ + LOGV("getMaxAmplitude"); + if(mMediaRecorder == NULL) { + LOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + if (mCurrentState & MEDIA_RECORDER_ERROR) { + LOGE("getMaxAmplitude called in an invalid state: %d", mCurrentState); + return INVALID_OPERATION; + } + + status_t ret = mMediaRecorder->getMaxAmplitude(max); + if (OK != ret) { + LOGE("getMaxAmplitude failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return UNKNOWN_ERROR; + } + return ret; +} + +status_t MediaRecorder::start() +{ + LOGV("start"); + if (mMediaRecorder == NULL) { + LOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + if (!(mCurrentState & MEDIA_RECORDER_PREPARED)) { + LOGE("start called in an invalid state: %d", mCurrentState); + return INVALID_OPERATION; + } + + status_t ret = mMediaRecorder->start(); + if (OK != ret) { + LOGE("start failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return UNKNOWN_ERROR; + } + mCurrentState = MEDIA_RECORDER_RECORDING; + return ret; +} + +status_t MediaRecorder::stop() +{ + LOGV("stop"); + if (mMediaRecorder == NULL) { + LOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + if (!(mCurrentState & MEDIA_RECORDER_RECORDING)) { + LOGE("stop called in an invalid state: %d", mCurrentState); + return INVALID_OPERATION; + } + + status_t ret = mMediaRecorder->stop(); + if (OK != ret) { + LOGE("stop failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return UNKNOWN_ERROR; + } + mCurrentState = MEDIA_RECORDER_IDLE; + return ret; +} + +// Reset should be OK in any state +status_t MediaRecorder::reset() +{ + LOGV("reset"); + if (mMediaRecorder == NULL) { + LOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + + doCleanUp(); + status_t ret = UNKNOWN_ERROR; + switch(mCurrentState) { + case MEDIA_RECORDER_IDLE: + ret = OK; + break; + + case MEDIA_RECORDER_RECORDING: + case MEDIA_RECORDER_DATASOURCE_CONFIGURED: + case MEDIA_RECORDER_PREPARED: + case MEDIA_RECORDER_ERROR: { + ret = doReset(); + if (OK != ret) { + return ret; // No need to continue + } + } // Intentional fall through + case MEDIA_RECORDER_INITIALIZED: + ret = close(); + break; + + default: { + LOGE("Unexpected non-existing state: %d", mCurrentState); + break; + } + } + return ret; +} + +status_t MediaRecorder::close() +{ + LOGV("close"); + if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { + LOGE("close called in an invalid state: %d", mCurrentState); + return INVALID_OPERATION; + } + status_t ret = mMediaRecorder->close(); + if (OK != ret) { + LOGE("close failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return UNKNOWN_ERROR; + } else { + mCurrentState = MEDIA_RECORDER_IDLE; + } + return ret; +} + +status_t MediaRecorder::doReset() +{ + LOGV("doReset"); + status_t ret = mMediaRecorder->reset(); + if (OK != ret) { + LOGE("doReset failed: %d", ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return UNKNOWN_ERROR; + } else { + mCurrentState = MEDIA_RECORDER_INITIALIZED; + } + return ret; +} + +void MediaRecorder::doCleanUp() +{ + LOGV("doCleanUp"); + mIsAudioSourceSet = false; + mIsVideoSourceSet = false; + mIsAudioEncoderSet = false; + mIsVideoEncoderSet = false; + mIsOutputFileSet = false; +} + +// Release should be OK in any state +status_t MediaRecorder::release() +{ + LOGV("release"); + if (mMediaRecorder != NULL) { + return mMediaRecorder->release(); + } + return INVALID_OPERATION; +} + +MediaRecorder::MediaRecorder() +{ + LOGV("constructor"); + sp sm = defaultServiceManager(); + sp binder; + + do { + binder = sm->getService(String16("media.player")); + if (binder != NULL) { + break; + } + LOGW("MediaPlayerService not published, waiting..."); + usleep(500000); // 0.5 s + } while(true); + + sp service = interface_cast(binder); + if (service != NULL) { + mMediaRecorder = service->createMediaRecorder(getpid()); + } + if (mMediaRecorder != NULL) { + mCurrentState = MEDIA_RECORDER_IDLE; + } + doCleanUp(); +} + +status_t MediaRecorder::initCheck() +{ + return mMediaRecorder != 0 ? NO_ERROR : NO_INIT; +} + +MediaRecorder::~MediaRecorder() +{ + LOGV("destructor"); + if (mMediaRecorder != NULL) { + mMediaRecorder.clear(); + } +} + +status_t MediaRecorder::setListener(const sp& listener) +{ + LOGV("setListener"); + Mutex::Autolock _l(mLock); + mListener = listener; + + return NO_ERROR; +} + +void MediaRecorder::notify(int msg, int ext1, int ext2) +{ + LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2); + + sp listener; + mLock.lock(); + listener = mListener; + mLock.unlock(); + + if (listener != NULL) { + Mutex::Autolock _l(mNotifyLock); + LOGV("callback application"); + listener->notify(msg, ext1, ext2); + LOGV("back from callback"); + } +} + +}; // namespace android + diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk new file mode 100644 index 0000000..f710921 --- /dev/null +++ b/media/libmediaplayerservice/Android.mk @@ -0,0 +1,36 @@ +LOCAL_PATH:= $(call my-dir) + +# +# libmediaplayerservice +# + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + MediaRecorderClient.cpp \ + MediaPlayerService.cpp \ + MetadataRetrieverClient.cpp \ + VorbisPlayer.cpp \ + MidiFile.cpp + +ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true) +LOCAL_LDLIBS += -ldl -lpthread +endif + +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + libutils \ + libvorbisidec \ + libsonivox \ + libopencoreplayer \ + libopencoreauthor \ + libmedia \ + libandroid_runtime + +LOCAL_C_INCLUDES := external/tremor/Tremor \ + $(call include-path-for, graphics corecg) + +LOCAL_MODULE:= libmediaplayerservice + +include $(BUILD_SHARED_LIBRARY) + diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp new file mode 100644 index 0000000..40705c6 --- /dev/null +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -0,0 +1,1173 @@ +/* +** +** Copyright 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. +*/ + +// Proxy for media player implementations + +//#define LOG_NDEBUG 0 +#define LOG_TAG "MediaPlayerService" +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "MediaRecorderClient.h" +#include "MediaPlayerService.h" +#include "MetadataRetrieverClient.h" + +#include "MidiFile.h" +#include "VorbisPlayer.h" +#include + +/* desktop Linux needs a little help with gettid() */ +#if defined(HAVE_GETTID) && !defined(HAVE_ANDROID_OS) +#define __KERNEL__ +# include +#ifdef _syscall0 +_syscall0(pid_t,gettid) +#else +pid_t gettid() { return syscall(__NR_gettid);} +#endif +#undef __KERNEL__ +#endif + + +namespace android { + +// TODO: Temp hack until we can register players +typedef struct { + const char *extension; + const player_type playertype; +} extmap; +extmap FILE_EXTS [] = { + {".mid", SONIVOX_PLAYER}, + {".midi", SONIVOX_PLAYER}, + {".smf", SONIVOX_PLAYER}, + {".xmf", SONIVOX_PLAYER}, + {".imy", SONIVOX_PLAYER}, + {".rtttl", SONIVOX_PLAYER}, + {".rtx", SONIVOX_PLAYER}, + {".ota", SONIVOX_PLAYER}, + {".ogg", VORBIS_PLAYER}, + {".oga", VORBIS_PLAYER}, +}; + +// 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; + +void MediaPlayerService::instantiate() { + defaultServiceManager()->addService( + String16("media.player"), new MediaPlayerService()); +} + +MediaPlayerService::MediaPlayerService() +{ + LOGV("MediaPlayerService created"); + mNextConnId = 1; +} + +MediaPlayerService::~MediaPlayerService() +{ + LOGV("MediaPlayerService destroyed"); +} + +sp MediaPlayerService::createMediaRecorder(pid_t pid) +{ + sp recorder = new MediaRecorderClient(pid); + LOGV("Create new media recorder client from pid %d", pid); + return recorder; +} + +sp MediaPlayerService::createMetadataRetriever(pid_t pid) +{ + sp retriever = new MetadataRetrieverClient(pid); + LOGV("Create new media retriever from pid %d", pid); + return retriever; +} + +sp MediaPlayerService::create(pid_t pid, const sp& client, const char* url) +{ + int32_t connId = android_atomic_inc(&mNextConnId); + sp c = new Client(this, pid, connId, client); + LOGV("Create new client(%d) from pid %d, url=%s, connId=%d", connId, pid, url, connId); + if (NO_ERROR != c->setDataSource(url)) + { + c.clear(); + return c; + } + wp w = c; + Mutex::Autolock lock(mLock); + mClients.add(w); + return c; +} + +sp MediaPlayerService::create(pid_t pid, const sp& client, + int fd, int64_t offset, int64_t length) +{ + int32_t connId = android_atomic_inc(&mNextConnId); + sp c = new Client(this, pid, connId, client); + LOGV("Create new client(%d) from pid %d, fd=%d, offset=%lld, length=%lld", + connId, pid, fd, offset, length); + if (NO_ERROR != c->setDataSource(fd, offset, length)) { + c.clear(); + } else { + wp w = c; + Mutex::Autolock lock(mLock); + mClients.add(w); + } + ::close(fd); + return c; +} + +status_t MediaPlayerService::AudioCache::dump(int fd, const Vector& args) const +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + + result.append(" AudioCache\n"); + if (mHeap != 0) { + snprintf(buffer, 255, " heap base(%p), size(%d), flags(%d), device(%s)\n", + mHeap->getBase(), mHeap->getSize(), mHeap->getFlags(), mHeap->getDevice()); + result.append(buffer); + } + 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"); + result.append(buffer); + ::write(fd, result.string(), result.size()); + return NO_ERROR; +} + +status_t MediaPlayerService::AudioOutput::dump(int fd, const Vector& args) const +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + + result.append(" AudioOutput\n"); + 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)\n", + mMsecsPerFrame, mLatency); + result.append(buffer); + ::write(fd, result.string(), result.size()); + if (mTrack != 0) { + mTrack->dump(fd, args); + } + return NO_ERROR; +} + +status_t MediaPlayerService::Client::dump(int fd, const Vector& args) const +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + result.append(" Client\n"); + snprintf(buffer, 255, " pid(%d), connId(%d), status(%d), looping(%s)\n", + mPid, mConnId, mStatus, mLoop?"true": "false"); + result.append(buffer); + write(fd, result.string(), result.size()); + if (mAudioOutput != 0) { + mAudioOutput->dump(fd, args); + } + write(fd, "\n", 1); + return NO_ERROR; +} + +static int myTid() { +#ifdef HAVE_GETTID + return gettid(); +#else + return getpid(); +#endif +} + +#if defined(__arm__) +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); + +void memStatus(int fd, const Vector& args) +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + + typedef struct { + size_t size; + size_t dups; + intptr_t * backtrace; + } AllocEntry; + + uint8_t *info = NULL; + size_t overallSize = 0; + size_t infoSize = 0; + size_t totalMemory = 0; + size_t backtraceSize = 0; + + get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize); + if (info) { + uint8_t *ptr = info; + size_t count = overallSize / infoSize; + + snprintf(buffer, SIZE, " Allocation count %i\n", count); + result.append(buffer); + + AllocEntry * entries = new AllocEntry[count]; + + for (size_t i = 0; i < count; i++) { + // Each entry should be size_t, size_t, intptr_t[backtraceSize] + AllocEntry *e = &entries[i]; + + e->size = *reinterpret_cast(ptr); + ptr += sizeof(size_t); + + e->dups = *reinterpret_cast(ptr); + ptr += sizeof(size_t); + + e->backtrace = reinterpret_cast(ptr); + ptr += sizeof(intptr_t) * backtraceSize; + } + + // Now we need to sort the entries. They come sorted by size but + // not by stack trace which causes problems using diff. + bool moved; + do { + moved = false; + for (size_t i = 0; i < (count - 1); i++) { + AllocEntry *e1 = &entries[i]; + AllocEntry *e2 = &entries[i+1]; + + bool swap = e1->size < e2->size; + if (e1->size == e2->size) { + for(size_t j = 0; j < backtraceSize; j++) { + if (e1->backtrace[j] == e2->backtrace[j]) { + continue; + } + swap = e1->backtrace[j] < e2->backtrace[j]; + break; + } + } + if (swap) { + AllocEntry t = entries[i]; + entries[i] = entries[i+1]; + entries[i+1] = t; + moved = true; + } + } + } while (moved); + + for (size_t i = 0; i < count; i++) { + AllocEntry *e = &entries[i]; + + snprintf(buffer, SIZE, "size %8i, dup %4i", e->size, e->dups); + result.append(buffer); + for (size_t ct = 0; (ct < backtraceSize) && e->backtrace[ct]; ct++) { + if (ct) { + result.append(", "); + } + snprintf(buffer, SIZE, "0x%08x", e->backtrace[ct]); + result.append(buffer); + } + result.append("\n"); + } + + delete[] entries; + free_malloc_leak_info(info); + } + + write(fd, result.string(), result.size()); +} +#endif + +status_t MediaPlayerService::dump(int fd, const Vector& args) +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + if (checkCallingPermission(String16("android.permission.DUMP")) == false) { + snprintf(buffer, SIZE, "Permission Denial: " + "can't dump MediaPlayerService from pid=%d, uid=%d\n", + IPCThreadState::self()->getCallingPid(), + IPCThreadState::self()->getCallingUid()); + result.append(buffer); + } else { + Mutex::Autolock lock(mLock); + for (int i = 0, n = mClients.size(); i < n; ++i) { + sp c = mClients[i].promote(); + if (c != 0) c->dump(fd, args); + } + result.append(" Files opened and/or mapped:\n"); + snprintf(buffer, SIZE, "/proc/%d/maps", myTid()); + FILE *f = fopen(buffer, "r"); + if (f) { + while (!feof(f)) { + fgets(buffer, SIZE, f); + if (strstr(buffer, " /sdcard/") || + strstr(buffer, " /system/sounds/") || + strstr(buffer, " /system/media/")) { + result.append(" "); + result.append(buffer); + } + } + fclose(f); + } else { + result.append("couldn't open "); + result.append(buffer); + result.append("\n"); + } + + snprintf(buffer, SIZE, "/proc/%d/fd", myTid()); + DIR *d = opendir(buffer); + if (d) { + struct dirent *ent; + while((ent = readdir(d)) != NULL) { + 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) { + if ((s.st_mode & S_IFMT) == S_IFLNK) { + char linkto[256]; + int len = readlink(buffer, linkto, sizeof(linkto)); + if(len > 0) { + if(len > 255) { + linkto[252] = '.'; + linkto[253] = '.'; + linkto[254] = '.'; + linkto[255] = 0; + } else { + linkto[len] = 0; + } + if (strstr(linkto, "/sdcard/") == linkto || + strstr(linkto, "/system/sounds/") == linkto || + strstr(linkto, "/system/media/") == linkto) { + result.append(" "); + result.append(buffer); + result.append(" -> "); + result.append(linkto); + result.append("\n"); + } + } + } else { + result.append(" unexpected type for "); + result.append(buffer); + result.append("\n"); + } + } + } + } + closedir(d); + } else { + result.append("couldn't open "); + result.append(buffer); + result.append("\n"); + } + +#if defined(__arm__) + bool dumpMem = false; + for (size_t i = 0; i < args.size(); i++) { + if (args[i] == String16("-m")) { + dumpMem = true; + } + } + if (dumpMem) { + memStatus(fd, args); + } +#endif + } + write(fd, result.string(), result.size()); + return NO_ERROR; +} + +void MediaPlayerService::removeClient(wp client) +{ + Mutex::Autolock lock(mLock); + mClients.remove(client); +} + +MediaPlayerService::Client::Client(const sp& service, pid_t pid, + int32_t connId, const sp& client) +{ + LOGV("Client(%d) constructor", connId); + mPid = pid; + mConnId = connId; + mService = service; + mClient = client; + mLoop = false; + mStatus = NO_INIT; +#if CALLBACK_ANTAGONIZER + LOGD("create Antagonizer"); + mAntagonizer = new Antagonizer(notify, this); +#endif +} + +MediaPlayerService::Client::~Client() +{ + LOGV("Client(%d) destructor pid = %d", mConnId, mPid); + mAudioOutput.clear(); + wp client(this); + disconnect(); + mService->removeClient(client); +} + +void MediaPlayerService::Client::disconnect() +{ + LOGV("disconnect(%d) from pid %d", mConnId, mPid); + // grab local reference and clear main reference to prevent future + // access to object + sp p; + { + Mutex::Autolock l(mLock); + p = mPlayer; + } + mPlayer.clear(); + + // clear the notification to prevent callbacks to dead client + // and reset the player. We assume the player will serialize + // access to itself if necessary. + if (p != 0) { + p->setNotifyCallback(0, 0); +#if CALLBACK_ANTAGONIZER + LOGD("kill Antagonizer"); + mAntagonizer->kill(); +#endif + p->reset(); + } + + IPCThreadState::self()->flushCommands(); +} + +static player_type getPlayerType(int fd, int64_t offset, int64_t length) +{ + char buf[20]; + lseek(fd, offset, SEEK_SET); + read(fd, buf, sizeof(buf)); + lseek(fd, offset, SEEK_SET); + + long ident = *((long*)buf); + + // Ogg vorbis? + if (ident == 0x5367674f) // 'OggS' + return VORBIS_PLAYER; + + // Some kind of MIDI? + EAS_DATA_HANDLE easdata; + if (EAS_Init(&easdata) == EAS_SUCCESS) { + EAS_FILE locator; + locator.path = NULL; + locator.fd = fd; + locator.offset = offset; + locator.length = length; + EAS_HANDLE eashandle; + if (EAS_OpenFile(easdata, &locator, &eashandle) == EAS_SUCCESS) { + EAS_CloseFile(easdata, eashandle); + EAS_Shutdown(easdata); + return SONIVOX_PLAYER; + } + EAS_Shutdown(easdata); + } + + // Fall through to PV + return PV_PLAYER; +} + +static player_type getPlayerType(const char* url) +{ + + // use MidiFile for MIDI extensions + int lenURL = strlen(url); + for (int i = 0; i < NELEM(FILE_EXTS); ++i) { + int len = strlen(FILE_EXTS[i].extension); + int start = lenURL - len; + if (start > 0) { + if (!strncmp(url + start, FILE_EXTS[i].extension, len)) { + return FILE_EXTS[i].playertype; + } + } + } + + // Fall through to PV + return PV_PLAYER; +} + +static sp createPlayer(player_type playerType, void* cookie, + notify_callback_f notifyFunc) +{ + sp p; + switch (playerType) { + case PV_PLAYER: + LOGV(" create PVPlayer"); + p = new PVPlayer(); + break; + case SONIVOX_PLAYER: + LOGV(" create MidiFile"); + p = new MidiFile(); + break; + case VORBIS_PLAYER: + LOGV(" create VorbisPlayer"); + p = new VorbisPlayer(); + break; + } + if (p != NULL) { + if (p->initCheck() == NO_ERROR) { + p->setNotifyCallback(cookie, notifyFunc); + } else { + p.clear(); + } + } + if (p == NULL) { + LOGE("Failed to create player object"); + } + return p; +} + +sp MediaPlayerService::Client::createPlayer(player_type playerType) +{ + // determine if we have the right player type + sp p = mPlayer; + if ((p != NULL) && (p->playerType() != playerType)) { + LOGV("delete player"); + p.clear(); + } + if (p == NULL) { + p = android::createPlayer(playerType, this, notify); + } + return p; +} + +status_t MediaPlayerService::Client::setDataSource(const char *url) +{ + LOGV("setDataSource(%s)", url); + if (url == NULL) + return UNKNOWN_ERROR; + + if (strncmp(url, "content://", 10) == 0) { + // get a filedescriptor for the content Uri and + // pass it to the setDataSource(fd) method + + String16 url16(url); + int fd = android::openContentProviderFile(url16); + if (fd < 0) + { + LOGE("Couldn't open fd for %s", url); + return UNKNOWN_ERROR; + } + setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus + close(fd); + return mStatus; + } else { + player_type playerType = getPlayerType(url); + LOGV("player type = %d", playerType); + + // create the right type of player + sp p = createPlayer(playerType); + if (p == NULL) return NO_INIT; + + if (!p->hardwareOutput()) { + mAudioOutput = new AudioOutput(); + static_cast(p.get())->setAudioSink(mAudioOutput); + } + + // now set data source + LOGV(" setDataSource"); + mStatus = p->setDataSource(url); + if (mStatus == NO_ERROR) mPlayer = p; + return mStatus; + } +} + +status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length) +{ + LOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length); + 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 error"); + ::close(fd); + return UNKNOWN_ERROR; + } + if (offset + length > sb.st_size) { + length = sb.st_size - offset; + LOGV("calculated length = %lld", length); + } + + player_type playerType = getPlayerType(fd, offset, length); + LOGV("player type = %d", playerType); + + // create the right type of player + sp p = createPlayer(playerType); + if (p == NULL) return NO_INIT; + + if (!p->hardwareOutput()) { + mAudioOutput = new AudioOutput(); + static_cast(p.get())->setAudioSink(mAudioOutput); + } + + // now set data source + mStatus = p->setDataSource(fd, offset, length); + if (mStatus == NO_ERROR) mPlayer = p; + return mStatus; +} + +status_t MediaPlayerService::Client::setVideoSurface(const sp& surface) +{ + LOGV("[%d] setVideoSurface(%p)", mConnId, surface.get()); + sp p = getPlayer(); + if (p == 0) return UNKNOWN_ERROR; + return p->setVideoSurface(surface); +} + +status_t MediaPlayerService::Client::prepareAsync() +{ + LOGV("[%d] prepareAsync", mConnId); + sp p = getPlayer(); + if (p == 0) return UNKNOWN_ERROR; + status_t ret = p->prepareAsync(); +#if CALLBACK_ANTAGONIZER + LOGD("start Antagonizer"); + if (ret == NO_ERROR) mAntagonizer->start(); +#endif + return ret; +} + +status_t MediaPlayerService::Client::start() +{ + LOGV("[%d] start", mConnId); + sp p = getPlayer(); + if (p == 0) return UNKNOWN_ERROR; + p->setLooping(mLoop); + return p->start(); +} + +status_t MediaPlayerService::Client::stop() +{ + LOGV("[%d] stop", mConnId); + sp p = getPlayer(); + if (p == 0) return UNKNOWN_ERROR; + return p->stop(); +} + +status_t MediaPlayerService::Client::pause() +{ + LOGV("[%d] pause", mConnId); + sp p = getPlayer(); + if (p == 0) return UNKNOWN_ERROR; + return p->pause(); +} + +status_t MediaPlayerService::Client::isPlaying(bool* state) +{ + *state = false; + sp p = getPlayer(); + if (p == 0) return UNKNOWN_ERROR; + *state = p->isPlaying(); + LOGV("[%d] isPlaying: %d", mConnId, *state); + return NO_ERROR; +} + +status_t MediaPlayerService::Client::getCurrentPosition(int *msec) +{ + LOGV("getCurrentPosition"); + sp p = getPlayer(); + if (p == 0) return UNKNOWN_ERROR; + status_t ret = p->getCurrentPosition(msec); + if (ret == NO_ERROR) { + LOGV("[%d] getCurrentPosition = %d", mConnId, *msec); + } else { + LOGE("getCurrentPosition returned %d", ret); + } + return ret; +} + +status_t MediaPlayerService::Client::getDuration(int *msec) +{ + LOGV("getDuration"); + sp p = getPlayer(); + if (p == 0) return UNKNOWN_ERROR; + status_t ret = p->getDuration(msec); + if (ret == NO_ERROR) { + LOGV("[%d] getDuration = %d", mConnId, *msec); + } else { + LOGE("getDuration returned %d", ret); + } + return ret; +} + +status_t MediaPlayerService::Client::seekTo(int msec) +{ + LOGV("[%d] seekTo(%d)", mConnId, msec); + sp p = getPlayer(); + if (p == 0) return UNKNOWN_ERROR; + return p->seekTo(msec); +} + +status_t MediaPlayerService::Client::reset() +{ + LOGV("[%d] reset", mConnId); + sp p = getPlayer(); + if (p == 0) return UNKNOWN_ERROR; + return p->reset(); +} + +status_t MediaPlayerService::Client::setAudioStreamType(int type) +{ + LOGV("[%d] setAudioStreamType(%d)", mConnId, type); + // TODO: for hardware output, call player instead + Mutex::Autolock l(mLock); + if (mAudioOutput != 0) mAudioOutput->setAudioStreamType(type); + return NO_ERROR; +} + +status_t MediaPlayerService::Client::setLooping(int loop) +{ + LOGV("[%d] setLooping(%d)", mConnId, loop); + mLoop = loop; + sp p = getPlayer(); + if (p != 0) return p->setLooping(loop); + return NO_ERROR; +} + +status_t MediaPlayerService::Client::setVolume(float leftVolume, float rightVolume) +{ + LOGV("[%d] setVolume(%f, %f)", mConnId, leftVolume, rightVolume); + // TODO: for hardware output, call player instead + Mutex::Autolock l(mLock); + if (mAudioOutput != 0) mAudioOutput->setVolume(leftVolume, rightVolume); + return NO_ERROR; +} + +void MediaPlayerService::Client::notify(void* cookie, int msg, int ext1, int ext2) +{ + Client* client = static_cast(cookie); + LOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, cookie, msg, ext1, ext2); + client->mClient->notify(msg, ext1, ext2); +} + +#if CALLBACK_ANTAGONIZER +const int Antagonizer::interval = 10000; // 10 msecs + +Antagonizer::Antagonizer(notify_callback_f cb, void* client) : + mExit(false), mActive(false), mClient(client), mCb(cb) +{ + createThread(callbackThread, this); +} + +void Antagonizer::kill() +{ + Mutex::Autolock _l(mLock); + mActive = false; + mExit = true; + mCondition.wait(mLock); +} + +int Antagonizer::callbackThread(void* user) +{ + LOGD("Antagonizer started"); + Antagonizer* p = reinterpret_cast(user); + while (!p->mExit) { + if (p->mActive) { + LOGV("send event"); + p->mCb(p->mClient, 0, 0, 0); + } + usleep(interval); + } + Mutex::Autolock _l(p->mLock); + p->mCondition.signal(); + LOGD("Antagonizer stopped"); + return 0; +} +#endif + +static size_t kDefaultHeapSize = 1024 * 1024; // 1MB + +sp MediaPlayerService::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) +{ + LOGV("decode(%s)", url); + sp mem; + sp player; + + // Protect our precious, precious DRMd ringtones by only allowing + // decoding of http, but not filesystem paths or content Uris. + // If the application wants to decode those, it should open a + // filedescriptor for them and use that. + if (url != NULL && strncmp(url, "http://", 7) != 0) { + LOGD("Can't decode %s by path, use filedescriptor instead", url); + return mem; + } + + player_type playerType = getPlayerType(url); + LOGV("player type = %d", playerType); + + // create the right type of player + sp cache = new AudioCache(url); + player = android::createPlayer(playerType, cache.get(), cache->notify); + if (player == NULL) goto Exit; + if (player->hardwareOutput()) goto Exit; + + static_cast(player.get())->setAudioSink(cache); + + // set data source + if (player->setDataSource(url) != NO_ERROR) goto Exit; + + LOGV("prepare"); + player->prepareAsync(); + + LOGV("wait for prepare"); + if (cache->wait() != NO_ERROR) goto Exit; + + LOGV("start"); + player->start(); + + LOGV("wait for playback complete"); + if (cache->wait() != NO_ERROR) goto Exit; + + mem = new MemoryBase(cache->getHeap(), 0, cache->size()); + *pSampleRate = cache->sampleRate(); + *pNumChannels = cache->channelCount(); + *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 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 mem; + sp player; + + player_type playerType = getPlayerType(fd, offset, length); + LOGV("player type = %d", playerType); + + // create the right type of player + sp cache = new AudioCache("decode_fd"); + player = android::createPlayer(playerType, cache.get(), cache->notify); + if (player == NULL) goto Exit; + if (player->hardwareOutput()) goto Exit; + + static_cast(player.get())->setAudioSink(cache); + + // set data source + if (player->setDataSource(fd, offset, length) != NO_ERROR) goto Exit; + + LOGV("prepare"); + player->prepareAsync(); + + LOGV("wait for prepare"); + if (cache->wait() != NO_ERROR) goto Exit; + + LOGV("start"); + player->start(); + + LOGV("wait for playback complete"); + if (cache->wait() != NO_ERROR) goto Exit; + + mem = new MemoryBase(cache->getHeap(), 0, cache->size()); + *pSampleRate = cache->sampleRate(); + *pNumChannels = cache->channelCount(); + *pFormat = cache->format(); + LOGV("return memory @ %p, sampleRate=%u, channelCount = %d, format = %d", mem->pointer(), *pSampleRate, *pNumChannels, *pFormat); + +Exit: + if (player != 0) player->reset(); + ::close(fd); + return mem; +} + +#undef LOG_TAG +#define LOG_TAG "AudioSink" +MediaPlayerService::AudioOutput::AudioOutput() +{ + mTrack = 0; + mStreamType = AudioSystem::MUSIC; + mLeftVolume = 1.0; + mRightVolume = 1.0; + mLatency = 0; + mMsecsPerFrame = 0; + setMinBufferCount(); +} + +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() * frameSize(); +} + +ssize_t MediaPlayerService::AudioOutput::frameCount() const +{ + if (mTrack == 0) return NO_INIT; + return mTrack->frameCount(); +} + +ssize_t MediaPlayerService::AudioOutput::channelCount() const +{ + if (mTrack == 0) return NO_INIT; + return mTrack->channelCount(); +} + +ssize_t MediaPlayerService::AudioOutput::frameSize() const +{ + if (mTrack == 0) return NO_INIT; + return mTrack->frameSize(); +} + +uint32_t MediaPlayerService::AudioOutput::latency () const +{ + return mLatency; +} + +float MediaPlayerService::AudioOutput::msecsPerFrame() const +{ + return mMsecsPerFrame; +} + +status_t MediaPlayerService::AudioOutput::open(uint32_t sampleRate, int channelCount, int format, int 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; + + if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) { + return NO_INIT; + } + if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) { + return NO_INIT; + } + + frameCount = (sampleRate*afFrameCount*bufferCount)/afSampleRate; + AudioTrack *t = new AudioTrack(mStreamType, sampleRate, format, channelCount, frameCount); + if ((t == 0) || (t->initCheck() != NO_ERROR)) { + LOGE("Unable to create audio track"); + delete t; + return NO_INIT; + } + + LOGV("setVolume"); + t->setVolume(mLeftVolume, mRightVolume); + mMsecsPerFrame = 1.e3 / (float) sampleRate; + mLatency = t->latency() + kAudioVideoDelayMs; + mTrack = t; + return NO_ERROR; +} + +void MediaPlayerService::AudioOutput::start() +{ + LOGV("start"); + if (mTrack) { + mTrack->setVolume(mLeftVolume, mRightVolume); + mTrack->start(); + } +} + +ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size) +{ + //LOGV("write(%p, %u)", buffer, size); + if (mTrack) return mTrack->write(buffer, size); + return NO_INIT; +} + +void MediaPlayerService::AudioOutput::stop() +{ + LOGV("stop"); + if (mTrack) mTrack->stop(); +} + +void MediaPlayerService::AudioOutput::flush() +{ + LOGV("flush"); + if (mTrack) mTrack->flush(); +} + +void MediaPlayerService::AudioOutput::pause() +{ + LOGV("pause"); + if (mTrack) mTrack->pause(); +} + +void MediaPlayerService::AudioOutput::close() +{ + LOGV("close"); + delete mTrack; + mTrack = 0; +} + +void MediaPlayerService::AudioOutput::setVolume(float left, float right) +{ + LOGV("setVolume(%f, %f)", left, right); + mLeftVolume = left; + mRightVolume = right; + if (mTrack) { + mTrack->setVolume(left, right); + } +} + +#undef LOG_TAG +#define LOG_TAG "AudioCache" +MediaPlayerService::AudioCache::AudioCache(const char* name) : + mChannelCount(0), mFrameCount(1024), mSampleRate(0), mSize(0), + mError(NO_ERROR), mCommandComplete(false) +{ + // create ashmem heap + mHeap = new MemoryHeapBase(kDefaultHeapSize, 0, name); +} + +uint32_t MediaPlayerService::AudioCache::latency () const +{ + return 0; +} + +float MediaPlayerService::AudioCache::msecsPerFrame() const +{ + return mMsecsPerFrame; +} + +status_t MediaPlayerService::AudioCache::open(uint32_t sampleRate, int channelCount, int format, int bufferCount) +{ + 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; +} + +ssize_t MediaPlayerService::AudioCache::write(const void* buffer, size_t size) +{ + LOGV("write(%p, %u)", buffer, size); + if ((buffer == 0) || (size == 0)) return size; + + uint8_t* p = static_cast(mHeap->getBase()); + 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; +} + +// call with lock held +status_t MediaPlayerService::AudioCache::wait() +{ + Mutex::Autolock lock(mLock); + if (!mCommandComplete) { + mSignal.wait(mLock); + } + mCommandComplete = false; + + if (mError == NO_ERROR) { + LOGV("wait - success"); + } else { + LOGV("wait - error"); + } + return mError; +} + +void MediaPlayerService::AudioCache::notify(void* cookie, int msg, int ext1, int ext2) +{ + LOGV("notify(%p, %d, %d, %d)", cookie, msg, ext1, ext2); + AudioCache* p = static_cast(cookie); + + // ignore buffering messages + if (msg == MEDIA_BUFFERING_UPDATE) return; + + // set error condition + if (msg == MEDIA_ERROR) { + LOGE("Error %d, %d occurred", ext1, ext2); + p->mError = ext1; + } + + // wake up thread + LOGV("wakeup thread"); + p->mCommandComplete = true; + p->mSignal.signal(); +} + +}; // namespace android diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h new file mode 100644 index 0000000..f138886 --- /dev/null +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -0,0 +1,238 @@ +/* +** +** Copyright 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_MEDIAPLAYERSERVICE_H +#define ANDROID_MEDIAPLAYERSERVICE_H + +#include +#include +#include + +#include +#include + +namespace android { + +class IMediaRecorder; +class IMediaMetadataRetriever; + +#define CALLBACK_ANTAGONIZER 0 +#if CALLBACK_ANTAGONIZER +class Antagonizer { +public: + Antagonizer(notify_callback_f cb, void* client); + void start() { mActive = true; } + void stop() { mActive = false; } + void kill(); +private: + static const int interval; + Antagonizer(); + static int callbackThread(void* cookie); + Mutex mLock; + Condition mCondition; + bool mExit; + bool mActive; + void* mClient; + notify_callback_f mCb; +}; +#endif + +class MediaPlayerService : public BnMediaPlayerService +{ + class Client; + + class AudioOutput : public MediaPlayerBase::AudioSink + { + public: + AudioOutput(); + virtual ~AudioOutput(); + + virtual bool ready() const { return mTrack != NULL; } + virtual bool realtime() const { return true; } + virtual ssize_t bufferSize() const; + virtual ssize_t frameCount() const; + virtual ssize_t channelCount() const; + virtual ssize_t frameSize() const; + virtual uint32_t latency() const; + virtual float msecsPerFrame() const; + 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(); + virtual void flush(); + virtual void pause(); + virtual void close(); + void setAudioStreamType(int streamType) { mStreamType = streamType; } + void setVolume(float left, float right); + virtual status_t dump(int fd, const Vector& 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; + + // 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 + { + public: + AudioCache(const char* name); + virtual ~AudioCache() {} + + virtual bool ready() const { return (mChannelCount > 0) && (mHeap->getHeapID() > 0); } + virtual bool realtime() const { return false; } + virtual ssize_t bufferSize() const { return frameSize() * mFrameCount; } + virtual ssize_t frameCount() const { return mFrameCount; } + 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 format, int bufferCount=1); + virtual void start() {} + virtual ssize_t write(const void* buffer, size_t size); + virtual void stop() {} + virtual void flush() {} + virtual void pause() {} + virtual void close() {} + 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(); + + sp getHeap() const { return mHeap; } + + static void notify(void* cookie, int msg, int ext1, int ext2); + virtual status_t dump(int fd, const Vector& args) const; + + private: + AudioCache(); + + Mutex mLock; + Condition mSignal; + sp mHeap; + float mMsecsPerFrame; + uint16_t mChannelCount; + uint16_t mFormat; + ssize_t mFrameCount; + uint32_t mSampleRate; + uint32_t mSize; + int mError; + bool mCommandComplete; + }; + +public: + static void instantiate(); + + // IMediaPlayerService interface + virtual sp createMediaRecorder(pid_t pid); + virtual sp createMetadataRetriever(pid_t pid); + + // House keeping for media player clients + virtual sp create(pid_t pid, const sp& client, const char* url); + virtual sp create(pid_t pid, const sp& client, int fd, int64_t offset, int64_t length); + virtual sp decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat); + virtual sp decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat); + + virtual status_t dump(int fd, const Vector& args); + + void removeClient(wp client); + +private: + + class Client : public BnMediaPlayer { + + // IMediaPlayer interface + virtual void disconnect(); + virtual status_t setVideoSurface(const sp& surface); + virtual status_t prepareAsync(); + virtual status_t start(); + virtual status_t stop(); + virtual status_t pause(); + virtual status_t isPlaying(bool* state); + virtual status_t seekTo(int msec); + virtual status_t getCurrentPosition(int* msec); + virtual status_t getDuration(int* msec); + virtual status_t reset(); + virtual status_t setAudioStreamType(int type); + virtual status_t setLooping(int loop); + virtual status_t setVolume(float leftVolume, float rightVolume); + + sp createPlayer(player_type playerType); + status_t setDataSource(const char *url); + status_t setDataSource(int fd, int64_t offset, int64_t length); + static void notify(void* cookie, int msg, int ext1, int ext2); + + pid_t pid() const { return mPid; } + virtual status_t dump(int fd, const Vector& args) const; + + private: + friend class MediaPlayerService; + Client( const sp& service, + pid_t pid, + int32_t connId, + const sp& client); + Client(); + virtual ~Client(); + + void deletePlayer(); + + sp getPlayer() const { Mutex::Autolock lock(mLock); return mPlayer; } + + mutable Mutex mLock; + sp mPlayer; + sp mService; + sp mClient; + sp mAudioOutput; + pid_t mPid; + status_t mStatus; + bool mLoop; + int32_t mConnId; +#if CALLBACK_ANTAGONIZER + Antagonizer* mAntagonizer; +#endif + }; + +// ---------------------------------------------------------------------------- + + MediaPlayerService(); + virtual ~MediaPlayerService(); + + mutable Mutex mLock; + SortedVector< wp > mClients; + int32_t mNextConnId; +}; + +// ---------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_MEDIAPLAYERSERVICE_H + diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp new file mode 100644 index 0000000..4b45acb --- /dev/null +++ b/media/libmediaplayerservice/MediaRecorderClient.cpp @@ -0,0 +1,273 @@ +/* + ** 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "MediaRecorderClient.h" + +namespace android { + +status_t MediaRecorderClient::setCamera(const sp& 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& 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::setOutputFile(int fd, int64_t offset, int64_t length) +{ + LOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length); + Mutex::Autolock lock(mLock); + if (mRecorder == NULL) { + LOGE("recorder is not initialized"); + return NO_INIT; + } + return mRecorder->setOutputFile(fd, offset, length); +} + +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(); +} + +status_t MediaRecorderClient::setListener(const sp& listener) +{ + LOGV("setListener"); + Mutex::Autolock lock(mLock); + if (mRecorder == NULL) { + LOGE("recorder is not initialized"); + return NO_INIT; + } + return mRecorder->setListener(listener); +} + +}; // namespace android + diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h new file mode 100644 index 0000000..93fd802 --- /dev/null +++ b/media/libmediaplayerservice/MediaRecorderClient.h @@ -0,0 +1,66 @@ +/* + ** + ** 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 + +namespace android { + +class PVMediaRecorder; +class ISurface; + +class MediaRecorderClient : public BnMediaRecorder +{ +public: + virtual status_t setCamera(const sp& camera); + virtual status_t setPreviewSurface(const sp& 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 setOutputFile(int fd, int64_t offset, int64_t length); + virtual status_t setVideoSize(int width, int height); + virtual status_t setVideoFrameRate(int frames_per_second); + virtual status_t setListener(const sp& listener); + 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 + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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& 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 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(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 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(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 +#include +#include + +#include + + +namespace android { + +class IMediaPlayerService; +class MemoryDealer; + +class MetadataRetrieverClient : public BnMediaMetadataRetriever +{ +public: + MetadataRetrieverClient(const sp& 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 captureFrame(); + virtual sp extractAlbumArt(); + virtual const char* extractMetadata(int keyCode); + + virtual status_t dump(int fd, const Vector& args) const; + +private: + friend class MediaPlayerService; + + explicit MetadataRetrieverClient(pid_t pid); + virtual ~MetadataRetrieverClient(); + + mutable Mutex mLock; + sp mRetriever; + pid_t mPid; + + // Keep the shared memory copy of album art and capture frame (for thumbnail) + sp mAlbumArtDealer; + sp mThumbnailDealer; + sp mAlbumArt; + sp mThumbnail; +}; + +}; // namespace android + +#endif // ANDROID_MEDIAMETADATARETRIEVERSERVICE_H + diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp new file mode 100644 index 0000000..d03caa5 --- /dev/null +++ b/media/libmediaplayerservice/MidiFile.cpp @@ -0,0 +1,558 @@ +/* MidiFile.cpp +** +** Copyright 2007, 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 "MidiFile" +#include "utils/Log.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "MidiFile.h" + +#ifdef HAVE_GETTID +static pid_t myTid() { return gettid(); } +#else +static pid_t myTid() { return getpid(); } +#endif + +// ---------------------------------------------------------------------------- + +namespace android { + +// ---------------------------------------------------------------------------- + +// The midi engine buffers are a bit small (128 frames), so we batch them up +static const int NUM_BUFFERS = 4; + +// TODO: Determine appropriate return codes +static status_t ERROR_NOT_OPEN = -1; +static status_t ERROR_OPEN_FAILED = -2; +static status_t ERROR_EAS_FAILURE = -3; +static status_t ERROR_ALLOCATE_FAILED = -4; + +static const S_EAS_LIB_CONFIG* pLibConfig = NULL; + +MidiFile::MidiFile() : + mEasData(NULL), mEasHandle(NULL), mAudioBuffer(NULL), + mPlayTime(-1), mDuration(-1), mState(EAS_STATE_ERROR), + mStreamType(AudioSystem::MUSIC), mLoop(false), mExit(false), + mPaused(false), mRender(false), mTid(-1) +{ + LOGV("constructor"); + + mFileLocator.path = NULL; + mFileLocator.fd = -1; + mFileLocator.offset = 0; + mFileLocator.length = 0; + + // get the library configuration and do sanity check + if (pLibConfig == NULL) + pLibConfig = EAS_Config(); + if ((pLibConfig == NULL) || (LIB_VERSION != pLibConfig->libVersion)) { + LOGE("EAS library/header mismatch"); + goto Failed; + } + + // initialize EAS library + if (EAS_Init(&mEasData) != EAS_SUCCESS) { + LOGE("EAS_Init failed"); + goto Failed; + } + + // select reverb preset and enable + EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_PRESET, EAS_PARAM_REVERB_CHAMBER); + EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_BYPASS, EAS_FALSE); + + // create playback thread + { + Mutex::Autolock l(mMutex); + createThreadEtc(renderThread, this, "midithread"); + mCondition.wait(mMutex); + LOGV("thread started"); + } + + // indicate success + if (mTid > 0) { + LOGV(" render thread(%d) started", mTid); + mState = EAS_STATE_READY; + } + +Failed: + return; +} + +status_t MidiFile::initCheck() +{ + if (mState == EAS_STATE_ERROR) return ERROR_EAS_FAILURE; + return NO_ERROR; +} + +MidiFile::~MidiFile() { + LOGV("MidiFile destructor"); + release(); +} + +status_t MidiFile::setDataSource(const char* path) +{ + LOGV("MidiFile::setDataSource url=%s", path); + Mutex::Autolock lock(mMutex); + + // file still open? + if (mEasHandle) { + reset_nosync(); + } + + // open file and set paused state + mFileLocator.path = strdup(path); + mFileLocator.fd = -1; + mFileLocator.offset = 0; + mFileLocator.length = 0; + EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle); + if (result == EAS_SUCCESS) { + updateState(); + } + + if (result != EAS_SUCCESS) { + LOGE("EAS_OpenFile failed: [%d]", (int)result); + mState = EAS_STATE_ERROR; + return ERROR_OPEN_FAILED; + } + + mState = EAS_STATE_OPEN; + mPlayTime = 0; + return NO_ERROR; +} + +status_t MidiFile::setDataSource(int fd, int64_t offset, int64_t length) +{ + LOGV("MidiFile::setDataSource fd=%d", fd); + Mutex::Autolock lock(mMutex); + + // file still open? + if (mEasHandle) { + reset_nosync(); + } + + // open file and set paused state + mFileLocator.fd = dup(fd); + mFileLocator.offset = offset; + mFileLocator.length = length; + EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle); + updateState(); + + if (result != EAS_SUCCESS) { + LOGE("EAS_OpenFile failed: [%d]", (int)result); + mState = EAS_STATE_ERROR; + return ERROR_OPEN_FAILED; + } + + mState = EAS_STATE_OPEN; + mPlayTime = 0; + return NO_ERROR; +} + +status_t MidiFile::prepare() +{ + LOGV("MidiFile::prepare"); + Mutex::Autolock lock(mMutex); + if (!mEasHandle) { + return ERROR_NOT_OPEN; + } + EAS_RESULT result; + if ((result = EAS_Prepare(mEasData, mEasHandle)) != EAS_SUCCESS) { + LOGE("EAS_Prepare failed: [%ld]", result); + return ERROR_EAS_FAILURE; + } + updateState(); + return NO_ERROR; +} + +status_t MidiFile::prepareAsync() +{ + LOGV("MidiFile::prepareAsync"); + status_t ret = prepare(); + + // don't hold lock during callback + if (ret == NO_ERROR) { + sendEvent(MEDIA_PREPARED); + } else { + sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ret); + } + return ret; +} + +status_t MidiFile::start() +{ + LOGV("MidiFile::start"); + Mutex::Autolock lock(mMutex); + if (!mEasHandle) { + return ERROR_NOT_OPEN; + } + + // resuming after pause? + if (mPaused) { + if (EAS_Resume(mEasData, mEasHandle) != EAS_SUCCESS) { + return ERROR_EAS_FAILURE; + } + mPaused = false; + updateState(); + } + + mRender = true; + + // wake up render thread + LOGV(" wakeup render thread"); + mCondition.signal(); + return NO_ERROR; +} + +status_t MidiFile::stop() +{ + LOGV("MidiFile::stop"); + Mutex::Autolock lock(mMutex); + if (!mEasHandle) { + return ERROR_NOT_OPEN; + } + if (!mPaused && (mState != EAS_STATE_STOPPED)) { + EAS_RESULT result = EAS_Pause(mEasData, mEasHandle); + if (result != EAS_SUCCESS) { + LOGE("EAS_Pause returned error %ld", result); + return ERROR_EAS_FAILURE; + } + } + mPaused = false; + return NO_ERROR; +} + +status_t MidiFile::seekTo(int position) +{ + LOGV("MidiFile::seekTo %d", position); + // hold lock during EAS calls + { + Mutex::Autolock lock(mMutex); + if (!mEasHandle) { + return ERROR_NOT_OPEN; + } + EAS_RESULT result; + if ((result = EAS_Locate(mEasData, mEasHandle, position, false)) + != EAS_SUCCESS) + { + LOGE("EAS_Locate returned %ld", result); + return ERROR_EAS_FAILURE; + } + EAS_GetLocation(mEasData, mEasHandle, &mPlayTime); + } + sendEvent(MEDIA_SEEK_COMPLETE); + return NO_ERROR; +} + +status_t MidiFile::pause() +{ + LOGV("MidiFile::pause"); + Mutex::Autolock lock(mMutex); + if (!mEasHandle) { + return ERROR_NOT_OPEN; + } + if ((mState == EAS_STATE_PAUSING) || (mState == EAS_STATE_PAUSED)) return NO_ERROR; + if (EAS_Pause(mEasData, mEasHandle) != EAS_SUCCESS) { + return ERROR_EAS_FAILURE; + } + mPaused = true; + return NO_ERROR; +} + +bool MidiFile::isPlaying() +{ + LOGV("MidiFile::isPlaying, mState=%d", int(mState)); + if (!mEasHandle || mPaused) return false; + return (mState == EAS_STATE_PLAY); +} + +status_t MidiFile::getCurrentPosition(int* position) +{ + LOGV("MidiFile::getCurrentPosition"); + if (!mEasHandle) { + LOGE("getCurrentPosition(): file not open"); + return ERROR_NOT_OPEN; + } + if (mPlayTime < 0) { + LOGE("getCurrentPosition(): mPlayTime = %ld", mPlayTime); + return ERROR_EAS_FAILURE; + } + *position = mPlayTime; + return NO_ERROR; +} + +status_t MidiFile::getDuration(int* duration) +{ + + LOGV("MidiFile::getDuration"); + { + Mutex::Autolock lock(mMutex); + if (!mEasHandle) return ERROR_NOT_OPEN; + *duration = mDuration; + } + + // if no duration cached, get the duration + // don't need a lock here because we spin up a new engine + if (*duration < 0) { + EAS_I32 temp; + EAS_DATA_HANDLE easData = NULL; + EAS_HANDLE easHandle = NULL; + EAS_RESULT result = EAS_Init(&easData); + if (result == EAS_SUCCESS) { + result = EAS_OpenFile(easData, &mFileLocator, &easHandle); + } + if (result == EAS_SUCCESS) { + result = EAS_Prepare(easData, easHandle); + } + if (result == EAS_SUCCESS) { + result = EAS_ParseMetaData(easData, easHandle, &temp); + } + if (easHandle) { + EAS_CloseFile(easData, easHandle); + } + if (easData) { + EAS_Shutdown(easData); + } + + if (result != EAS_SUCCESS) { + return ERROR_EAS_FAILURE; + } + + // cache successful result + mDuration = *duration = int(temp); + } + + return NO_ERROR; +} + +status_t MidiFile::release() +{ + LOGV("MidiFile::release"); + Mutex::Autolock l(mMutex); + reset_nosync(); + + // wait for render thread to exit + mExit = true; + mCondition.signal(); + + // wait for thread to exit + if (mAudioBuffer) { + mCondition.wait(mMutex); + } + + // release resources + if (mEasData) { + EAS_Shutdown(mEasData); + mEasData = NULL; + } + return NO_ERROR; +} + +status_t MidiFile::reset() +{ + LOGV("MidiFile::reset"); + Mutex::Autolock lock(mMutex); + return reset_nosync(); +} + +// call only with mutex held +status_t MidiFile::reset_nosync() +{ + LOGV("MidiFile::reset_nosync"); + // close file + if (mEasHandle) { + EAS_CloseFile(mEasData, mEasHandle); + mEasHandle = NULL; + } + if (mFileLocator.path) { + free((void*)mFileLocator.path); + mFileLocator.path = NULL; + } + if (mFileLocator.fd >= 0) { + close(mFileLocator.fd); + } + mFileLocator.fd = -1; + mFileLocator.offset = 0; + mFileLocator.length = 0; + + mPlayTime = -1; + mDuration = -1; + mLoop = false; + mPaused = false; + mRender = false; + return NO_ERROR; +} + +status_t MidiFile::setLooping(int loop) +{ + LOGV("MidiFile::setLooping"); + Mutex::Autolock lock(mMutex); + if (!mEasHandle) { + return ERROR_NOT_OPEN; + } + loop = loop ? -1 : 0; + if (EAS_SetRepeat(mEasData, mEasHandle, loop) != EAS_SUCCESS) { + return ERROR_EAS_FAILURE; + } + return NO_ERROR; +} + +status_t MidiFile::createOutputTrack() { + if (mAudioSink->open(pLibConfig->sampleRate, pLibConfig->numChannels, AudioSystem::PCM_16_BIT, 2) != NO_ERROR) { + LOGE("mAudioSink open failed"); + return ERROR_OPEN_FAILED; + } + return NO_ERROR; +} + +int MidiFile::renderThread(void* p) { + + return ((MidiFile*)p)->render(); +} + +int MidiFile::render() { + EAS_RESULT result = EAS_FAILURE; + EAS_I32 count; + int temp; + bool audioStarted = false; + + LOGV("MidiFile::render"); + + // allocate render buffer + mAudioBuffer = new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * NUM_BUFFERS]; + if (!mAudioBuffer) { + LOGE("mAudioBuffer allocate failed"); + goto threadExit; + } + + // signal main thread that we started + { + Mutex::Autolock l(mMutex); + mTid = myTid(); + LOGV("render thread(%d) signal", mTid); + mCondition.signal(); + } + + while (1) { + mMutex.lock(); + + // nothing to render, wait for client thread to wake us up + while (!mRender && !mExit) + { + LOGV("MidiFile::render - signal wait"); + mCondition.wait(mMutex); + LOGV("MidiFile::render - signal rx'd"); + } + if (mExit) { + mMutex.unlock(); + break; + } + + // render midi data into the input buffer + //LOGV("MidiFile::render - rendering audio"); + int num_output = 0; + EAS_PCM* p = mAudioBuffer; + for (int i = 0; i < NUM_BUFFERS; i++) { + result = EAS_Render(mEasData, p, pLibConfig->mixBufferSize, &count); + if (result != EAS_SUCCESS) { + LOGE("EAS_Render returned %ld", result); + } + p += count * pLibConfig->numChannels; + num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM); + } + + // update playback state and position + // LOGV("MidiFile::render - updating state"); + EAS_GetLocation(mEasData, mEasHandle, &mPlayTime); + EAS_State(mEasData, mEasHandle, &mState); + mMutex.unlock(); + + // create audio output track if necessary + if (!mAudioSink->ready()) { + LOGV("MidiFile::render - create output track"); + if (createOutputTrack() != NO_ERROR) + goto threadExit; + } + + // Write data to the audio hardware + // LOGV("MidiFile::render - writing to audio output"); + if ((temp = mAudioSink->write(mAudioBuffer, num_output)) < 0) { + LOGE("Error in writing:%d",temp); + return temp; + } + + // start audio output if necessary + if (!audioStarted) { + //LOGV("MidiFile::render - starting audio"); + mAudioSink->start(); + audioStarted = true; + } + + // still playing? + if ((mState == EAS_STATE_STOPPED) || (mState == EAS_STATE_ERROR) || + (mState == EAS_STATE_PAUSED)) + { + switch(mState) { + case EAS_STATE_STOPPED: + { + LOGV("MidiFile::render - stopped"); + sendEvent(MEDIA_PLAYBACK_COMPLETE); + break; + } + case EAS_STATE_ERROR: + { + LOGE("MidiFile::render - error"); + sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN); + break; + } + case EAS_STATE_PAUSED: + LOGV("MidiFile::render - paused"); + break; + default: + break; + } + mAudioSink->stop(); + audioStarted = false; + mRender = false; + } + } + +threadExit: + mAudioSink.clear(); + if (mAudioBuffer) { + delete [] mAudioBuffer; + mAudioBuffer = NULL; + } + mMutex.lock(); + mTid = -1; + mCondition.signal(); + mMutex.unlock(); + return result; +} + +} // end namespace android diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h new file mode 100644 index 0000000..302f1cf --- /dev/null +++ b/media/libmediaplayerservice/MidiFile.h @@ -0,0 +1,77 @@ +/* +** +** Copyright 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_MIDIFILE_H +#define ANDROID_MIDIFILE_H + +#include +#include +#include + +namespace android { + +class MidiFile : public MediaPlayerInterface { +public: + MidiFile(); + ~MidiFile(); + + virtual status_t initCheck(); + virtual status_t setDataSource(const char* path); + virtual status_t setDataSource(int fd, int64_t offset, int64_t length); + virtual status_t setVideoSurface(const sp& surface) { return UNKNOWN_ERROR; } + virtual status_t prepare(); + virtual status_t prepareAsync(); + virtual status_t start(); + virtual status_t stop(); + virtual status_t seekTo(int msec); + virtual status_t pause(); + virtual bool isPlaying(); + virtual status_t getCurrentPosition(int* msec); + virtual status_t getDuration(int* msec); + virtual status_t release(); + virtual status_t reset(); + virtual status_t setLooping(int loop); + virtual player_type playerType() { return SONIVOX_PLAYER; } + +private: + status_t createOutputTrack(); + status_t reset_nosync(); + static int renderThread(void*); + int render(); + void updateState(){ EAS_State(mEasData, mEasHandle, &mState); } + + Mutex mMutex; + Condition mCondition; + EAS_DATA_HANDLE mEasData; + EAS_HANDLE mEasHandle; + EAS_PCM* mAudioBuffer; + EAS_I32 mPlayTime; + EAS_I32 mDuration; + EAS_STATE mState; + EAS_FILE mFileLocator; + int mStreamType; + bool mLoop; + volatile bool mExit; + bool mPaused; + volatile bool mRender; + pid_t mTid; +}; + +}; // namespace android + +#endif // ANDROID_MIDIFILE_H + diff --git a/media/libmediaplayerservice/VorbisPlayer.cpp b/media/libmediaplayerservice/VorbisPlayer.cpp new file mode 100644 index 0000000..0ad335f --- /dev/null +++ b/media/libmediaplayerservice/VorbisPlayer.cpp @@ -0,0 +1,529 @@ +/* +** Copyright 2007, 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 "VorbisPlayer" +#include "utils/Log.h" + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "VorbisPlayer.h" + +#ifdef HAVE_GETTID +static pid_t myTid() { return gettid(); } +#else +static pid_t myTid() { return getpid(); } +#endif + +// ---------------------------------------------------------------------------- + +namespace android { + +// ---------------------------------------------------------------------------- + +// TODO: Determine appropriate return codes +static status_t ERROR_NOT_OPEN = -1; +static status_t ERROR_OPEN_FAILED = -2; +static status_t ERROR_ALLOCATE_FAILED = -4; +static status_t ERROR_NOT_SUPPORTED = -8; +static status_t ERROR_NOT_READY = -16; +static status_t STATE_INIT = 0; +static status_t STATE_ERROR = 1; +static status_t STATE_OPEN = 2; + + +VorbisPlayer::VorbisPlayer() : + mAudioBuffer(NULL), mPlayTime(-1), mDuration(-1), mState(STATE_ERROR), + mStreamType(AudioSystem::MUSIC), mLoop(false), mAndroidLoop(false), + mExit(false), mPaused(false), mRender(false), mRenderTid(-1) +{ + LOGV("constructor\n"); + memset(&mVorbisFile, 0, sizeof mVorbisFile); +} + +void VorbisPlayer::onFirstRef() +{ + LOGV("onFirstRef"); + // create playback thread + Mutex::Autolock l(mMutex); + createThreadEtc(renderThread, this, "vorbis decoder"); + mCondition.wait(mMutex); + if (mRenderTid > 0) { + LOGV("render thread(%d) started", mRenderTid); + mState = STATE_INIT; + } +} + +status_t VorbisPlayer::initCheck() +{ + if (mState != STATE_ERROR) return NO_ERROR; + return ERROR_NOT_READY; +} + +VorbisPlayer::~VorbisPlayer() { + LOGV("VorbisPlayer destructor\n"); + release(); +} + +status_t VorbisPlayer::setDataSource(const char* path) +{ + return setdatasource(path, -1, 0, 0x7ffffffffffffffLL); // intentionally less than LONG_MAX +} + +status_t VorbisPlayer::setDataSource(int fd, int64_t offset, int64_t length) +{ + return setdatasource(NULL, fd, offset, length); +} + +size_t VorbisPlayer::vp_fread(void *buf, size_t size, size_t nmemb, void *me) { + VorbisPlayer *self = (VorbisPlayer*) me; + + long curpos = vp_ftell(me); + while (nmemb != 0 && (curpos + size * nmemb) > self->mLength) { + nmemb--; + } + return fread(buf, size, nmemb, self->mFile); +} + +int VorbisPlayer::vp_fseek(void *me, ogg_int64_t off, int whence) { + VorbisPlayer *self = (VorbisPlayer*) me; + if (whence == SEEK_SET) + return fseek(self->mFile, off + self->mOffset, whence); + else if (whence == SEEK_CUR) + return fseek(self->mFile, off, whence); + else if (whence == SEEK_END) + return fseek(self->mFile, self->mOffset + self->mLength + off, SEEK_SET); + return -1; +} + +int VorbisPlayer::vp_fclose(void *me) { + LOGV("vp_fclose"); + VorbisPlayer *self = (VorbisPlayer*) me; + int ret = fclose (self->mFile); + self->mFile = NULL; + return ret; +} + +long VorbisPlayer::vp_ftell(void *me) { + VorbisPlayer *self = (VorbisPlayer*) me; + return ftell(self->mFile) - self->mOffset; +} + +status_t VorbisPlayer::setdatasource(const char *path, int fd, int64_t offset, int64_t length) +{ + LOGV("setDataSource url=%s, fd=%d\n", path, fd); + + // file still open? + Mutex::Autolock l(mMutex); + if (mState == STATE_OPEN) { + reset_nosync(); + } + + // open file and set paused state + if (path) { + mFile = fopen(path, "r"); + } else { + mFile = fdopen(dup(fd), "r"); + } + if (mFile == NULL) { + return ERROR_OPEN_FAILED; + } + + struct stat sb; + int ret; + if (path) { + ret = stat(path, &sb); + } else { + ret = fstat(fd, &sb); + } + if (ret != 0) { + mState = STATE_ERROR; + fclose(mFile); + return ERROR_OPEN_FAILED; + } + if (sb.st_size > (length + offset)) { + mLength = length; + } else { + mLength = sb.st_size - offset; + } + + ov_callbacks callbacks = { + (size_t (*)(void *, size_t, size_t, void *)) vp_fread, + (int (*)(void *, ogg_int64_t, int)) vp_fseek, + (int (*)(void *)) vp_fclose, + (long (*)(void *)) vp_ftell + }; + + mOffset = offset; + fseek(mFile, offset, SEEK_SET); + + int result = ov_open_callbacks(this, &mVorbisFile, NULL, 0, callbacks); + if (result < 0) { + LOGE("ov_open() failed: [%d]\n", (int)result); + mState = STATE_ERROR; + fclose(mFile); + return ERROR_OPEN_FAILED; + } + + // look for the android loop tag (for ringtones) + char **ptr = ov_comment(&mVorbisFile,-1)->user_comments; + while(*ptr) { + // does the comment start with ANDROID_LOOP_TAG + if(strncmp(*ptr, ANDROID_LOOP_TAG, strlen(ANDROID_LOOP_TAG)) == 0) { + // read the value of the tag + char *val = *ptr + strlen(ANDROID_LOOP_TAG) + 1; + mAndroidLoop = (strncmp(val, "true", 4) == 0); + } + // we keep parsing even after finding one occurence of ANDROID_LOOP_TAG, + // as we could find another one (the tag might have been appended more than once). + ++ptr; + } + LOGV_IF(mAndroidLoop, "looped sound"); + + mState = STATE_OPEN; + return NO_ERROR; +} + +status_t VorbisPlayer::prepare() +{ + LOGV("prepare\n"); + if (mState != STATE_OPEN ) { + return ERROR_NOT_OPEN; + } + return NO_ERROR; +} + +status_t VorbisPlayer::prepareAsync() { + LOGV("prepareAsync\n"); + // can't hold the lock here because of the callback + // it's safe because we don't change state + if (mState != STATE_OPEN ) { + sendEvent(MEDIA_ERROR); + return NO_ERROR; + } + sendEvent(MEDIA_PREPARED); + return NO_ERROR; +} + +status_t VorbisPlayer::start() +{ + LOGV("start\n"); + Mutex::Autolock l(mMutex); + if (mState != STATE_OPEN) { + return ERROR_NOT_OPEN; + } + + mPaused = false; + mRender = true; + + // wake up render thread + LOGV(" wakeup render thread\n"); + mCondition.signal(); + return NO_ERROR; +} + +status_t VorbisPlayer::stop() +{ + LOGV("stop\n"); + Mutex::Autolock l(mMutex); + if (mState != STATE_OPEN) { + return ERROR_NOT_OPEN; + } + mPaused = true; + mRender = false; + return NO_ERROR; +} + +status_t VorbisPlayer::seekTo(int position) +{ + LOGV("seekTo %d\n", position); + Mutex::Autolock l(mMutex); + if (mState != STATE_OPEN) { + return ERROR_NOT_OPEN; + } + + int result = ov_time_seek(&mVorbisFile, position); + if (result != 0) { + LOGE("ov_time_seek() returned %d\n", result); + return result; + } + sendEvent(MEDIA_SEEK_COMPLETE); + return NO_ERROR; +} + +status_t VorbisPlayer::pause() +{ + LOGV("pause\n"); + Mutex::Autolock l(mMutex); + if (mState != STATE_OPEN) { + return ERROR_NOT_OPEN; + } + mPaused = true; + return NO_ERROR; +} + +bool VorbisPlayer::isPlaying() +{ + LOGV("isPlaying\n"); + if (mState == STATE_OPEN) { + return mRender; + } + return false; +} + +status_t VorbisPlayer::getCurrentPosition(int* position) +{ + LOGV("getCurrentPosition\n"); + Mutex::Autolock l(mMutex); + if (mState != STATE_OPEN) { + LOGE("getCurrentPosition(): file not open"); + return ERROR_NOT_OPEN; + } + *position = ov_time_tell(&mVorbisFile); + if (*position < 0) { + LOGE("getCurrentPosition(): ov_time_tell returned %d", *position); + return *position; + } + return NO_ERROR; +} + +status_t VorbisPlayer::getDuration(int* duration) +{ + LOGV("getDuration\n"); + Mutex::Autolock l(mMutex); + if (mState != STATE_OPEN) { + return ERROR_NOT_OPEN; + } + + int ret = ov_time_total(&mVorbisFile, -1); + if (ret == OV_EINVAL) { + return -1; + } + + *duration = ret; + return NO_ERROR; +} + +status_t VorbisPlayer::release() +{ + LOGV("release\n"); + Mutex::Autolock l(mMutex); + reset_nosync(); + + // TODO: timeout when thread won't exit + // wait for render thread to exit + if (mRenderTid > 0) { + mExit = true; + mCondition.signal(); + mCondition.wait(mMutex); + } + return NO_ERROR; +} + +status_t VorbisPlayer::reset() +{ + LOGV("reset\n"); + Mutex::Autolock l(mMutex); + if (mState != STATE_OPEN) { + return NO_ERROR; + } + return reset_nosync(); +} + +// always call with lock held +status_t VorbisPlayer::reset_nosync() +{ + // close file + ov_clear(&mVorbisFile); // this also closes the FILE + if (mFile != NULL) { + LOGV("OOPS! Vorbis didn't close the file"); + fclose(mFile); + } + mState = STATE_ERROR; + + mPlayTime = -1; + mDuration = -1; + mLoop = false; + mAndroidLoop = false; + mPaused = false; + mRender = false; + return NO_ERROR; +} + +status_t VorbisPlayer::setLooping(int loop) +{ + LOGV("setLooping\n"); + Mutex::Autolock l(mMutex); + mLoop = (loop != 0); + return NO_ERROR; +} + +status_t VorbisPlayer::createOutputTrack() { + // open audio track + vorbis_info *vi = ov_info(&mVorbisFile, -1); + + LOGV("Create AudioTrack object: rate=%ld, channels=%d\n", + vi->rate, vi->channels); + if (mAudioSink->open(vi->rate, vi->channels, AudioSystem::PCM_16_BIT, DEFAULT_AUDIOSINK_BUFFERCOUNT) != NO_ERROR) { + LOGE("mAudioSink open failed"); + return ERROR_OPEN_FAILED; + } + return NO_ERROR; +} + +int VorbisPlayer::renderThread(void* p) { + return ((VorbisPlayer*)p)->render(); +} + +#define AUDIOBUFFER_SIZE 4096 + +int VorbisPlayer::render() { + int result = -1; + int temp; + int current_section = 0; + bool audioStarted = false; + + LOGV("render\n"); + + // allocate render buffer + mAudioBuffer = new char[AUDIOBUFFER_SIZE]; + if (!mAudioBuffer) { + LOGE("mAudioBuffer allocate failed\n"); + goto threadExit; + } + + // let main thread know we're ready + { + Mutex::Autolock l(mMutex); + mRenderTid = myTid(); + mCondition.signal(); + } + + while (1) { + long numread = 0; + { + Mutex::Autolock l(mMutex); + + // pausing? + if (mPaused) { + if (mAudioSink->ready()) mAudioSink->pause(); + mRender = false; + audioStarted = false; + } + + // nothing to render, wait for client thread to wake us up + if (!mExit && !mRender) { + LOGV("render - signal wait\n"); + mCondition.wait(mMutex); + LOGV("render - signal rx'd\n"); + } + if (mExit) break; + + // We could end up here if start() is called, and before we get a + // chance to run, the app calls stop() or reset(). Re-check render + // flag so we don't try to render in stop or reset state. + if (!mRender) continue; + + // render vorbis data into the input buffer + numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, ¤t_section); + if (numread == 0) { + // end of file, do we need to loop? + // ... + if (mLoop || mAndroidLoop) { + ov_time_seek(&mVorbisFile, 0); + current_section = 0; + numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, ¤t_section); + } else { + mAudioSink->stop(); + audioStarted = false; + mRender = false; + mPaused = true; + int endpos = ov_time_tell(&mVorbisFile); + + LOGV("send MEDIA_PLAYBACK_COMPLETE"); + sendEvent(MEDIA_PLAYBACK_COMPLETE); + + // wait until we're started again + LOGV("playback complete - wait for signal"); + mCondition.wait(mMutex); + LOGV("playback complete - signal rx'd"); + if (mExit) break; + + // if we're still at the end, restart from the beginning + if (mState == STATE_OPEN) { + int curpos = ov_time_tell(&mVorbisFile); + if (curpos == endpos) { + ov_time_seek(&mVorbisFile, 0); + } + current_section = 0; + numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, ¤t_section); + } + } + } + } + + // codec returns negative number on error + if (numread < 0) { + LOGE("Error in Vorbis decoder"); + sendEvent(MEDIA_ERROR); + break; + } + + // create audio output track if necessary + if (!mAudioSink->ready()) { + LOGV("render - create output track\n"); + if (createOutputTrack() != NO_ERROR) + break; + } + + // Write data to the audio hardware + if ((temp = mAudioSink->write(mAudioBuffer, numread)) < 0) { + LOGE("Error in writing:%d",temp); + result = temp; + break; + } + + // start audio output if necessary + if (!audioStarted && !mPaused && !mExit) { + LOGV("render - starting audio\n"); + mAudioSink->start(); + audioStarted = true; + } + } + +threadExit: + mAudioSink.clear(); + if (mAudioBuffer) { + delete [] mAudioBuffer; + mAudioBuffer = NULL; + } + + // tell main thread goodbye + Mutex::Autolock l(mMutex); + mRenderTid = -1; + mCondition.signal(); + return result; +} + +} // end namespace android diff --git a/media/libmediaplayerservice/VorbisPlayer.h b/media/libmediaplayerservice/VorbisPlayer.h new file mode 100644 index 0000000..c30dc1b --- /dev/null +++ b/media/libmediaplayerservice/VorbisPlayer.h @@ -0,0 +1,91 @@ +/* +** +** Copyright 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_VORBISPLAYER_H +#define ANDROID_VORBISPLAYER_H + +#include + +#include +#include + +#include "ivorbiscodec.h" +#include "ivorbisfile.h" + +#define ANDROID_LOOP_TAG "ANDROID_LOOP" + +namespace android { + +class VorbisPlayer : public MediaPlayerInterface { +public: + VorbisPlayer(); + ~VorbisPlayer(); + + virtual void onFirstRef(); + virtual status_t initCheck(); + virtual status_t setDataSource(const char* path); + virtual status_t setDataSource(int fd, int64_t offset, int64_t length); + virtual status_t setVideoSurface(const sp& surface) { return UNKNOWN_ERROR; } + virtual status_t prepare(); + virtual status_t prepareAsync(); + virtual status_t start(); + virtual status_t stop(); + virtual status_t seekTo(int msec); + virtual status_t pause(); + virtual bool isPlaying(); + virtual status_t getCurrentPosition(int* msec); + virtual status_t getDuration(int* msec); + virtual status_t release(); + virtual status_t reset(); + virtual status_t setLooping(int loop); + virtual player_type playerType() { return VORBIS_PLAYER; } + +private: + status_t setdatasource(const char *path, int fd, int64_t offset, int64_t length); + status_t reset_nosync(); + status_t createOutputTrack(); + static int renderThread(void*); + int render(); + + static size_t vp_fread(void *, size_t, size_t, void *); + static int vp_fseek(void *, ogg_int64_t, int); + static int vp_fclose(void *); + static long vp_ftell(void *); + + Mutex mMutex; + Condition mCondition; + FILE* mFile; + int64_t mOffset; + int64_t mLength; + OggVorbis_File mVorbisFile; + char* mAudioBuffer; + int mPlayTime; + int mDuration; + status_t mState; + int mStreamType; + bool mLoop; + bool mAndroidLoop; + volatile bool mExit; + bool mPaused; + volatile bool mRender; + pid_t mRenderTid; +}; + +}; // namespace android + +#endif // ANDROID_VORBISPLAYER_H + diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk new file mode 100644 index 0000000..c681698 --- /dev/null +++ b/media/mediaserver/Android.mk @@ -0,0 +1,22 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + main_mediaserver.cpp + +LOCAL_SHARED_LIBRARIES := \ + libaudioflinger \ + libcameraservice \ + libmediaplayerservice \ + libutils + +base := $(LOCAL_PATH)/../.. + +LOCAL_C_INCLUDES := \ + $(base)/libs/audioflinger \ + $(base)/camera/libcameraservice \ + $(base)/media/libmediaplayerservice + +LOCAL_MODULE:= mediaserver + +include $(BUILD_EXECUTABLE) diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp new file mode 100644 index 0000000..6954b63 --- /dev/null +++ b/media/mediaserver/main_mediaserver.cpp @@ -0,0 +1,45 @@ +/* +** +** Copyright 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. +*/ + +// System headers required for setgroups, etc. +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace android; + +int main(int argc, char** argv) +{ + sp proc(ProcessState::self()); + sp sm = defaultServiceManager(); + LOGI("ServiceManager: %p", sm.get()); + AudioFlinger::instantiate(); + MediaPlayerService::instantiate(); + CameraService::instantiate(); + ProcessState::self()->startThreadPool(); + IPCThreadState::self()->joinThreadPool(); +} -- cgit v1.1 From 8555d0867c3e8fe6cc5c7ad40af557fe6b92fa72 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Thu, 5 Mar 2009 14:34:35 -0800 Subject: auto import from //depot/cupcake/@136594 --- media/libmedia/AudioTrack.cpp | 9 ++++++++- media/libmedia/mediarecorder.cpp | 36 ++++++++++++++++++------------------ 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index e79f336..d26b0c5 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -808,7 +808,14 @@ bool AudioTrack::processAudioBuffer(const sp& thread) writtenSize = audioBuffer.size; // Sanity check on returned size - if (ssize_t(writtenSize) <= 0) break; + if (ssize_t(writtenSize) <= 0) { + // The callback is done filling buffers + // Keep this thread going to handle timed events and + // still try to get more data in intervals of WAIT_PERIOD_MS + // but don't just loop and block the CPU, so wait + usleep(WAIT_PERIOD_MS*1000); + break; + } if (writtenSize > reqSize) writtenSize = reqSize; if (mFormat == AudioSystem::PCM_8_BIT) { diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index 98aac39..5eba0ef 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -42,7 +42,7 @@ status_t MediaRecorder::setCamera(const sp& camera) if (OK != ret) { LOGV("setCamera failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; + return ret; } return ret; } @@ -67,7 +67,7 @@ status_t MediaRecorder::setPreviewSurface(const sp& surface) if (OK != ret) { LOGV("setPreviewSurface failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; + return ret; } return ret; } @@ -88,14 +88,14 @@ status_t MediaRecorder::init() if (OK != ret) { LOGV("init failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; + return ret; } ret = mMediaRecorder->setListener(this); if (OK != ret) { LOGV("setListener failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; + return ret; } mCurrentState = MEDIA_RECORDER_INITIALIZED; @@ -129,7 +129,7 @@ status_t MediaRecorder::setVideoSource(int vs) if (OK != ret) { LOGV("setVideoSource failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; + return ret; } mIsVideoSourceSet = true; return ret; @@ -162,7 +162,7 @@ status_t MediaRecorder::setAudioSource(int as) if (OK != ret) { LOGV("setAudioSource failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; + return ret; } mIsAudioSourceSet = true; return ret; @@ -188,7 +188,7 @@ status_t MediaRecorder::setOutputFormat(int of) if (OK != ret) { LOGE("setOutputFormat failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; + return ret; } mCurrentState = MEDIA_RECORDER_DATASOURCE_CONFIGURED; return ret; @@ -218,7 +218,7 @@ status_t MediaRecorder::setVideoEncoder(int ve) if (OK != ret) { LOGV("setVideoEncoder failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; + return ret; } mIsVideoEncoderSet = true; return ret; @@ -248,7 +248,7 @@ status_t MediaRecorder::setAudioEncoder(int ae) if (OK != ret) { LOGV("setAudioEncoder failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; + return ret; } mIsAudioEncoderSet = true; return ret; @@ -274,7 +274,7 @@ status_t MediaRecorder::setOutputFile(const char* path) if (OK != ret) { LOGV("setOutputFile failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; + return ret; } mIsOutputFileSet = true; return ret; @@ -300,7 +300,7 @@ status_t MediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length) if (OK != ret) { LOGV("setOutputFile failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; + return ret; } mIsOutputFileSet = true; return ret; @@ -326,7 +326,7 @@ status_t MediaRecorder::setVideoSize(int width, int height) if (OK != ret) { LOGE("setVideoSize failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; + return ret; } return ret; } @@ -351,7 +351,7 @@ status_t MediaRecorder::setVideoFrameRate(int frames_per_second) if (OK != ret) { LOGE("setVideoFrameRate failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; + return ret; } return ret; } @@ -389,7 +389,7 @@ status_t MediaRecorder::prepare() if (OK != ret) { LOGE("prepare failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; + return ret; } mCurrentState = MEDIA_RECORDER_PREPARED; return ret; @@ -411,7 +411,7 @@ status_t MediaRecorder::getMaxAmplitude(int* max) if (OK != ret) { LOGE("getMaxAmplitude failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; + return ret; } return ret; } @@ -432,7 +432,7 @@ status_t MediaRecorder::start() if (OK != ret) { LOGE("start failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; + return ret; } mCurrentState = MEDIA_RECORDER_RECORDING; return ret; @@ -454,7 +454,7 @@ status_t MediaRecorder::stop() if (OK != ret) { LOGE("stop failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; + return ret; } mCurrentState = MEDIA_RECORDER_IDLE; return ret; @@ -522,7 +522,7 @@ status_t MediaRecorder::doReset() if (OK != ret) { LOGE("doReset failed: %d", ret); mCurrentState = MEDIA_RECORDER_ERROR; - return UNKNOWN_ERROR; + return ret; } else { mCurrentState = MEDIA_RECORDER_INITIALIZED; } -- cgit v1.1 From 87e06b6ae58d0caca9196e31490f2a5b515a9740 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Thu, 5 Mar 2009 17:04:48 -0800 Subject: auto import from //depot/cupcake/@136654 --- include/media/thread_init.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/media/thread_init.h b/include/media/thread_init.h index 2c0c1f1..2feac86 100644 --- a/include/media/thread_init.h +++ b/include/media/thread_init.h @@ -19,7 +19,6 @@ bool InitializeForThread(); void UninitializeForThread(); -void keydestructor(void*); #endif /* THREAD_INIT_H*/ -- cgit v1.1 From 8365529381f6284f2d59dcc38e26f73adeec9c67 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Mon, 9 Mar 2009 11:52:12 -0700 Subject: auto import from //branches/cupcake/...@137197 --- media/libmedia/ToneGenerator.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp index 5416629..8560593 100644 --- a/media/libmedia/ToneGenerator.cpp +++ b/media/libmedia/ToneGenerator.cpp @@ -182,8 +182,9 @@ bool ToneGenerator::startTone(int toneType) { mLock.lock(); if (mState == TONE_STARTING) { LOGV("Wait for start callback"); - if (mWaitCbkCond.waitRelative(mLock, seconds(1)) != NO_ERROR) { - LOGE("--- Immediate start timed out"); + status_t lStatus = mWaitCbkCond.waitRelative(mLock, seconds(1)); + if (lStatus != NO_ERROR) { + LOGE("--- Immediate start timed out, status %d", lStatus); mState = TONE_IDLE; lResult = false; } @@ -195,13 +196,14 @@ bool ToneGenerator::startTone(int toneType) { LOGV("Delayed start\n"); mState = TONE_RESTARTING; - if (mWaitCbkCond.waitRelative(mLock, seconds(1)) == NO_ERROR) { + status_t lStatus = mWaitCbkCond.waitRelative(mLock, seconds(1)); + if (lStatus == NO_ERROR) { if (mState != TONE_IDLE) { lResult = true; } LOGV("cond received"); } else { - LOGE("--- Delayed start timed out"); + LOGE("--- Delayed start timed out, status %d", lStatus); mState = TONE_IDLE; } } @@ -368,6 +370,8 @@ void ToneGenerator::audioCallback(int event, void* user, void *info) { break; default: LOGV("Extra Cbk"); + // Force loop exit + lNumSmp = 0; goto audioCallback_EndLoop; } -- cgit v1.1 From 65e731f393f704eedab6fbe0af7f8a580c8d4617 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Wed, 11 Mar 2009 12:11:56 -0700 Subject: auto import from //branches/cupcake/...@137873 --- include/media/PVPlayer.h | 4 +-- include/media/mediaplayer.h | 68 +++++++++++++++++++++++++++++++++++++--- media/libmedia/mediaplayer.cpp | 13 +++++++- media/libmedia/mediarecorder.cpp | 5 +++ 4 files changed, 83 insertions(+), 7 deletions(-) diff --git a/include/media/PVPlayer.h b/include/media/PVPlayer.h index 6d98852..8122df6 100644 --- a/include/media/PVPlayer.h +++ b/include/media/PVPlayer.h @@ -53,8 +53,8 @@ public: virtual status_t setLooping(int loop); virtual player_type playerType() { return PV_PLAYER; } - // make available to PlayerDriver - void sendEvent(int msg, int ext1=0, int ext2=0) { MediaPlayerBase::sendEvent(msg, ext1, ext2); } + // make available to PlayerDriver + void sendEvent(int msg, int ext1=0, int ext2=0) { MediaPlayerBase::sendEvent(msg, ext1, ext2); } private: static void do_nothing(status_t s, void *cookie, bool cancelled) { } diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h index 7288445..58906d1 100644 --- a/include/media/mediaplayer.h +++ b/include/media/mediaplayer.h @@ -34,11 +34,72 @@ enum media_event_type { MEDIA_SEEK_COMPLETE = 4, MEDIA_SET_VIDEO_SIZE = 5, MEDIA_ERROR = 100, + MEDIA_INFO = 200, }; -typedef int media_error_type; -const media_error_type MEDIA_ERROR_UNKNOWN = 1; -const media_error_type MEDIA_ERROR_SERVER_DIED = 100; +// Generic error codes for the media player framework. Errors are fatal, the +// playback must abort. +// +// Errors are communicated back to the client using the +// MediaPlayerListener::notify method defined below. +// In this situation, 'notify' is invoked with the following: +// 'msg' is set to MEDIA_ERROR. +// 'ext1' should be a value from the enum media_error_type. +// 'ext2' contains an implementation dependant error code to provide +// more details. Should default to 0 when not used. +// +// The codes are distributed as follow: +// 0xx: Reserved +// 1xx: Android Player errors. Something went wrong inside the MediaPlayer. +// 2xx: Media errors (e.g Codec not supported). There is a problem with the +// media itself. +// 3xx: Runtime errors. Some extraordinary condition arose making the playback +// impossible. +// +enum media_error_type { + // 0xx + MEDIA_ERROR_UNKNOWN = 1, + // 1xx + MEDIA_ERROR_SERVER_DIED = 100, + // 2xx + MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200, + // 3xx +}; + + +// Info and warning codes for the media player framework. These are non fatal, +// the playback is going on but there might be some user visible issues. +// +// Info and warning messages are communicated back to the client using the +// MediaPlayerListener::notify method defined below. In this situation, +// 'notify' is invoked with the following: +// 'msg' is set to MEDIA_INFO. +// 'ext1' should be a value from the enum media_info_type. +// 'ext2' contains an implementation dependant error code to provide +// more details. Should default to 0 when not used. +// +// The codes are distributed as follow: +// 0xx: Reserved +// 7xx: Android Player info/warning (e.g player lagging behind.) +// 8xx: Media info/warning (e.g media badly interleaved.) +// +enum media_info_type { + // 0xx + MEDIA_INFO_UNKNOWN = 1, + // 7xx + // The video is too complex for the decoder: it can't decode frames fast + // enough. Possibly only the audio plays fine at this stage. + MEDIA_INFO_VIDEO_TRACK_LAGGING = 700, + // 8xx + // Bad interleaving means that a media has been improperly interleaved or not + // interleaved at all, e.g has all the video samples first then all the audio + // ones. Video is playing but a lot of disk seek may be happening. + MEDIA_INFO_BAD_INTERLEAVING = 800, + // The media is not seekable (e.g live stream). + MEDIA_INFO_NOT_SEEKABLE = 801, +}; + + enum media_player_states { MEDIA_PLAYER_STATE_ERROR = 0, @@ -141,4 +202,3 @@ private: }; // namespace android #endif // ANDROID_MEDIAPLAYER_H - diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index bd8579c..6b40412 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -215,6 +215,10 @@ status_t MediaPlayer::prepareAsync_l() return INVALID_OPERATION; } +// TODO: In case of error, prepareAsync provides the caller with 2 error codes, +// one defined in the Android framework and one provided by the implementation +// that generated the error. The sync version of prepare returns only 1 error +// code. status_t MediaPlayer::prepare() { LOGV("prepare"); @@ -512,7 +516,9 @@ void MediaPlayer::notify(int msg, int ext1, int ext2) } break; case MEDIA_ERROR: - // Always log errors + // Always log errors. + // ext1: Media framework error code. + // ext2: Implementation dependant error code. LOGE("error (%d, %d)", ext1, ext2); mCurrentState = MEDIA_PLAYER_STATE_ERROR; if (mPrepareSync) @@ -524,6 +530,11 @@ void MediaPlayer::notify(int msg, int ext1, int ext2) send = false; } break; + case MEDIA_INFO: + // ext1: Media framework error code. + // ext2: Implementation dependant error code. + LOGW("info/warning (%d, %d)", ext1, ext2); + break; case MEDIA_SEEK_COMPLETE: LOGV("Received seek complete"); if (mSeekPosition != mCurrentPosition) { diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index 5eba0ef..572b1e7 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -456,6 +456,11 @@ status_t MediaRecorder::stop() mCurrentState = MEDIA_RECORDER_ERROR; return ret; } + + // FIXME: + // stop and reset are semantically different. + // We treat them the same for now, and will change this in the future. + doCleanUp(); mCurrentState = MEDIA_RECORDER_IDLE; return ret; } -- cgit v1.1 From c048cae0367db6fbb4fe1127be5011910713d4ad Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Fri, 13 Mar 2009 13:04:22 -0700 Subject: auto import from //branches/cupcake_rel/...@138607 --- include/media/IMediaRecorder.h | 1 + include/media/PVMediaRecorder.h | 1 + include/media/mediarecorder.h | 17 ++++++++++++++--- media/libmedia/IMediaRecorder.cpp | 17 +++++++++++++++++ media/libmedia/mediarecorder.cpp | 18 ++++++++++++++++++ media/libmediaplayerservice/MediaRecorderClient.cpp | 10 ++++++++++ media/libmediaplayerservice/MediaRecorderClient.h | 1 + 7 files changed, 62 insertions(+), 3 deletions(-) diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h index eace996..64d3a40 100644 --- a/include/media/IMediaRecorder.h +++ b/include/media/IMediaRecorder.h @@ -42,6 +42,7 @@ public: virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0; virtual status_t setVideoSize(int width, int height) = 0; virtual status_t setVideoFrameRate(int frames_per_second) = 0; + virtual status_t setParameters(const String8& params) = 0; virtual status_t setListener(const sp& listener) = 0; virtual status_t prepare() = 0; virtual status_t getMaxAmplitude(int* max) = 0; diff --git a/include/media/PVMediaRecorder.h b/include/media/PVMediaRecorder.h index 3315c59..0c71932 100644 --- a/include/media/PVMediaRecorder.h +++ b/include/media/PVMediaRecorder.h @@ -45,6 +45,7 @@ public: status_t setPreviewSurface(const sp& surface); status_t setOutputFile(const char *path); status_t setOutputFile(int fd, int64_t offset, int64_t length); + status_t setParameters(const String8& params); status_t setListener(const sp& listener); status_t prepare(); status_t start(); diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h index 8991f08..78d7621 100644 --- a/include/media/mediarecorder.h +++ b/include/media/mediarecorder.h @@ -89,14 +89,24 @@ enum media_recorder_states { }; // The "msg" code passed to the listener in notify. -enum { - MEDIA_RECORDER_EVENT_ERROR = 1 +enum media_recorder_event_type { + MEDIA_RECORDER_EVENT_ERROR = 1, + MEDIA_RECORDER_EVENT_INFO = 2 }; -enum { +enum media_recorder_error_type { MEDIA_RECORDER_ERROR_UNKNOWN = 1 }; +// The codes are distributed as follow: +// 0xx: Reserved +// 8xx: General info/warning +// +enum media_recorder_info_type { + MEDIA_RECORDER_INFO_UNKNOWN = 1, + MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800 +}; + // ---------------------------------------------------------------------------- // ref-counted object for callbacks class MediaRecorderListener: virtual public RefBase @@ -123,6 +133,7 @@ public: status_t setOutputFile(int fd, int64_t offset, int64_t length); status_t setVideoSize(int width, int height); status_t setVideoFrameRate(int frames_per_second); + status_t setParameters(const String8& params); status_t setListener(const sp& listener); status_t prepare(); status_t getMaxAmplitude(int* max); diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp index f187bf5..84d08c4 100644 --- a/media/libmedia/IMediaRecorder.cpp +++ b/media/libmedia/IMediaRecorder.cpp @@ -44,6 +44,7 @@ enum { SET_OUTPUT_FILE_FD, SET_VIDEO_SIZE, SET_VIDEO_FRAMERATE, + SET_PARAMETERS, SET_PREVIEW_SURFACE, SET_CAMERA, SET_LISTENER @@ -178,6 +179,16 @@ public: return reply.readInt32(); } + status_t setParameters(const String8& params) + { + LOGV("setParameter(%s)", params.string()); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + data.writeString8(params); + remote()->transact(SET_PARAMETERS, data, &reply); + return reply.readInt32(); + } + status_t setListener(const sp& listener) { LOGV("setListener(%p)", listener.get()); @@ -385,6 +396,12 @@ status_t BnMediaRecorder::onTransact( reply->writeInt32(setVideoFrameRate(frames_per_second)); return NO_ERROR; } break; + case SET_PARAMETERS: { + LOGV("SET_PARAMETER"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + reply->writeInt32(setParameters(data.readString8())); + return NO_ERROR; + } break; case SET_LISTENER: { LOGV("SET_LISTENER"); CHECK_INTERFACE(IMediaRecorder, data, reply); diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index 572b1e7..23b3b9d 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -356,6 +357,23 @@ status_t MediaRecorder::setVideoFrameRate(int frames_per_second) return ret; } +status_t MediaRecorder::setParameters(const String8& params) { + LOGV("setParameters(%s)", params.string()); + if(mMediaRecorder == NULL) { + LOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + + status_t ret = mMediaRecorder->setParameters(params); + if (OK != ret) { + LOGE("setParameters(%s) failed: %d", params.string(), ret); + mCurrentState = MEDIA_RECORDER_ERROR; + return ret; + } + + return ret; +} + status_t MediaRecorder::prepare() { LOGV("prepare"); diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp index 4b45acb..5d1887d 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.cpp +++ b/media/libmediaplayerservice/MediaRecorderClient.cpp @@ -154,6 +154,16 @@ status_t MediaRecorderClient::setVideoFrameRate(int frames_per_second) return mRecorder->setVideoFrameRate(frames_per_second); } +status_t MediaRecorderClient::setParameters(const String8& params) { + LOGV("setParameters(%s)", params.string()); + Mutex::Autolock lock(mLock); + if (mRecorder == NULL) { + LOGE("recorder is not initialized"); + return NO_INIT; + } + return mRecorder->setParameters(params); +} + status_t MediaRecorderClient::prepare() { LOGV("prepare"); diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h index 93fd802..6a1c2d5 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.h +++ b/media/libmediaplayerservice/MediaRecorderClient.h @@ -39,6 +39,7 @@ public: virtual status_t setOutputFile(int fd, int64_t offset, int64_t length); virtual status_t setVideoSize(int width, int height); virtual status_t setVideoFrameRate(int frames_per_second); + virtual status_t setParameters(const String8& params); virtual status_t setListener(const sp& listener); virtual status_t prepare(); virtual status_t getMaxAmplitude(int* max); -- cgit v1.1