diff options
-rw-r--r-- | include/media/IAudioTrack.h | 3 | ||||
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 3 | ||||
-rw-r--r-- | media/libmedia/IAudioTrack.cpp | 12 | ||||
-rw-r--r-- | media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp | 34 | ||||
-rw-r--r-- | media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h | 5 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.h | 1 | ||||
-rw-r--r-- | services/audioflinger/Effects.cpp | 22 | ||||
-rw-r--r-- | services/audioflinger/PlaybackTracks.h | 1 | ||||
-rw-r--r-- | services/audioflinger/Threads.cpp | 11 | ||||
-rw-r--r-- | services/audioflinger/Tracks.cpp | 16 | ||||
-rw-r--r-- | services/camera/libcameraservice/api1/client2/Parameters.cpp | 40 | ||||
-rw-r--r-- | services/camera/libcameraservice/api1/client2/Parameters.h | 4 |
12 files changed, 142 insertions, 10 deletions
diff --git a/include/media/IAudioTrack.h b/include/media/IAudioTrack.h index afac4ae..5c8a484 100644 --- a/include/media/IAudioTrack.h +++ b/include/media/IAudioTrack.h @@ -90,6 +90,9 @@ public: /* Return NO_ERROR if timestamp is valid */ virtual status_t getTimestamp(AudioTimestamp& timestamp) = 0; + + /* Signal the playback thread for a change in control block */ + virtual void signal() = 0; }; // ---------------------------------------------------------------------------- diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 754a4e3..37d50cf 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -534,6 +534,9 @@ status_t AudioTrack::setVolume(float left, float right) mProxy->setVolumeLR((uint32_t(uint16_t(right * 0x1000)) << 16) | uint16_t(left * 0x1000)); + if (isOffloaded()) { + mAudioTrack->signal(); + } return NO_ERROR; } diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp index f0d75ba..3cd9cfd 100644 --- a/media/libmedia/IAudioTrack.cpp +++ b/media/libmedia/IAudioTrack.cpp @@ -41,6 +41,7 @@ enum { SET_MEDIA_TIME_TRANSFORM, SET_PARAMETERS, GET_TIMESTAMP, + SIGNAL, }; class BpAudioTrack : public BpInterface<IAudioTrack> @@ -182,6 +183,12 @@ public: } return status; } + + virtual void signal() { + Parcel data, reply; + data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); + remote()->transact(SIGNAL, data, &reply); + } }; IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack"); @@ -269,6 +276,11 @@ status_t BnAudioTrack::onTransact( } return NO_ERROR; } break; + case SIGNAL: { + CHECK_INTERFACE(IAudioTrack, data, reply); + signal(); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp index 5f2b5c8..8375cac 100644 --- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp +++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp @@ -141,6 +141,7 @@ SoftVPXEncoder::SoftVPXEncoder(const char *name, mWidth(176), mHeight(144), mBitrate(192000), // in bps + mBitrateUpdated(false), mBitrateControlMode(VPX_VBR), // variable bitrate mFrameDurationUs(33333), // Defaults to 30 fps mDCTPartitions(0), @@ -536,6 +537,22 @@ OMX_ERRORTYPE SoftVPXEncoder::setConfig( return OMX_ErrorNone; } + case OMX_IndexConfigVideoBitrate: + { + OMX_VIDEO_CONFIG_BITRATETYPE *params = + (OMX_VIDEO_CONFIG_BITRATETYPE *)_params; + + if (params->nPortIndex != kOutputPortIndex) { + return OMX_ErrorBadPortIndex; + } + + if (mBitrate != params->nEncodeBitrate) { + mBitrate = params->nEncodeBitrate; + mBitrateUpdated = true; + } + return OMX_ErrorNone; + } + default: return SimpleSoftOMXComponent::setConfig(index, _params); } @@ -779,6 +796,21 @@ void SoftVPXEncoder::onQueueFilled(OMX_U32 portIndex) { mKeyFrameRequested = false; } + if (mBitrateUpdated) { + mCodecConfiguration->rc_target_bitrate = mBitrate/1000; + vpx_codec_err_t res = vpx_codec_enc_config_set(mCodecContext, + mCodecConfiguration); + if (res != VPX_CODEC_OK) { + ALOGE("vp8 encoder failed to update bitrate: %s", + vpx_codec_err_to_string(res)); + notify(OMX_EventError, + OMX_ErrorUndefined, + 0, // Extra notification data + NULL); // Notification data pointer + } + mBitrateUpdated = false; + } + codec_return = vpx_codec_encode( mCodecContext, &raw_frame, @@ -803,6 +835,8 @@ void SoftVPXEncoder::onQueueFilled(OMX_U32 portIndex) { if (encoded_packet->kind == VPX_CODEC_CX_FRAME_PKT) { outputBufferHeader->nTimeStamp = encoded_packet->data.frame.pts; outputBufferHeader->nFlags = 0; + if (encoded_packet->data.frame.flags & VPX_FRAME_IS_KEY) + outputBufferHeader->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; outputBufferHeader->nOffset = 0; outputBufferHeader->nFilledLen = encoded_packet->data.frame.sz; memcpy(outputBufferHeader->pBuffer, diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h index 4ee5e51..076830f 100644 --- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h +++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h @@ -128,7 +128,10 @@ private: int32_t mHeight; // Target bitrate set for the encoder, in bits per second. - int32_t mBitrate; + uint32_t mBitrate; + + // If a request for a change it bitrate has been received. + bool mBitrateUpdated; // Bitrate control mode, either constant or variable vpx_rc_mode mBitrateControlMode; diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index b41d480..2aeb263 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -412,6 +412,7 @@ private: int target); virtual status_t setParameters(const String8& keyValuePairs); virtual status_t getTimestamp(AudioTimestamp& timestamp); + virtual void signal(); // signal playback thread for a change in control block virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp index 6e0354d..a8a5169 100644 --- a/services/audioflinger/Effects.cpp +++ b/services/audioflinger/Effects.cpp @@ -972,13 +972,20 @@ status_t AudioFlinger::EffectHandle::enable() } mEnabled = false; } else { - if (thread != 0 && !mEffect->isOffloadable()) { - if ((thread->type() == ThreadBase::OFFLOAD)) { + if (thread != 0) { + if (thread->type() == ThreadBase::OFFLOAD) { PlaybackThread *t = (PlaybackThread *)thread.get(); - t->invalidateTracks(AUDIO_STREAM_MUSIC); + Mutex::Autolock _l(t->mLock); + t->broadcast_l(); } - if (mEffect->sessionId() == AUDIO_SESSION_OUTPUT_MIX) { - thread->mAudioFlinger->onNonOffloadableGlobalEffectEnable(); + if (!mEffect->isOffloadable()) { + if (thread->type() == ThreadBase::OFFLOAD) { + PlaybackThread *t = (PlaybackThread *)thread.get(); + t->invalidateTracks(AUDIO_STREAM_MUSIC); + } + if (mEffect->sessionId() == AUDIO_SESSION_OUTPUT_MIX) { + thread->mAudioFlinger->onNonOffloadableGlobalEffectEnable(); + } } } } @@ -1009,6 +1016,11 @@ status_t AudioFlinger::EffectHandle::disable() sp<ThreadBase> thread = mEffect->thread().promote(); if (thread != 0) { thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId()); + if (thread->type() == ThreadBase::OFFLOAD) { + PlaybackThread *t = (PlaybackThread *)thread.get(); + Mutex::Autolock _l(t->mLock); + t->broadcast_l(); + } } return status; diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h index f7ad6b1..a2e2511 100644 --- a/services/audioflinger/PlaybackTracks.h +++ b/services/audioflinger/PlaybackTracks.h @@ -60,6 +60,7 @@ public: int16_t *mainBuffer() const { return mMainBuffer; } int auxEffectId() const { return mAuxEffectId; } virtual status_t getTimestamp(AudioTimestamp& timestamp); + void signal(); // implement FastMixerState::VolumeProvider interface virtual uint32_t getVolumeLR(); diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 2d9d485..187adf3 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -2238,12 +2238,21 @@ bool AudioFlinger::PlaybackThread::threadLoop() } // only process effects if we're going to write - if (sleepTime == 0) { + if (sleepTime == 0 && mType != OFFLOAD) { for (size_t i = 0; i < effectChains.size(); i ++) { effectChains[i]->process_l(); } } } + // Process effect chains for offloaded thread even if no audio + // was read from audio track: process only updates effect state + // and thus does have to be synchronized with audio writes but may have + // to be called while waiting for async write callback + if (mType == OFFLOAD) { + for (size_t i = 0; i < effectChains.size(); i ++) { + effectChains[i]->process_l(); + } + } // enable changes in effect chain unlockEffectChains(effectChains); diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index d8d325d..9c6e724 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -288,6 +288,12 @@ status_t AudioFlinger::TrackHandle::getTimestamp(AudioTimestamp& timestamp) return mTrack->getTimestamp(timestamp); } + +void AudioFlinger::TrackHandle::signal() +{ + return mTrack->signal(); +} + status_t AudioFlinger::TrackHandle::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { @@ -926,6 +932,16 @@ void AudioFlinger::PlaybackThread::Track::invalidate() mIsInvalid = true; } +void AudioFlinger::PlaybackThread::Track::signal() +{ + sp<ThreadBase> thread = mThread.promote(); + if (thread != 0) { + PlaybackThread *t = (PlaybackThread *)thread.get(); + Mutex::Autolock _l(t->mLock); + t->broadcast_l(); + } +} + // ---------------------------------------------------------------------------- sp<AudioFlinger::PlaybackThread::TimedTrack> diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp index a6c1083..8e197a9 100644 --- a/services/camera/libcameraservice/api1/client2/Parameters.cpp +++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp @@ -250,9 +250,17 @@ status_t Parameters::initialize(const CameraMetadata *info) { staticInfo(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, 4); if (!availableJpegThumbnailSizes.count) return NO_INIT; - // TODO: Pick default thumbnail size sensibly - jpegThumbSize[0] = availableJpegThumbnailSizes.data.i32[0]; - jpegThumbSize[1] = availableJpegThumbnailSizes.data.i32[1]; + // Pick the largest thumbnail size that matches still image aspect ratio. + ALOG_ASSERT(pictureWidth > 0 && pictureHeight > 0, + "Invalid picture size, %d x %d", pictureWidth, pictureHeight); + float picAspectRatio = static_cast<float>(pictureWidth) / pictureHeight; + Size thumbnailSize = + getMaxSizeForRatio( + picAspectRatio, + &availableJpegThumbnailSizes.data.i32[0], + availableJpegThumbnailSizes.count); + jpegThumbSize[0] = thumbnailSize.width; + jpegThumbSize[1] = thumbnailSize.height; params.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, jpegThumbSize[0]); @@ -2525,6 +2533,32 @@ status_t Parameters::getFilteredPreviewSizes(Size limit, Vector<Size> *sizes) { return OK; } +Parameters::Size Parameters::getMaxSizeForRatio( + float ratio, const int32_t* sizeArray, size_t count) { + ALOG_ASSERT(sizeArray != NULL, "size array shouldn't be NULL"); + ALOG_ASSERT(count >= 2 && count % 2 == 0, "count must be a positive even number"); + + Size maxSize = {0, 0}; + for (size_t i = 0; i < count; i += 2) { + if (sizeArray[i] > 0 && sizeArray[i+1] > 0) { + float curRatio = static_cast<float>(sizeArray[i]) / sizeArray[i+1]; + if (fabs(curRatio - ratio) < ASPECT_RATIO_TOLERANCE && maxSize.width < sizeArray[i]) { + maxSize.width = sizeArray[i]; + maxSize.height = sizeArray[i+1]; + } + } + } + + if (maxSize.width == 0 || maxSize.height == 0) { + maxSize.width = sizeArray[0]; + maxSize.height = sizeArray[1]; + ALOGW("Unable to find the size to match the given aspect ratio %f." + "Fall back to %d x %d", ratio, maxSize.width, maxSize.height); + } + + return maxSize; +} + Parameters::CropRegion Parameters::calculateCropRegion( Parameters::CropRegion::Outputs outputs) const { diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h index 0505b0e..2e78c73 100644 --- a/services/camera/libcameraservice/api1/client2/Parameters.h +++ b/services/camera/libcameraservice/api1/client2/Parameters.h @@ -168,6 +168,8 @@ struct Parameters { // Max preview size allowed static const unsigned int MAX_PREVIEW_WIDTH = 1920; static const unsigned int MAX_PREVIEW_HEIGHT = 1080; + // Aspect ratio tolerance + static const float ASPECT_RATIO_TOLERANCE = 0.001; // Full static camera info, object owned by someone else, such as // Camera2Device. @@ -331,6 +333,8 @@ private: Vector<Size> availablePreviewSizes; // Get size list (that are no larger than limit) from static metadata. status_t getFilteredPreviewSizes(Size limit, Vector<Size> *sizes); + // Get max size (from the size array) that matches the given aspect ratio. + Size getMaxSizeForRatio(float ratio, const int32_t* sizeArray, size_t count); }; // This class encapsulates the Parameters class so that it can only be accessed |