diff options
Diffstat (limited to 'media/libmedia')
-rw-r--r-- | media/libmedia/Android.mk | 3 | ||||
-rw-r--r-- | media/libmedia/AudioEffect.cpp | 13 | ||||
-rw-r--r-- | media/libmedia/AudioRecord.cpp | 231 | ||||
-rw-r--r-- | media/libmedia/AudioSystem.cpp | 51 | ||||
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 35 | ||||
-rw-r--r-- | media/libmedia/IAudioFlinger.cpp | 61 | ||||
-rw-r--r-- | media/libmedia/IAudioPolicyService.cpp | 42 | ||||
-rw-r--r-- | media/libmedia/IAudioRecord.cpp | 4 | ||||
-rw-r--r-- | media/libmedia/IHDCP.cpp | 206 | ||||
-rw-r--r-- | media/libmedia/IMediaPlayer.cpp | 34 | ||||
-rw-r--r-- | media/libmedia/IMediaPlayerService.cpp | 41 | ||||
-rw-r--r-- | media/libmedia/IRemoteDisplay.cpp | 63 | ||||
-rw-r--r-- | media/libmedia/IRemoteDisplayClient.cpp | 102 | ||||
-rw-r--r-- | media/libmedia/IStreamSource.cpp | 16 | ||||
-rw-r--r-- | media/libmedia/MediaProfiles.cpp | 2 | ||||
-rw-r--r-- | media/libmedia/Visualizer.cpp | 9 |
16 files changed, 720 insertions, 193 deletions
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index 6afc505..54666fb 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -18,6 +18,7 @@ LOCAL_SRC_FILES:= \ IAudioTrack.cpp \ IAudioRecord.cpp \ ICrypto.cpp \ + IHDCP.cpp \ AudioRecord.cpp \ AudioSystem.cpp \ mediaplayer.cpp \ @@ -26,6 +27,8 @@ LOCAL_SRC_FILES:= \ IMediaRecorderClient.cpp \ IMediaPlayer.cpp \ IMediaRecorder.cpp \ + IRemoteDisplay.cpp \ + IRemoteDisplayClient.cpp \ IStreamSource.cpp \ Metadata.cpp \ mediarecorder.cpp \ diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp index 34451ca..680604b 100644 --- a/media/libmedia/AudioEffect.cpp +++ b/media/libmedia/AudioEffect.cpp @@ -122,19 +122,12 @@ status_t AudioEffect::set(const effect_uuid_t *type, mSessionId = sessionId; memset(&mDescriptor, 0, sizeof(effect_descriptor_t)); - memcpy(&mDescriptor.type, EFFECT_UUID_NULL, sizeof(effect_uuid_t)); - memcpy(&mDescriptor.uuid, EFFECT_UUID_NULL, sizeof(effect_uuid_t)); - - if (type != NULL) { - memcpy(&mDescriptor.type, type, sizeof(effect_uuid_t)); - } - if (uuid != NULL) { - memcpy(&mDescriptor.uuid, uuid, sizeof(effect_uuid_t)); - } + mDescriptor.type = *(type != NULL ? type : EFFECT_UUID_NULL); + mDescriptor.uuid = *(uuid != NULL ? uuid : EFFECT_UUID_NULL); mIEffectClient = new EffectClient(this); - iEffect = audioFlinger->createEffect(getpid(), (effect_descriptor_t *)&mDescriptor, + iEffect = audioFlinger->createEffect(getpid(), &mDescriptor, mIEffectClient, priority, io, mSessionId, &mStatus, &mId, &enabled); if (iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) { diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 0562f8e..8ea6306 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -18,28 +18,18 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "AudioRecord" -#include <stdint.h> -#include <sys/types.h> - -#include <sched.h> #include <sys/resource.h> +#include <sys/types.h> -#include <private/media/AudioTrackShared.h> - -#include <media/AudioSystem.h> +#include <binder/IPCThreadState.h> +#include <cutils/atomic.h> +#include <cutils/compiler.h> #include <media/AudioRecord.h> -#include <media/mediarecorder.h> - -#include <binder/IServiceManager.h> +#include <media/AudioSystem.h> +#include <system/audio.h> #include <utils/Log.h> -#include <binder/Parcel.h> -#include <binder/IPCThreadState.h> -#include <utils/Timers.h> -#include <utils/Atomic.h> -#include <system/audio.h> -#include <cutils/bitops.h> -#include <cutils/compiler.h> +#include <private/media/AudioTrackShared.h> namespace android { // --------------------------------------------------------------------------- @@ -49,18 +39,23 @@ status_t AudioRecord::getMinFrameCount( int* frameCount, uint32_t sampleRate, audio_format_t format, - int channelCount) + audio_channel_mask_t channelMask) { + if (frameCount == NULL) return BAD_VALUE; + + // default to 0 in case of error + *frameCount = 0; + size_t size = 0; - if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &size) + if (AudioSystem::getInputBufferSize(sampleRate, format, channelMask, &size) != NO_ERROR) { ALOGE("AudioSystem could not query the input buffer size."); return NO_INIT; } if (size == 0) { - ALOGE("Unsupported configuration: sampleRate %d, format %d, channelCount %d", - sampleRate, format, channelCount); + ALOGE("Unsupported configuration: sampleRate %d, format %d, channelMask %#x", + sampleRate, format, channelMask); return BAD_VALUE; } @@ -68,6 +63,7 @@ status_t AudioRecord::getMinFrameCount( size <<= 1; if (audio_is_linear_pcm(format)) { + int channelCount = popcount(channelMask); size /= channelCount * audio_bytes_per_sample(format); } @@ -87,9 +83,8 @@ AudioRecord::AudioRecord( audio_source_t inputSource, uint32_t sampleRate, audio_format_t format, - uint32_t channelMask, + audio_channel_mask_t channelMask, int frameCount, - record_flags flags, callback_t cbf, void* user, int notificationFrames, @@ -98,7 +93,7 @@ AudioRecord::AudioRecord( mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT) { mStatus = set(inputSource, sampleRate, format, channelMask, - frameCount, flags, cbf, user, notificationFrames, sessionId); + frameCount, cbf, user, notificationFrames, sessionId); } AudioRecord::~AudioRecord() @@ -108,9 +103,10 @@ AudioRecord::~AudioRecord() // it is looping on buffer empty condition in obtainBuffer(). // Otherwise the callback thread will never exit. stop(); - if (mClientRecordThread != 0) { - mClientRecordThread->requestExitAndWait(); - mClientRecordThread.clear(); + if (mAudioRecordThread != 0) { + mAudioRecordThread->requestExit(); // see comment in AudioRecord.h + mAudioRecordThread->requestExitAndWait(); + mAudioRecordThread.clear(); } mAudioRecord.clear(); IPCThreadState::self()->flushCommands(); @@ -122,9 +118,8 @@ status_t AudioRecord::set( audio_source_t inputSource, uint32_t sampleRate, audio_format_t format, - uint32_t channelMask, + audio_channel_mask_t channelMask, int frameCount, - record_flags flags, callback_t cbf, void* user, int notificationFrames, @@ -132,7 +127,7 @@ status_t AudioRecord::set( int sessionId) { - ALOGV("set(): sampleRate %d, channelMask %d, frameCount %d",sampleRate, channelMask, frameCount); + ALOGV("set(): sampleRate %d, channelMask %#x, frameCount %d",sampleRate, channelMask, frameCount); AutoMutex lock(mLock); @@ -174,7 +169,6 @@ status_t AudioRecord::set( sampleRate, format, channelMask, - (audio_in_acoustics_t)flags, mSessionId); if (input == 0) { ALOGE("Could not get audio input for record source %d", inputSource); @@ -183,7 +177,7 @@ status_t AudioRecord::set( // validate framecount int minFrameCount = 0; - status_t status = getMinFrameCount(&minFrameCount, sampleRate, format, channelCount); + status_t status = getMinFrameCount(&minFrameCount, sampleRate, format, channelMask); if (status != NO_ERROR) { return status; } @@ -207,7 +201,8 @@ status_t AudioRecord::set( } if (cbf != NULL) { - mClientRecordThread = new ClientRecordThread(*this, threadCanCallJava); + mAudioRecordThread = new AudioRecordThread(*this, threadCanCallJava); + mAudioRecordThread->run("AudioRecord", ANDROID_PRIORITY_AUDIO); } mStatus = NO_ERROR; @@ -217,7 +212,7 @@ status_t AudioRecord::set( mFrameCount = mCblk->frameCount; mChannelCount = (uint8_t)channelCount; mChannelMask = channelMask; - mActive = 0; + mActive = false; mCbf = cbf; mNotificationFrames = notificationFrames; mRemainingFrames = notificationFrames; @@ -229,7 +224,6 @@ status_t AudioRecord::set( mNewPosition = 0; mUpdatePeriod = 0; mInputSource = inputSource; - mFlags = flags; mInput = input; AudioSystem::acquireAudioSessionId(mSessionId); @@ -282,41 +276,19 @@ audio_source_t AudioRecord::inputSource() const status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession) { status_t ret = NO_ERROR; - sp<ClientRecordThread> t = mClientRecordThread; + sp<AudioRecordThread> t = mAudioRecordThread; ALOGV("start, sync event %d trigger session %d", event, triggerSession); - if (t != 0) { - if (t->exitPending()) { - if (t->requestExitAndWait() == WOULD_BLOCK) { - ALOGE("AudioRecord::start called from thread"); - return WOULD_BLOCK; - } - } - } - AutoMutex lock(mLock); // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed // while we are accessing the cblk sp<IAudioRecord> audioRecord = mAudioRecord; sp<IMemory> iMem = mCblkMemory; audio_track_cblk_t* cblk = mCblk; - if (mActive == 0) { - mActive = 1; - pid_t tid; - if (t != 0) { - mReadyToRun = WOULD_BLOCK; - t->run("AudioRecord", ANDROID_PRIORITY_AUDIO); - tid = t->getTid(); // pid_t is unknown until run() - ALOGV("getTid=%d", tid); - if (tid == -1) { - tid = 0; - } - // thread blocks in readyToRun() - } else { - tid = 0; // not gettid() - } + if (!mActive) { + mActive = true; cblk->lock.lock(); if (!(cblk->flags & CBLK_INVALID_MSK)) { @@ -338,58 +310,51 @@ status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession) AudioSystem::kSyncRecordStartTimeOutMs; cblk->waitTimeMs = 0; if (t != 0) { - // thread unblocks in readyToRun() and returns NO_ERROR - mReadyToRun = NO_ERROR; - mCondition.signal(); + t->resume(); } else { mPreviousPriority = getpriority(PRIO_PROCESS, 0); get_sched_policy(0, &mPreviousSchedulingGroup); androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); } } else { - mActive = 0; - // thread unblocks in readyToRun() and returns NO_INIT - mReadyToRun = NO_INIT; - mCondition.signal(); + mActive = false; } } return ret; } -status_t AudioRecord::stop() +void AudioRecord::stop() { - sp<ClientRecordThread> t = mClientRecordThread; + sp<AudioRecordThread> t = mAudioRecordThread; ALOGV("stop"); AutoMutex lock(mLock); - if (mActive == 1) { - mActive = 0; + if (mActive) { + mActive = false; mCblk->cv.signal(); mAudioRecord->stop(); // the record head position will reset to 0, so if a marker is set, we need // to activate it again mMarkerReached = false; if (t != 0) { - t->requestExit(); + t->pause(); } else { setpriority(PRIO_PROCESS, 0, mPreviousPriority); set_sched_policy(0, mPreviousSchedulingGroup); } } - - return NO_ERROR; } bool AudioRecord::stopped() const { + AutoMutex lock(mLock); return !mActive; } uint32_t AudioRecord::getSampleRate() const { - AutoMutex lock(mLock); return mCblk->sampleRate; } @@ -397,6 +362,7 @@ status_t AudioRecord::setMarkerPosition(uint32_t marker) { if (mCbf == NULL) return INVALID_OPERATION; + AutoMutex lock(mLock); mMarkerPosition = marker; mMarkerReached = false; @@ -407,6 +373,7 @@ status_t AudioRecord::getMarkerPosition(uint32_t *marker) const { if (marker == NULL) return BAD_VALUE; + AutoMutex lock(mLock); *marker = mMarkerPosition; return NO_ERROR; @@ -418,6 +385,8 @@ status_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod) uint32_t curPosition; getPosition(&curPosition); + + AutoMutex lock(mLock); mNewPosition = curPosition + updatePeriod; mUpdatePeriod = updatePeriod; @@ -428,6 +397,7 @@ status_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) const { if (updatePeriod == NULL) return BAD_VALUE; + AutoMutex lock(mLock); *updatePeriod = mUpdatePeriod; return NO_ERROR; @@ -445,10 +415,8 @@ status_t AudioRecord::getPosition(uint32_t *position) const unsigned int AudioRecord::getInputFramesLost() const { - if (mActive) - return AudioSystem::getInputFramesLost(mInput); - else - return 0; + // no need to check mActive, because if inactive this will return 0, which is what we want + return AudioSystem::getInputFramesLost(mInput); } // ------------------------------------------------------------------------- @@ -457,7 +425,7 @@ unsigned int AudioRecord::getInputFramesLost() const status_t AudioRecord::openRecord_l( uint32_t sampleRate, audio_format_t format, - uint32_t channelMask, + audio_channel_mask_t channelMask, int frameCount, audio_io_handle_t input) { @@ -467,13 +435,20 @@ status_t AudioRecord::openRecord_l( return NO_INIT; } + pid_t tid = -1; + // FIXME see similar logic at AudioTrack + + int originalSessionId = mSessionId; sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), input, sampleRate, format, channelMask, frameCount, IAudioFlinger::TRACK_DEFAULT, + tid, &mSessionId, &status); + ALOGE_IF(originalSessionId != 0 && mSessionId != originalSessionId, + "session ID changed from %d to %d", originalSessionId, mSessionId); if (record == 0) { ALOGE("AudioFlinger could not create record track, status: %d", status); @@ -499,7 +474,7 @@ status_t AudioRecord::openRecord_l( status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) { AutoMutex lock(mLock); - int active; + bool active; status_t result = NO_ERROR; audio_track_cblk_t* cblk = mCblk; uint32_t framesReq = audioBuffer->frameCount; @@ -528,7 +503,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); cblk->lock.unlock(); mLock.lock(); - if (mActive == 0) { + if (!mActive) { return status_t(STOPPED); } cblk->lock.lock(); @@ -613,13 +588,13 @@ audio_io_handle_t AudioRecord::getInput_l() mCblk->sampleRate, mFormat, mChannelMask, - (audio_in_acoustics_t)mFlags, mSessionId); return mInput; } int AudioRecord::getSessionId() const { + // no lock needed because session ID doesn't change after first set() return mSessionId; } @@ -678,7 +653,7 @@ ssize_t AudioRecord::read(void* buffer, size_t userSize) // ------------------------------------------------------------------------- -bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread) +bool AudioRecord::processAudioBuffer(const sp<AudioRecordThread>& thread) { Buffer audioBuffer; uint32_t frames = mRemainingFrames; @@ -690,22 +665,32 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread) sp<IAudioRecord> audioRecord = mAudioRecord; sp<IMemory> iMem = mCblkMemory; audio_track_cblk_t* cblk = mCblk; + bool active = mActive; + uint32_t markerPosition = mMarkerPosition; + uint32_t newPosition = mNewPosition; + uint32_t user = cblk->user; + // determine whether a marker callback will be needed, while locked + bool needMarker = !mMarkerReached && (mMarkerPosition > 0) && (user >= mMarkerPosition); + if (needMarker) { + mMarkerReached = true; + } + // determine the number of new position callback(s) that will be needed, while locked + uint32_t updatePeriod = mUpdatePeriod; + uint32_t needNewPos = updatePeriod > 0 && user >= newPosition ? + ((user - newPosition) / updatePeriod) + 1 : 0; + mNewPosition = newPosition + updatePeriod * needNewPos; mLock.unlock(); - // Manage marker callback - if (!mMarkerReached && (mMarkerPosition > 0)) { - if (cblk->user >= mMarkerPosition) { - mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition); - mMarkerReached = true; - } + // perform marker callback, while unlocked + if (needMarker) { + mCbf(EVENT_MARKER, mUserData, &markerPosition); } - // Manage new position callback - if (mUpdatePeriod > 0) { - while (cblk->user >= mNewPosition) { - mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition); - mNewPosition += mUpdatePeriod; - } + // perform new position callback(s), while unlocked + for (; needNewPos > 0; --needNewPos) { + uint32_t temp = newPosition; + mCbf(EVENT_NEW_POS, mUserData, &temp); + newPosition += updatePeriod; } do { @@ -748,10 +733,12 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread) // Manage overrun callback - if (mActive && (cblk->framesAvailable() == 0)) { + if (active && (cblk->framesAvailable() == 0)) { + // The value of active is stale, but we are almost sure to be active here because + // otherwise we would have exited when obtainBuffer returned STOPPED earlier. ALOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags); if (!(android_atomic_or(CBLK_UNDERRUN_ON, &cblk->flags) & CBLK_UNDERRUN_MSK)) { - mCbf(EVENT_OVERRUN, mUserData, 0); + mCbf(EVENT_OVERRUN, mUserData, NULL); } } @@ -805,7 +792,7 @@ status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk) result = NO_ERROR; cblk->lock.unlock(); } - if (result != NO_ERROR || mActive == 0) { + if (result != NO_ERROR || !mActive) { result = status_t(STOPPED); } } @@ -825,23 +812,51 @@ status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk) // ========================================================================= -AudioRecord::ClientRecordThread::ClientRecordThread(AudioRecord& receiver, bool bCanCallJava) - : Thread(bCanCallJava), mReceiver(receiver) +AudioRecord::AudioRecordThread::AudioRecordThread(AudioRecord& receiver, bool bCanCallJava) + : Thread(bCanCallJava), mReceiver(receiver), mPaused(true) +{ +} + +AudioRecord::AudioRecordThread::~AudioRecordThread() +{ +} + +bool AudioRecord::AudioRecordThread::threadLoop() +{ + { + AutoMutex _l(mMyLock); + if (mPaused) { + mMyCond.wait(mMyLock); + // caller will check for exitPending() + return true; + } + } + if (!mReceiver.processAudioBuffer(this)) { + pause(); + } + return true; +} + +void AudioRecord::AudioRecordThread::requestExit() { + // must be in this order to avoid a race condition + Thread::requestExit(); + resume(); } -bool AudioRecord::ClientRecordThread::threadLoop() +void AudioRecord::AudioRecordThread::pause() { - return mReceiver.processAudioBuffer(this); + AutoMutex _l(mMyLock); + mPaused = true; } -status_t AudioRecord::ClientRecordThread::readyToRun() +void AudioRecord::AudioRecordThread::resume() { - AutoMutex(mReceiver.mLock); - while (mReceiver.mReadyToRun == WOULD_BLOCK) { - mReceiver.mCondition.wait(mReceiver.mLock); + AutoMutex _l(mMyLock); + if (mPaused) { + mPaused = false; + mMyCond.signal(); } - return mReceiver.mReadyToRun; } // ------------------------------------------------------------------------- diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 4c41ba5..207f96f 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -41,7 +41,7 @@ DefaultKeyedVector<audio_io_handle_t, AudioSystem::OutputDescriptor *> AudioSyst // Cached values for recording queries, all protected by gLock uint32_t AudioSystem::gPrevInSamplingRate = 16000; audio_format_t AudioSystem::gPrevInFormat = AUDIO_FORMAT_PCM_16_BIT; -int AudioSystem::gPrevInChannelCount = 1; +audio_channel_mask_t AudioSystem::gPrevInChannelMask = AUDIO_CHANNEL_IN_MONO; size_t AudioSystem::gInBuffSize = 0; @@ -334,25 +334,25 @@ status_t AudioSystem::getLatency(audio_io_handle_t output, return NO_ERROR; } -status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, audio_format_t format, int channelCount, - size_t* buffSize) +status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, audio_format_t format, + audio_channel_mask_t channelMask, size_t* buffSize) { gLock.lock(); // Do we have a stale gInBufferSize or are we requesting the input buffer size for new values size_t inBuffSize = gInBuffSize; if ((inBuffSize == 0) || (sampleRate != gPrevInSamplingRate) || (format != gPrevInFormat) - || (channelCount != gPrevInChannelCount)) { + || (channelMask != gPrevInChannelMask)) { gLock.unlock(); const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); if (af == 0) { return PERMISSION_DENIED; } - inBuffSize = af->getInputBufferSize(sampleRate, format, channelCount); + inBuffSize = af->getInputBufferSize(sampleRate, format, channelMask); gLock.lock(); // save the request params gPrevInSamplingRate = sampleRate; gPrevInFormat = format; - gPrevInChannelCount = channelCount; + gPrevInChannelMask = channelMask; gInBuffSize = inBuffSize; } @@ -449,7 +449,7 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(int event, audio_io_handle OutputDescriptor *outputDesc = new OutputDescriptor(*desc); gOutputs.add(ioHandle, outputDesc); - ALOGV("ioConfigChanged() new output samplingRate %d, format %d channels %d frameCount %d latency %d", + ALOGV("ioConfigChanged() new output samplingRate %d, format %d channels %#x frameCount %d latency %d", outputDesc->samplingRate, outputDesc->format, outputDesc->channels, outputDesc->frameCount, outputDesc->latency); } break; case OUTPUT_CLOSED: { @@ -471,7 +471,7 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(int event, audio_io_handle if (param2 == NULL) break; desc = (const OutputDescriptor *)param2; - ALOGV("ioConfigChanged() new config for output %d samplingRate %d, format %d channels %d frameCount %d latency %d", + ALOGV("ioConfigChanged() new config for output %d samplingRate %d, format %d channels %#x frameCount %d latency %d", ioHandle, desc->samplingRate, desc->format, desc->channels, desc->frameCount, desc->latency); OutputDescriptor *outputDesc = gOutputs.valueAt(index); @@ -588,12 +588,12 @@ audio_policy_forced_cfg_t AudioSystem::getForceUse(audio_policy_force_use_t usag audio_io_handle_t AudioSystem::getOutput(audio_stream_type_t stream, uint32_t samplingRate, audio_format_t format, - uint32_t channels, + audio_channel_mask_t channelMask, audio_output_flags_t flags) { const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return 0; - return aps->getOutput(stream, samplingRate, format, channels, flags); + return aps->getOutput(stream, samplingRate, format, channelMask, flags); } status_t AudioSystem::startOutput(audio_io_handle_t output, @@ -624,13 +624,12 @@ void AudioSystem::releaseOutput(audio_io_handle_t output) audio_io_handle_t AudioSystem::getInput(audio_source_t inputSource, uint32_t samplingRate, audio_format_t format, - uint32_t channels, - audio_in_acoustics_t acoustics, + audio_channel_mask_t channelMask, int sessionId) { const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return 0; - return aps->getInput(inputSource, samplingRate, format, channels, acoustics, sessionId); + return aps->getInput(inputSource, samplingRate, format, channelMask, sessionId); } status_t AudioSystem::startInput(audio_io_handle_t input) @@ -695,14 +694,14 @@ audio_devices_t AudioSystem::getDevicesForStream(audio_stream_type_t stream) return aps->getDevicesForStream(stream); } -audio_io_handle_t AudioSystem::getOutputForEffect(effect_descriptor_t *desc) +audio_io_handle_t AudioSystem::getOutputForEffect(const effect_descriptor_t *desc) { const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return PERMISSION_DENIED; return aps->getOutputForEffect(desc); } -status_t AudioSystem::registerEffect(effect_descriptor_t *desc, +status_t AudioSystem::registerEffect(const effect_descriptor_t *desc, audio_io_handle_t io, uint32_t strategy, int session, @@ -736,6 +735,28 @@ status_t AudioSystem::isStreamActive(audio_stream_type_t stream, bool* state, ui return NO_ERROR; } +status_t AudioSystem::isSourceActive(audio_source_t stream, bool* state) +{ + const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + if (state == NULL) return BAD_VALUE; + *state = aps->isSourceActive(stream); + return NO_ERROR; +} + +int32_t AudioSystem::getPrimaryOutputSamplingRate() +{ + const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); + if (af == 0) return 0; + return af->getPrimaryOutputSamplingRate(); +} + +int32_t AudioSystem::getPrimaryOutputFrameCount() +{ + const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); + if (af == 0) return 0; + return af->getPrimaryOutputFrameCount(); +} void AudioSystem::clearAudioConfigCache() { diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index e5a60f5..362d022 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -54,6 +54,11 @@ status_t AudioTrack::getMinFrameCount( audio_stream_type_t streamType, uint32_t sampleRate) { + if (frameCount == NULL) return BAD_VALUE; + + // default to 0 in case of error + *frameCount = 0; + // FIXME merge with similar code in createTrack_l(), except we're missing // some information here that is available in createTrack_l(): // audio_io_handle_t output @@ -98,7 +103,7 @@ AudioTrack::AudioTrack( audio_stream_type_t streamType, uint32_t sampleRate, audio_format_t format, - int channelMask, + audio_channel_mask_t channelMask, int frameCount, audio_output_flags_t flags, callback_t cbf, @@ -131,7 +136,8 @@ AudioTrack::AudioTrack( mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT) { - mStatus = set((audio_stream_type_t)streamType, sampleRate, (audio_format_t)format, channelMask, + mStatus = set((audio_stream_type_t)streamType, sampleRate, (audio_format_t)format, + (audio_channel_mask_t) channelMask, frameCount, (audio_output_flags_t)flags, cbf, user, notificationFrames, 0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId); } @@ -140,7 +146,7 @@ AudioTrack::AudioTrack( audio_stream_type_t streamType, uint32_t sampleRate, audio_format_t format, - int channelMask, + audio_channel_mask_t channelMask, const sp<IMemory>& sharedBuffer, audio_output_flags_t flags, callback_t cbf, @@ -181,7 +187,7 @@ status_t AudioTrack::set( audio_stream_type_t streamType, uint32_t sampleRate, audio_format_t format, - int channelMask, + audio_channel_mask_t channelMask, int frameCount, audio_output_flags_t flags, callback_t cbf, @@ -247,7 +253,7 @@ status_t AudioTrack::set( } if (!audio_is_output_channel(channelMask)) { - ALOGE("Invalid channel mask"); + ALOGE("Invalid channel mask %#x", channelMask); return BAD_VALUE; } uint32_t channelCount = popcount(channelMask); @@ -281,7 +287,7 @@ status_t AudioTrack::set( status_t status = createTrack_l(streamType, sampleRate, format, - (uint32_t)channelMask, + channelMask, frameCount, flags, sharedBuffer, @@ -299,7 +305,7 @@ status_t AudioTrack::set( mStreamType = streamType; mFormat = format; - mChannelMask = (uint32_t)channelMask; + mChannelMask = channelMask; mChannelCount = channelCount; mSharedBuffer = sharedBuffer; mMuted = false; @@ -367,7 +373,6 @@ sp<IMemory>& AudioTrack::sharedBuffer() void AudioTrack::start() { sp<AudioTrackThread> t = mAudioTrackThread; - status_t status = NO_ERROR; ALOGV("start %p", this); @@ -395,6 +400,7 @@ void AudioTrack::start() } ALOGV("start %p before lock cblk %p", this, mCblk); + status_t status = NO_ERROR; if (!(cblk->flags & CBLK_INVALID_MSK)) { cblk->lock.unlock(); ALOGV("mAudioTrack->start()"); @@ -744,7 +750,7 @@ status_t AudioTrack::createTrack_l( audio_stream_type_t streamType, uint32_t sampleRate, audio_format_t format, - uint32_t channelMask, + audio_channel_mask_t channelMask, int frameCount, audio_output_flags_t flags, const sp<IMemory>& sharedBuffer, @@ -1138,7 +1144,7 @@ status_t TimedAudioTrack::allocateTimedBuffer(size_t size, sp<IMemory>* buffer) // If the track is not invalid already, try to allocate a buffer. alloc // fails indicating that the server is dead, flag the track as invalid so - // we can attempt to restore in in just a bit. + // we can attempt to restore in just a bit. if (!(mCblk->flags & CBLK_INVALID_MSK)) { result = mAudioTrack->allocateTimedBuffer(size, buffer); if (result == DEAD_OBJECT) { @@ -1472,15 +1478,6 @@ bool AudioTrack::AudioTrackThread::threadLoop() return true; } -status_t AudioTrack::AudioTrackThread::readyToRun() -{ - return NO_ERROR; -} - -void AudioTrack::AudioTrackThread::onFirstRef() -{ -} - void AudioTrack::AudioTrackThread::requestExit() { // must be in this order to avoid a race condition diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index e8dd438..ce8ffc4 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -32,7 +32,7 @@ enum { CREATE_TRACK = IBinder::FIRST_CALL_TRANSACTION, OPEN_RECORD, SAMPLE_RATE, - CHANNEL_COUNT, + CHANNEL_COUNT, // obsolete FORMAT, FRAME_COUNT, LATENCY, @@ -70,7 +70,9 @@ enum { GET_EFFECT_DESCRIPTOR, CREATE_EFFECT, MOVE_EFFECTS, - LOAD_HW_MODULE + LOAD_HW_MODULE, + GET_PRIMARY_OUTPUT_SAMPLING_RATE, + GET_PRIMARY_OUTPUT_FRAME_COUNT, }; class BpAudioFlinger : public BpInterface<IAudioFlinger> @@ -86,7 +88,7 @@ public: audio_stream_type_t streamType, uint32_t sampleRate, audio_format_t format, - uint32_t channelMask, + audio_channel_mask_t channelMask, int frameCount, track_flags_t flags, const sp<IMemory>& sharedBuffer, @@ -135,9 +137,10 @@ public: audio_io_handle_t input, uint32_t sampleRate, audio_format_t format, - uint32_t channelMask, + audio_channel_mask_t channelMask, int frameCount, track_flags_t flags, + pid_t tid, int *sessionId, status_t *status) { @@ -151,6 +154,7 @@ public: data.writeInt32(channelMask); data.writeInt32(frameCount); data.writeInt32(flags); + data.writeInt32((int32_t) tid); int lSessionId = 0; if (sessionId != NULL) { lSessionId = *sessionId; @@ -182,6 +186,7 @@ public: return reply.readInt32(); } +#if 0 virtual int channelCount(audio_io_handle_t output) const { Parcel data, reply; @@ -190,6 +195,7 @@ public: remote()->transact(CHANNEL_COUNT, data, &reply); return reply.readInt32(); } +#endif virtual audio_format_t format(audio_io_handle_t output) const { @@ -347,13 +353,14 @@ public: remote()->transact(REGISTER_CLIENT, data, &reply); } - virtual size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format, int channelCount) const + virtual size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format, + audio_channel_mask_t channelMask) const { Parcel data, reply; data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); data.writeInt32(sampleRate); data.writeInt32(format); - data.writeInt32(channelCount); + data.writeInt32(channelMask); remote()->transact(GET_INPUTBUFFERSIZE, data, &reply); return reply.readInt32(); } @@ -682,6 +689,23 @@ public: remote()->transact(LOAD_HW_MODULE, data, &reply); return (audio_module_handle_t) reply.readInt32(); } + + virtual int32_t getPrimaryOutputSamplingRate() + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + remote()->transact(GET_PRIMARY_OUTPUT_SAMPLING_RATE, data, &reply); + return reply.readInt32(); + } + + virtual int32_t getPrimaryOutputFrameCount() + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + remote()->transact(GET_PRIMARY_OUTPUT_FRAME_COUNT, data, &reply); + return reply.readInt32(); + } + }; IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger"); @@ -698,7 +722,7 @@ status_t BnAudioFlinger::onTransact( int streamType = data.readInt32(); uint32_t sampleRate = data.readInt32(); audio_format_t format = (audio_format_t) data.readInt32(); - int channelCount = data.readInt32(); + audio_channel_mask_t channelMask = data.readInt32(); size_t bufferCount = data.readInt32(); track_flags_t flags = (track_flags_t) data.readInt32(); sp<IMemory> buffer = interface_cast<IMemory>(data.readStrongBinder()); @@ -708,7 +732,7 @@ status_t BnAudioFlinger::onTransact( status_t status; sp<IAudioTrack> track = createTrack(pid, (audio_stream_type_t) streamType, sampleRate, format, - channelCount, bufferCount, flags, buffer, output, tid, &sessionId, &status); + channelMask, bufferCount, flags, buffer, output, tid, &sessionId, &status); reply->writeInt32(sessionId); reply->writeInt32(status); reply->writeStrongBinder(track->asBinder()); @@ -720,13 +744,14 @@ status_t BnAudioFlinger::onTransact( audio_io_handle_t input = (audio_io_handle_t) data.readInt32(); uint32_t sampleRate = data.readInt32(); audio_format_t format = (audio_format_t) data.readInt32(); - int channelCount = data.readInt32(); + audio_channel_mask_t channelMask = data.readInt32(); size_t bufferCount = data.readInt32(); track_flags_t flags = (track_flags_t) data.readInt32(); + pid_t tid = (pid_t) data.readInt32(); int sessionId = data.readInt32(); status_t status; sp<IAudioRecord> record = openRecord(pid, input, - sampleRate, format, channelCount, bufferCount, flags, &sessionId, &status); + sampleRate, format, channelMask, bufferCount, flags, tid, &sessionId, &status); reply->writeInt32(sessionId); reply->writeInt32(status); reply->writeStrongBinder(record->asBinder()); @@ -737,11 +762,13 @@ status_t BnAudioFlinger::onTransact( reply->writeInt32( sampleRate((audio_io_handle_t) data.readInt32()) ); return NO_ERROR; } break; +#if 0 case CHANNEL_COUNT: { CHECK_INTERFACE(IAudioFlinger, data, reply); reply->writeInt32( channelCount((audio_io_handle_t) data.readInt32()) ); return NO_ERROR; } break; +#endif case FORMAT: { CHECK_INTERFACE(IAudioFlinger, data, reply); reply->writeInt32( format((audio_io_handle_t) data.readInt32()) ); @@ -846,8 +873,8 @@ status_t BnAudioFlinger::onTransact( CHECK_INTERFACE(IAudioFlinger, data, reply); uint32_t sampleRate = data.readInt32(); audio_format_t format = (audio_format_t) data.readInt32(); - int channelCount = data.readInt32(); - reply->writeInt32( getInputBufferSize(sampleRate, format, channelCount) ); + audio_channel_mask_t channelMask = data.readInt32(); + reply->writeInt32( getInputBufferSize(sampleRate, format, channelMask) ); return NO_ERROR; } break; case OPEN_OUTPUT: { @@ -1037,6 +1064,16 @@ status_t BnAudioFlinger::onTransact( reply->writeInt32(loadHwModule(data.readCString())); return NO_ERROR; } break; + case GET_PRIMARY_OUTPUT_SAMPLING_RATE: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + reply->writeInt32(getPrimaryOutputSamplingRate()); + return NO_ERROR; + } break; + case GET_PRIMARY_OUTPUT_FRAME_COUNT: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + reply->writeInt32(getPrimaryOutputFrameCount()); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index 7aab8d6..401437c 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -52,6 +52,7 @@ enum { REGISTER_EFFECT, UNREGISTER_EFFECT, IS_STREAM_ACTIVE, + IS_SOURCE_ACTIVE, GET_DEVICES_FOR_STREAM, QUERY_DEFAULT_PRE_PROCESSING, SET_EFFECT_ENABLED @@ -123,7 +124,7 @@ public: audio_stream_type_t stream, uint32_t samplingRate, audio_format_t format, - uint32_t channels, + audio_channel_mask_t channelMask, audio_output_flags_t flags) { Parcel data, reply; @@ -131,7 +132,7 @@ public: data.writeInt32(static_cast <uint32_t>(stream)); data.writeInt32(samplingRate); data.writeInt32(static_cast <uint32_t>(format)); - data.writeInt32(channels); + data.writeInt32(channelMask); data.writeInt32(static_cast <uint32_t>(flags)); remote()->transact(GET_OUTPUT, data, &reply); return static_cast <audio_io_handle_t> (reply.readInt32()); @@ -175,8 +176,7 @@ public: audio_source_t inputSource, uint32_t samplingRate, audio_format_t format, - uint32_t channels, - audio_in_acoustics_t acoustics, + audio_channel_mask_t channelMask, int audioSession) { Parcel data, reply; @@ -184,8 +184,7 @@ public: data.writeInt32((int32_t) inputSource); data.writeInt32(samplingRate); data.writeInt32(static_cast <uint32_t>(format)); - data.writeInt32(channels); - data.writeInt32(static_cast <uint32_t>(acoustics)); + data.writeInt32(channelMask); data.writeInt32(audioSession); remote()->transact(GET_INPUT, data, &reply); return static_cast <audio_io_handle_t> (reply.readInt32()); @@ -276,7 +275,7 @@ public: return (audio_devices_t) reply.readInt32(); } - virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc) + virtual audio_io_handle_t getOutputForEffect(const effect_descriptor_t *desc) { Parcel data, reply; data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); @@ -285,7 +284,7 @@ public: return static_cast <audio_io_handle_t> (reply.readInt32()); } - virtual status_t registerEffect(effect_descriptor_t *desc, + virtual status_t registerEffect(const effect_descriptor_t *desc, audio_io_handle_t io, uint32_t strategy, int session, @@ -331,6 +330,15 @@ public: return reply.readInt32(); } + virtual bool isSourceActive(audio_source_t source) const + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.writeInt32((int32_t) source); + remote()->transact(IS_SOURCE_ACTIVE, data, &reply); + return reply.readInt32(); + } + virtual status_t queryDefaultPreProcessing(int audioSession, effect_descriptor_t *descriptors, uint32_t *count) @@ -417,14 +425,14 @@ status_t BnAudioPolicyService::onTransact( static_cast <audio_stream_type_t>(data.readInt32()); uint32_t samplingRate = data.readInt32(); audio_format_t format = (audio_format_t) data.readInt32(); - uint32_t channels = data.readInt32(); + audio_channel_mask_t channelMask = data.readInt32(); audio_output_flags_t flags = static_cast <audio_output_flags_t>(data.readInt32()); audio_io_handle_t output = getOutput(stream, samplingRate, format, - channels, + channelMask, flags); reply->writeInt32(static_cast <int>(output)); return NO_ERROR; @@ -464,15 +472,12 @@ status_t BnAudioPolicyService::onTransact( audio_source_t inputSource = (audio_source_t) data.readInt32(); uint32_t samplingRate = data.readInt32(); audio_format_t format = (audio_format_t) data.readInt32(); - uint32_t channels = data.readInt32(); - audio_in_acoustics_t acoustics = - static_cast <audio_in_acoustics_t>(data.readInt32()); + audio_channel_mask_t channelMask = data.readInt32(); int audioSession = data.readInt32(); audio_io_handle_t input = getInput(inputSource, samplingRate, format, - channels, - acoustics, + channelMask, audioSession); reply->writeInt32(static_cast <int>(input)); return NO_ERROR; @@ -597,6 +602,13 @@ status_t BnAudioPolicyService::onTransact( return NO_ERROR; } break; + case IS_SOURCE_ACTIVE: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_source_t source = (audio_source_t) data.readInt32(); + reply->writeInt32( isSourceActive(source)); + return NO_ERROR; + } + case QUERY_DEFAULT_PRE_PROCESSING: { CHECK_INTERFACE(IAudioPolicyService, data, reply); int audioSession = data.readInt32(); diff --git a/media/libmedia/IAudioRecord.cpp b/media/libmedia/IAudioRecord.cpp index 57a80a9..0d06e98 100644 --- a/media/libmedia/IAudioRecord.cpp +++ b/media/libmedia/IAudioRecord.cpp @@ -42,7 +42,7 @@ public: { } - virtual status_t start(int event, int triggerSession) + virtual status_t start(int /*AudioSystem::sync_event_t*/ event, int triggerSession) { Parcel data, reply; data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor()); @@ -92,7 +92,7 @@ status_t BnAudioRecord::onTransact( } break; case START: { CHECK_INTERFACE(IAudioRecord, data, reply); - int event = data.readInt32(); + int /*AudioSystem::sync_event_t*/ event = data.readInt32(); int triggerSession = data.readInt32(); reply->writeInt32(start(event, triggerSession)); return NO_ERROR; diff --git a/media/libmedia/IHDCP.cpp b/media/libmedia/IHDCP.cpp new file mode 100644 index 0000000..493f5a4 --- /dev/null +++ b/media/libmedia/IHDCP.cpp @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2012 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 "IHDCP" +#include <utils/Log.h> + +#include <binder/Parcel.h> +#include <media/IHDCP.h> +#include <media/stagefright/MediaErrors.h> +#include <media/stagefright/foundation/ADebug.h> + +namespace android { + +enum { + OBSERVER_NOTIFY = IBinder::FIRST_CALL_TRANSACTION, + HDCP_SET_OBSERVER, + HDCP_INIT_ASYNC, + HDCP_SHUTDOWN_ASYNC, + HDCP_ENCRYPT, +}; + +struct BpHDCPObserver : public BpInterface<IHDCPObserver> { + BpHDCPObserver(const sp<IBinder> &impl) + : BpInterface<IHDCPObserver>(impl) { + } + + virtual void notify( + int msg, int ext1, int ext2, const Parcel *obj) { + Parcel data, reply; + data.writeInterfaceToken(IHDCPObserver::getInterfaceDescriptor()); + data.writeInt32(msg); + data.writeInt32(ext1); + data.writeInt32(ext2); + if (obj && obj->dataSize() > 0) { + data.appendFrom(const_cast<Parcel *>(obj), 0, obj->dataSize()); + } + remote()->transact(OBSERVER_NOTIFY, data, &reply, IBinder::FLAG_ONEWAY); + } +}; + +IMPLEMENT_META_INTERFACE(HDCPObserver, "android.hardware.IHDCPObserver"); + +struct BpHDCP : public BpInterface<IHDCP> { + BpHDCP(const sp<IBinder> &impl) + : BpInterface<IHDCP>(impl) { + } + + virtual status_t setObserver(const sp<IHDCPObserver> &observer) { + Parcel data, reply; + data.writeInterfaceToken(IHDCP::getInterfaceDescriptor()); + data.writeStrongBinder(observer->asBinder()); + remote()->transact(HDCP_SET_OBSERVER, data, &reply); + return reply.readInt32(); + } + + virtual status_t initAsync(const char *host, unsigned port) { + Parcel data, reply; + data.writeInterfaceToken(IHDCP::getInterfaceDescriptor()); + data.writeCString(host); + data.writeInt32(port); + remote()->transact(HDCP_INIT_ASYNC, data, &reply); + return reply.readInt32(); + } + + virtual status_t shutdownAsync() { + Parcel data, reply; + data.writeInterfaceToken(IHDCP::getInterfaceDescriptor()); + remote()->transact(HDCP_SHUTDOWN_ASYNC, data, &reply); + return reply.readInt32(); + } + + virtual status_t encrypt( + const void *inData, size_t size, uint32_t streamCTR, + uint64_t *outInputCTR, void *outData) { + Parcel data, reply; + data.writeInterfaceToken(IHDCP::getInterfaceDescriptor()); + data.writeInt32(size); + data.write(inData, size); + data.writeInt32(streamCTR); + remote()->transact(HDCP_ENCRYPT, data, &reply); + + status_t err = reply.readInt32(); + + if (err != OK) { + *outInputCTR = 0; + + return err; + } + + *outInputCTR = reply.readInt64(); + reply.read(outData, size); + + return err; + } +}; + +IMPLEMENT_META_INTERFACE(HDCP, "android.hardware.IHDCP"); + +status_t BnHDCPObserver::onTransact( + uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { + switch (code) { + case OBSERVER_NOTIFY: + { + CHECK_INTERFACE(IHDCPObserver, data, reply); + + int msg = data.readInt32(); + int ext1 = data.readInt32(); + int ext2 = data.readInt32(); + + Parcel obj; + if (data.dataAvail() > 0) { + obj.appendFrom( + const_cast<Parcel *>(&data), + data.dataPosition(), + data.dataAvail()); + } + + notify(msg, ext1, ext2, &obj); + + return OK; + } + + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +status_t BnHDCP::onTransact( + uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { + switch (code) { + case HDCP_SET_OBSERVER: + { + CHECK_INTERFACE(IHDCP, data, reply); + + sp<IHDCPObserver> observer = + interface_cast<IHDCPObserver>(data.readStrongBinder()); + + reply->writeInt32(setObserver(observer)); + return OK; + } + + case HDCP_INIT_ASYNC: + { + CHECK_INTERFACE(IHDCP, data, reply); + + const char *host = data.readCString(); + unsigned port = data.readInt32(); + + reply->writeInt32(initAsync(host, port)); + return OK; + } + + case HDCP_SHUTDOWN_ASYNC: + { + CHECK_INTERFACE(IHDCP, data, reply); + + reply->writeInt32(shutdownAsync()); + return OK; + } + + case HDCP_ENCRYPT: + { + size_t size = data.readInt32(); + + void *inData = malloc(2 * size); + void *outData = (uint8_t *)inData + size; + + data.read(inData, size); + + uint32_t streamCTR = data.readInt32(); + uint64_t inputCTR; + status_t err = encrypt(inData, size, streamCTR, &inputCTR, outData); + + reply->writeInt32(err); + + if (err == OK) { + reply->writeInt64(inputCTR); + reply->write(outData, size); + } + + free(inData); + inData = outData = NULL; + + return OK; + } + + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +} // namespace android diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp index 0bb237d..cb07766 100644 --- a/media/libmedia/IMediaPlayer.cpp +++ b/media/libmedia/IMediaPlayer.cpp @@ -55,6 +55,7 @@ enum { SET_PARAMETER, GET_PARAMETER, SET_RETRANSMIT_ENDPOINT, + GET_RETRANSMIT_ENDPOINT, SET_NEXT_PLAYER, }; @@ -292,7 +293,8 @@ public: return remote()->transact(GET_PARAMETER, data, reply); } - status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint) { + status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint) + { Parcel data, reply; status_t err; @@ -319,6 +321,23 @@ public: remote()->transact(SET_NEXT_PLAYER, data, &reply); return reply.readInt32(); } + + status_t getRetransmitEndpoint(struct sockaddr_in* endpoint) + { + Parcel data, reply; + status_t err; + + data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + err = remote()->transact(GET_RETRANSMIT_ENDPOINT, data, &reply); + + if ((OK != err) || (OK != (err = reply.readInt32()))) { + return err; + } + + data.read(endpoint, sizeof(*endpoint)); + + return err; + } }; IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer"); @@ -498,11 +517,24 @@ status_t BnMediaPlayer::onTransact( } else { reply->writeInt32(setRetransmitEndpoint(NULL)); } + + return NO_ERROR; + } break; + case GET_RETRANSMIT_ENDPOINT: { + CHECK_INTERFACE(IMediaPlayer, data, reply); + + struct sockaddr_in endpoint; + status_t res = getRetransmitEndpoint(&endpoint); + + reply->writeInt32(res); + reply->write(&endpoint, sizeof(endpoint)); + return NO_ERROR; } break; case SET_NEXT_PLAYER: { CHECK_INTERFACE(IMediaPlayer, data, reply); reply->writeInt32(setNextPlayer(interface_cast<IMediaPlayer>(data.readStrongBinder()))); + return NO_ERROR; } break; default: diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp index 9120617..c0a0260 100644 --- a/media/libmedia/IMediaPlayerService.cpp +++ b/media/libmedia/IMediaPlayerService.cpp @@ -21,12 +21,16 @@ #include <binder/Parcel.h> #include <binder/IMemory.h> #include <media/ICrypto.h> +#include <media/IHDCP.h> #include <media/IMediaPlayerService.h> #include <media/IMediaRecorder.h> #include <media/IOMX.h> +#include <media/IRemoteDisplay.h> +#include <media/IRemoteDisplayClient.h> #include <media/IStreamSource.h> #include <utils/Errors.h> // for status_t +#include <utils/String8.h> namespace android { @@ -38,8 +42,10 @@ enum { CREATE_METADATA_RETRIEVER, GET_OMX, MAKE_CRYPTO, + MAKE_HDCP, ADD_BATTERY_DATA, - PULL_BATTERY_DATA + PULL_BATTERY_DATA, + LISTEN_FOR_REMOTE_DISPLAY, }; class BpMediaPlayerService: public BpInterface<IMediaPlayerService> @@ -120,6 +126,13 @@ public: return interface_cast<ICrypto>(reply.readStrongBinder()); } + virtual sp<IHDCP> makeHDCP() { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); + remote()->transact(MAKE_HDCP, data, &reply); + return interface_cast<IHDCP>(reply.readStrongBinder()); + } + virtual void addBatteryData(uint32_t params) { Parcel data, reply; data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); @@ -132,6 +145,17 @@ public: data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); return remote()->transact(PULL_BATTERY_DATA, data, reply); } + + virtual sp<IRemoteDisplay> listenForRemoteDisplay(const sp<IRemoteDisplayClient>& client, + const String8& iface) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); + data.writeStrongBinder(client->asBinder()); + data.writeString8(iface); + remote()->transact(LISTEN_FOR_REMOTE_DISPLAY, data, &reply); + return interface_cast<IRemoteDisplay>(reply.readStrongBinder()); + } }; IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService"); @@ -206,6 +230,12 @@ status_t BnMediaPlayerService::onTransact( reply->writeStrongBinder(crypto->asBinder()); return NO_ERROR; } break; + case MAKE_HDCP: { + CHECK_INTERFACE(IMediaPlayerService, data, reply); + sp<IHDCP> hdcp = makeHDCP(); + reply->writeStrongBinder(hdcp->asBinder()); + return NO_ERROR; + } break; case ADD_BATTERY_DATA: { CHECK_INTERFACE(IMediaPlayerService, data, reply); uint32_t params = data.readInt32(); @@ -217,6 +247,15 @@ status_t BnMediaPlayerService::onTransact( pullBatteryData(reply); return NO_ERROR; } break; + case LISTEN_FOR_REMOTE_DISPLAY: { + CHECK_INTERFACE(IMediaPlayerService, data, reply); + sp<IRemoteDisplayClient> client( + interface_cast<IRemoteDisplayClient>(data.readStrongBinder())); + String8 iface(data.readString8()); + sp<IRemoteDisplay> display(listenForRemoteDisplay(client, iface)); + reply->writeStrongBinder(display->asBinder()); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/media/libmedia/IRemoteDisplay.cpp b/media/libmedia/IRemoteDisplay.cpp new file mode 100644 index 0000000..da25a15 --- /dev/null +++ b/media/libmedia/IRemoteDisplay.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2012 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 <stdint.h> +#include <sys/types.h> + +#include <media/IRemoteDisplay.h> + +namespace android { + +enum { + DISPOSE = IBinder::FIRST_CALL_TRANSACTION, +}; + +class BpRemoteDisplay: public BpInterface<IRemoteDisplay> +{ +public: + BpRemoteDisplay(const sp<IBinder>& impl) + : BpInterface<IRemoteDisplay>(impl) + { + } + + status_t dispose() + { + Parcel data, reply; + data.writeInterfaceToken(IRemoteDisplay::getInterfaceDescriptor()); + remote()->transact(DISPOSE, data, &reply); + return reply.readInt32(); + } +}; + +IMPLEMENT_META_INTERFACE(RemoteDisplay, "android.media.IRemoteDisplay"); + +// ---------------------------------------------------------------------- + +status_t BnRemoteDisplay::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch (code) { + case DISPOSE: { + CHECK_INTERFACE(IRemoteDisplay, data, reply); + reply->writeInt32(dispose()); + return NO_ERROR; + } + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +}; // namespace android diff --git a/media/libmedia/IRemoteDisplayClient.cpp b/media/libmedia/IRemoteDisplayClient.cpp new file mode 100644 index 0000000..4a1b570 --- /dev/null +++ b/media/libmedia/IRemoteDisplayClient.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2012 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 <stdint.h> +#include <sys/types.h> + +#include <media/IRemoteDisplayClient.h> +#include <gui/ISurfaceTexture.h> +#include <utils/String8.h> + +namespace android { + +enum { + ON_DISPLAY_CONNECTED = IBinder::FIRST_CALL_TRANSACTION, + ON_DISPLAY_DISCONNECTED, + ON_DISPLAY_ERROR, +}; + +class BpRemoteDisplayClient: public BpInterface<IRemoteDisplayClient> +{ +public: + BpRemoteDisplayClient(const sp<IBinder>& impl) + : BpInterface<IRemoteDisplayClient>(impl) + { + } + + void onDisplayConnected(const sp<ISurfaceTexture>& surfaceTexture, + uint32_t width, uint32_t height, uint32_t flags) + { + Parcel data, reply; + data.writeInterfaceToken(IRemoteDisplayClient::getInterfaceDescriptor()); + data.writeStrongBinder(surfaceTexture->asBinder()); + data.writeInt32(width); + data.writeInt32(height); + data.writeInt32(flags); + remote()->transact(ON_DISPLAY_CONNECTED, data, &reply, IBinder::FLAG_ONEWAY); + } + + void onDisplayDisconnected() + { + Parcel data, reply; + data.writeInterfaceToken(IRemoteDisplayClient::getInterfaceDescriptor()); + remote()->transact(ON_DISPLAY_DISCONNECTED, data, &reply, IBinder::FLAG_ONEWAY); + } + + void onDisplayError(int32_t error) + { + Parcel data, reply; + data.writeInterfaceToken(IRemoteDisplayClient::getInterfaceDescriptor()); + data.writeInt32(error); + remote()->transact(ON_DISPLAY_ERROR, data, &reply, IBinder::FLAG_ONEWAY); + } +}; + +IMPLEMENT_META_INTERFACE(RemoteDisplayClient, "android.media.IRemoteDisplayClient"); + +// ---------------------------------------------------------------------- + +status_t BnRemoteDisplayClient::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch (code) { + case ON_DISPLAY_CONNECTED: { + CHECK_INTERFACE(IRemoteDisplayClient, data, reply); + sp<ISurfaceTexture> surfaceTexture( + interface_cast<ISurfaceTexture>(data.readStrongBinder())); + uint32_t width = data.readInt32(); + uint32_t height = data.readInt32(); + uint32_t flags = data.readInt32(); + onDisplayConnected(surfaceTexture, width, height, flags); + return NO_ERROR; + } + case ON_DISPLAY_DISCONNECTED: { + CHECK_INTERFACE(IRemoteDisplayClient, data, reply); + onDisplayDisconnected(); + return NO_ERROR; + } + case ON_DISPLAY_ERROR: { + CHECK_INTERFACE(IRemoteDisplayClient, data, reply); + int32_t error = data.readInt32(); + onDisplayError(error); + return NO_ERROR; + } + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +}; // namespace android diff --git a/media/libmedia/IStreamSource.cpp b/media/libmedia/IStreamSource.cpp index 078be94..78d810d 100644 --- a/media/libmedia/IStreamSource.cpp +++ b/media/libmedia/IStreamSource.cpp @@ -37,6 +37,7 @@ enum { SET_LISTENER = IBinder::FIRST_CALL_TRANSACTION, SET_BUFFERS, ON_BUFFER_AVAILABLE, + FLAGS, // IStreamListener QUEUE_BUFFER, @@ -72,6 +73,14 @@ struct BpStreamSource : public BpInterface<IStreamSource> { remote()->transact( ON_BUFFER_AVAILABLE, data, &reply, IBinder::FLAG_ONEWAY); } + + virtual uint32_t flags() const { + Parcel data, reply; + data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor()); + remote()->transact(FLAGS, data, &reply); + + return reply.readInt32(); + } }; IMPLEMENT_META_INTERFACE(StreamSource, "android.hardware.IStreamSource"); @@ -109,6 +118,13 @@ status_t BnStreamSource::onTransact( break; } + case FLAGS: + { + CHECK_INTERFACE(IStreamSource, data, reply); + reply->writeInt32(this->flags()); + break; + } + default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp index 48bbf8f..8319cd7 100644 --- a/media/libmedia/MediaProfiles.cpp +++ b/media/libmedia/MediaProfiles.cpp @@ -373,7 +373,7 @@ MediaProfiles::getCameraId(const char** atts) void MediaProfiles::addStartTimeOffset(int cameraId, const char** atts) { - int offsetTimeMs = 700; + int offsetTimeMs = 1000; if (atts[2]) { CHECK(!strcmp("startOffsetMs", atts[2])); offsetTimeMs = atoi(atts[3]); diff --git a/media/libmedia/Visualizer.cpp b/media/libmedia/Visualizer.cpp index de0bf7d..8196e10 100644 --- a/media/libmedia/Visualizer.cpp +++ b/media/libmedia/Visualizer.cpp @@ -353,13 +353,4 @@ bool Visualizer::CaptureThread::threadLoop() return false; } -status_t Visualizer::CaptureThread::readyToRun() -{ - return NO_ERROR; -} - -void Visualizer::CaptureThread::onFirstRef() -{ -} - }; // namespace android |