Merge changes from topic 'device_version_cleanup' into oc-dev
* changes:
Camera: Cleanup 'Camera2Client' device dependend code
Camera: Remove RAW boost value override logic
Camera: Remove AE pre-capture trigger cancel override
Camera: Make device related code version agnostic
diff --git a/include/media/VolumeShaper.h b/include/media/VolumeShaper.h
index 4ddb8d3..1282124 100644
--- a/include/media/VolumeShaper.h
+++ b/include/media/VolumeShaper.h
@@ -528,6 +528,10 @@
mDelayXOffset = xOffset;
}
+ bool isStarted() const {
+ return mStartFrame >= 0;
+ }
+
std::pair<T /* volume */, bool /* active */> getVolume(
int64_t trackFrameCount, double trackSampleRate) {
if ((getFlags() & VolumeShaper::Operation::FLAG_DELAY) != 0) {
@@ -752,6 +756,8 @@
return it->getState();
}
+ // getVolume() is not const, as it updates internal state.
+ // Once called, any VolumeShapers not already started begin running.
std::pair<T /* volume */, bool /* active */> getVolume(int64_t trackFrameCount) {
AutoMutex _l(mLock);
mLastFrame = trackFrameCount;
@@ -768,6 +774,14 @@
return mLastVolume;
}
+ // Used by a client side VolumeHandler to ensure all the VolumeShapers
+ // indicate that they have been started. Upon a change in audioserver
+ // output sink, this information is used for restoration of the server side
+ // VolumeHandler.
+ void setStarted() {
+ (void)getVolume(mLastFrame); // getVolume() will start the individual VolumeShapers.
+ }
+
std::pair<T /* volume */, bool /* active */> getLastVolume() const {
AutoMutex _l(mLock);
return mLastVolume;
@@ -784,14 +798,12 @@
return ss.str();
}
- void forall(const std::function<VolumeShaper::Status (
- const sp<VolumeShaper::Configuration> &configuration,
- const sp<VolumeShaper::Operation> &operation)> &lambda) {
+ void forall(const std::function<VolumeShaper::Status (const VolumeShaper &)> &lambda) {
AutoMutex _l(mLock);
VS_LOG("forall: mVolumeShapers.size() %zu", mVolumeShapers.size());
for (const auto &shaper : mVolumeShapers) {
- VS_LOG("forall applying lambda");
- (void)lambda(shaper.mConfiguration, shaper.mOperation);
+ VolumeShaper::Status status = lambda(shaper);
+ VS_LOG("forall applying lambda on shaper (%p): %d", &shaper, (int)status);
}
}
diff --git a/media/libaaudio/examples/write_sine/src/write_sine.cpp b/media/libaaudio/examples/write_sine/src/write_sine.cpp
index 6525c0a..df55c3f 100644
--- a/media/libaaudio/examples/write_sine/src/write_sine.cpp
+++ b/media/libaaudio/examples/write_sine/src/write_sine.cpp
@@ -63,8 +63,8 @@
aaudio_result_t result = AAUDIO_OK;
- const int requestedSamplesPerFrame = 2;
- int actualSamplesPerFrame = 0;
+ const int requestedChannelCount = 2;
+ int actualChannelCount = 0;
const int requestedSampleRate = SAMPLE_RATE;
int actualSampleRate = 0;
aaudio_audio_format_t actualDataFormat = AAUDIO_FORMAT_UNSPECIFIED;
@@ -90,7 +90,7 @@
// in a buffer if we hang or crash.
setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
- printf("%s - Play a sine wave using AAudio, Z2\n", argv[0]);
+ printf("%s - Play a sine wave using AAudio\n", argv[0]);
// Use an AAudioStreamBuilder to contain requested parameters.
result = AAudio_createStreamBuilder(&aaudioBuilder);
@@ -100,7 +100,7 @@
// Request stream properties.
AAudioStreamBuilder_setSampleRate(aaudioBuilder, requestedSampleRate);
- AAudioStreamBuilder_setSamplesPerFrame(aaudioBuilder, requestedSamplesPerFrame);
+ AAudioStreamBuilder_setChannelCount(aaudioBuilder, requestedChannelCount);
AAudioStreamBuilder_setFormat(aaudioBuilder, REQUESTED_FORMAT);
AAudioStreamBuilder_setSharingMode(aaudioBuilder, REQUESTED_SHARING_MODE);
@@ -120,9 +120,9 @@
sineOsc1.setup(440.0, actualSampleRate);
sineOsc2.setup(660.0, actualSampleRate);
- actualSamplesPerFrame = AAudioStream_getSamplesPerFrame(aaudioStream);
- printf("SamplesPerFrame: requested = %d, actual = %d\n",
- requestedSamplesPerFrame, actualSamplesPerFrame);
+ actualChannelCount = AAudioStream_getChannelCount(aaudioStream);
+ printf("ChannelCount: requested = %d, actual = %d\n",
+ requestedChannelCount, actualChannelCount);
actualSharingMode = AAudioStream_getSharingMode(aaudioStream);
printf("SharingMode: requested = %s, actual = %s\n",
@@ -152,9 +152,9 @@
// Allocate a buffer for the audio data.
if (actualDataFormat == AAUDIO_FORMAT_PCM_FLOAT) {
- floatData = new float[framesPerWrite * actualSamplesPerFrame];
+ floatData = new float[framesPerWrite * actualChannelCount];
} else if (actualDataFormat == AAUDIO_FORMAT_PCM_I16) {
- shortData = new int16_t[framesPerWrite * actualSamplesPerFrame];
+ shortData = new int16_t[framesPerWrite * actualChannelCount];
} else {
printf("ERROR Unsupported data format!\n");
goto finish;
@@ -178,15 +178,15 @@
if (actualDataFormat == AAUDIO_FORMAT_PCM_FLOAT) {
// Render sine waves to left and right channels.
- sineOsc1.render(&floatData[0], actualSamplesPerFrame, framesPerWrite);
- if (actualSamplesPerFrame > 1) {
- sineOsc2.render(&floatData[1], actualSamplesPerFrame, framesPerWrite);
+ sineOsc1.render(&floatData[0], actualChannelCount, framesPerWrite);
+ if (actualChannelCount > 1) {
+ sineOsc2.render(&floatData[1], actualChannelCount, framesPerWrite);
}
} else if (actualDataFormat == AAUDIO_FORMAT_PCM_I16) {
// Render sine waves to left and right channels.
- sineOsc1.render(&shortData[0], actualSamplesPerFrame, framesPerWrite);
- if (actualSamplesPerFrame > 1) {
- sineOsc2.render(&shortData[1], actualSamplesPerFrame, framesPerWrite);
+ sineOsc1.render(&shortData[0], actualChannelCount, framesPerWrite);
+ if (actualChannelCount > 1) {
+ sineOsc2.render(&shortData[1], actualChannelCount, framesPerWrite);
}
}
diff --git a/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp b/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
index 8c1072d..a7e32bd 100644
--- a/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
+++ b/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
@@ -65,11 +65,11 @@
/**
* Only call this after open() has been called.
*/
- int32_t getSamplesPerFrame() {
+ int32_t getChannelCount() {
if (mStream == nullptr) {
return AAUDIO_ERROR_INVALID_STATE;
}
- return AAudioStream_getSamplesPerFrame(mStream);;
+ return AAudioStream_getChannelCount(mStream);;
}
/**
@@ -119,7 +119,7 @@
// Write zero data to fill up the buffer and prevent underruns.
aaudio_result_t prime() {
- int32_t samplesPerFrame = AAudioStream_getSamplesPerFrame(mStream);
+ int32_t samplesPerFrame = AAudioStream_getChannelCount(mStream);
const int numFrames = 32;
float zeros[numFrames * samplesPerFrame];
memset(zeros, 0, sizeof(zeros));
@@ -186,7 +186,7 @@
sineData->schedulerChecked = true;
}
- int32_t samplesPerFrame = AAudioStream_getSamplesPerFrame(stream);
+ int32_t samplesPerFrame = AAudioStream_getChannelCount(stream);
// This code only plays on the first one or two channels.
// TODO Support arbitrary number of channels.
switch (AAudioStream_getFormat(stream)) {
@@ -239,7 +239,7 @@
goto error;
}
printf("player.getFramesPerSecond() = %d\n", player.getFramesPerSecond());
- printf("player.getSamplesPerFrame() = %d\n", player.getSamplesPerFrame());
+ printf("player.getChannelCount() = %d\n", player.getChannelCount());
myData.sineOsc1.setup(440.0, 48000);
myData.sineOsc1.setSweep(300.0, 600.0, 5.0);
myData.sineOsc2.setup(660.0, 48000);
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index 4c1ea55..532c372 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -206,20 +206,28 @@
int32_t sampleRate);
/**
- * Request a number of samples per frame.
+ * Request a number of channels for the stream.
*
* The stream may be opened with a different value.
* So the application should query for the actual value after the stream is opened.
*
* The default, if you do not call this function, is AAUDIO_UNSPECIFIED.
*
- * Note, this quantity is sometimes referred to as "channel count".
+ * Note, this quantity is sometimes referred to as "samples per frame".
*
* @param builder reference provided by AAudio_createStreamBuilder()
- * @param samplesPerFrame Number of samples in one frame, ie. numChannels.
+ * @param channelCount Number of channels desired.
*/
+AAUDIO_API void AAudioStreamBuilder_setChannelCount(AAudioStreamBuilder* builder,
+ int32_t channelCount);
+
+/**
+ *
+ * @deprecated use AAudioStreamBuilder_setChannelCount()
+ */
+// TODO remove as soon as the NDK and OS are in sync, before RC1
AAUDIO_API void AAudioStreamBuilder_setSamplesPerFrame(AAudioStreamBuilder* builder,
- int32_t samplesPerFrame);
+ int32_t samplesPerFrame);
/**
* Request a sample data format, for example AAUDIO_FORMAT_PCM_I16.
@@ -677,8 +685,18 @@
AAUDIO_API int32_t AAudioStream_getSampleRate(AAudioStream* stream);
/**
+ * A stream has one or more channels of data.
+ * A frame will contain one sample for each channel.
+ *
+ * @param stream reference provided by AAudioStreamBuilder_openStream()
+ * @return actual number of channels
+ */
+AAUDIO_API int32_t AAudioStream_getChannelCount(AAudioStream* stream);
+
+/**
* The samplesPerFrame is also known as channelCount.
*
+ * @deprecated use AAudioStream_getChannelCount()
* @param stream reference provided by AAudioStreamBuilder_openStream()
* @return actual samples per frame
*/
diff --git a/media/libaaudio/libaaudio.map.txt b/media/libaaudio/libaaudio.map.txt
index 1024e1f..efd92ae 100644
--- a/media/libaaudio/libaaudio.map.txt
+++ b/media/libaaudio/libaaudio.map.txt
@@ -9,6 +9,7 @@
AAudioStreamBuilder_setFramesPerDataCallback;
AAudioStreamBuilder_setSampleRate;
AAudioStreamBuilder_setSamplesPerFrame;
+ AAudioStreamBuilder_setChannelCount;
AAudioStreamBuilder_setFormat;
AAudioStreamBuilder_setSharingMode;
AAudioStreamBuilder_setDirection;
@@ -32,6 +33,7 @@
AAudioStream_getXRunCount;
AAudioStream_getSampleRate;
AAudioStream_getSamplesPerFrame;
+ AAudioStream_getChannelCount;
AAudioStream_getDeviceId;
AAudioStream_getFormat;
AAudioStream_getSharingMode;
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 97726e6..462ecb3 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -128,8 +128,15 @@
streamBuilder->setSampleRate(sampleRate);
}
+AAUDIO_API void AAudioStreamBuilder_setChannelCount(AAudioStreamBuilder* builder,
+ int32_t channelCount)
+{
+ AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
+ streamBuilder->setSamplesPerFrame(channelCount);
+}
+
AAUDIO_API void AAudioStreamBuilder_setSamplesPerFrame(AAudioStreamBuilder* builder,
- int32_t samplesPerFrame)
+ int32_t samplesPerFrame)
{
AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
streamBuilder->setSamplesPerFrame(samplesPerFrame);
@@ -334,6 +341,12 @@
return audioStream->getSampleRate();
}
+AAUDIO_API int32_t AAudioStream_getChannelCount(AAudioStream* stream)
+{
+ AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
+ return audioStream->getSamplesPerFrame();
+}
+
AAUDIO_API int32_t AAudioStream_getSamplesPerFrame(AAudioStream* stream)
{
AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 3a0ce5e..4baf253 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -652,6 +652,9 @@
get_sched_policy(0, &mPreviousSchedulingGroup);
androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
}
+
+ // Start our local VolumeHandler for restoration purposes.
+ mVolumeHandler->setStarted();
} else {
ALOGE("start() status %d", status);
mState = previousState;
@@ -2254,17 +2257,20 @@
}
}
// restore volume handler
- mVolumeHandler->forall([this](const sp<VolumeShaper::Configuration> &configuration,
- const sp<VolumeShaper::Operation> &operation) -> VolumeShaper::Status {
- sp<VolumeShaper::Operation> operationToEnd = new VolumeShaper::Operation(*operation);
+ mVolumeHandler->forall([this](const VolumeShaper &shaper) -> VolumeShaper::Status {
+ sp<VolumeShaper::Operation> operationToEnd =
+ new VolumeShaper::Operation(shaper.mOperation);
// TODO: Ideally we would restore to the exact xOffset position
// as returned by getVolumeShaperState(), but we don't have that
// information when restoring at the client unless we periodically poll
// the server or create shared memory state.
//
- // For now, we simply advance to the end of the VolumeShaper effect.
- operationToEnd->setXOffset(1.f);
- return mAudioTrack->applyVolumeShaper(configuration, operationToEnd);
+ // For now, we simply advance to the end of the VolumeShaper effect
+ // if it has been started.
+ if (shaper.isStarted()) {
+ operationToEnd->setXOffset(1.f);
+ }
+ return mAudioTrack->applyVolumeShaper(shaper.mConfiguration, operationToEnd);
});
if (mState == STATE_ACTIVE) {
@@ -2334,19 +2340,36 @@
AutoMutex lock(mLock);
mVolumeHandler->setIdIfNecessary(configuration);
VolumeShaper::Status status = mAudioTrack->applyVolumeShaper(configuration, operation);
+
+ if (status == DEAD_OBJECT) {
+ if (restoreTrack_l("applyVolumeShaper") == OK) {
+ status = mAudioTrack->applyVolumeShaper(configuration, operation);
+ }
+ }
if (status >= 0) {
// save VolumeShaper for restore
mVolumeHandler->applyVolumeShaper(configuration, operation);
+ if (mState == STATE_ACTIVE || mState == STATE_STOPPING) {
+ mVolumeHandler->setStarted();
+ }
+ } else {
+ // warn only if not an expected restore failure.
+ ALOGW_IF(!((isOffloadedOrDirect_l() || mDoNotReconnect) && status == DEAD_OBJECT),
+ "applyVolumeShaper failed: %d", status);
}
return status;
}
sp<VolumeShaper::State> AudioTrack::getVolumeShaperState(int id)
{
- // TODO: To properly restore the AudioTrack
- // we will need to save the last state in AudioTrackShared.
AutoMutex lock(mLock);
- return mAudioTrack->getVolumeShaperState(id);
+ sp<VolumeShaper::State> state = mAudioTrack->getVolumeShaperState(id);
+ if (state.get() == nullptr && (mCblk->mFlags & CBLK_INVALID) != 0) {
+ if (restoreTrack_l("getVolumeShaperState") == OK) {
+ state = mAudioTrack->getVolumeShaperState(id);
+ }
+ }
+ return state;
}
status_t AudioTrack::getTimestamp(ExtendedTimestamp *timestamp)
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index a7d9f0f..05b726a 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -302,6 +302,12 @@
void AudioMixer::track_t::unprepareForDownmix() {
ALOGV("AudioMixer::unprepareForDownmix(%p)", this);
+ if (mPostDownmixReformatBufferProvider != nullptr) {
+ // release any buffers held by the mPostDownmixReformatBufferProvider
+ // before deallocating the downmixerBufferProvider.
+ mPostDownmixReformatBufferProvider->reset();
+ }
+
mDownmixRequiresFormat = AUDIO_FORMAT_INVALID;
if (downmixerBufferProvider != NULL) {
// this track had previously been configured with a downmixer, delete it
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index b082654..cba5cf5 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -2029,12 +2029,23 @@
ALOGV("setVolume");
t->setVolume(mLeftVolume, mRightVolume);
- // Dispatch any queued VolumeShapers when the track was not open.
- mVolumeHandler->forall([&t](const sp<VolumeShaper::Configuration> &configuration,
- const sp<VolumeShaper::Operation> &operation) -> VolumeShaper::Status {
- return t->applyVolumeShaper(configuration, operation);
+ // Restore VolumeShapers for the MediaPlayer in case the track was recreated
+ // due to an output sink error (e.g. offload to non-offload switch).
+ mVolumeHandler->forall([&t](const VolumeShaper &shaper) -> VolumeShaper::Status {
+ sp<VolumeShaper::Operation> operationToEnd =
+ new VolumeShaper::Operation(shaper.mOperation);
+ // TODO: Ideally we would restore to the exact xOffset position
+ // as returned by getVolumeShaperState(), but we don't have that
+ // information when restoring at the client unless we periodically poll
+ // the server or create shared memory state.
+ //
+ // For now, we simply advance to the end of the VolumeShaper effect
+ // if it has been started.
+ if (shaper.isStarted()) {
+ operationToEnd->setXOffset(1.f);
+ }
+ return t->applyVolumeShaper(shaper.mConfiguration, operationToEnd);
});
- mVolumeHandler->reset(); // After dispatching, clear VolumeShaper queue.
mSampleRateHz = sampleRate;
mFlags = flags;
@@ -2075,7 +2086,11 @@
if (mTrack != 0) {
mTrack->setVolume(mLeftVolume, mRightVolume);
mTrack->setAuxEffectSendLevel(mSendLevel);
- return mTrack->start();
+ status_t status = mTrack->start();
+ if (status == NO_ERROR) {
+ mVolumeHandler->setStarted();
+ }
+ return status;
}
return NO_INIT;
}
@@ -2279,13 +2294,20 @@
Mutex::Autolock lock(mLock);
ALOGV("AudioOutput::applyVolumeShaper");
- // We take ownership of the VolumeShaper if set before the track is created.
mVolumeHandler->setIdIfNecessary(configuration);
+
+ VolumeShaper::Status status;
if (mTrack != 0) {
- return mTrack->applyVolumeShaper(configuration, operation);
+ status = mTrack->applyVolumeShaper(configuration, operation);
+ if (status >= 0) {
+ (void)mVolumeHandler->applyVolumeShaper(configuration, operation);
+ // TODO: start on exact AudioTrack state (STATE_ACTIVE || STATE_STOPPING)
+ mVolumeHandler->setStarted();
+ }
} else {
- return mVolumeHandler->applyVolumeShaper(configuration, operation);
+ status = mVolumeHandler->applyVolumeShaper(configuration, operation);
}
+ return status;
}
sp<VolumeShaper::State> MediaPlayerService::AudioOutput::getVolumeShaperState(int id)
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index ba45b98..fb1f42b 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -1954,12 +1954,12 @@
size_t psshsize;
if (!mFileMeta->findData(kKeyPssh, &type, &pssh, &psshsize)) {
- ALOGE("checkDrmInfo: No PSSH");
+ ALOGV("checkDrmInfo: No PSSH");
return OK; // source without DRM info
}
Parcel parcel;
- NuPlayerDrm::retrieveDrmInfo(pssh, psshsize, mMimes, &parcel);
+ NuPlayerDrm::retrieveDrmInfo(pssh, psshsize, &parcel);
ALOGV("checkDrmInfo: MEDIA_DRM_INFO PSSH size: %d Parcel size: %d objects#: %d",
(int)psshsize, (int)parcel.dataSize(), (int)parcel.objectsCount());
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
index ce6cedc..b7c9db7 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
@@ -205,26 +205,8 @@
}
// Parcel has only private copy constructor so passing it in rather than returning
-void NuPlayerDrm::retrieveDrmInfo(const void *pssh, size_t psshsize,
- const Vector<String8> &mimes_in, Parcel *parcel)
+void NuPlayerDrm::retrieveDrmInfo(const void *pssh, size_t psshsize, Parcel *parcel)
{
- // 0) Make mimes a vector of unique items while keeping the original order; video first
- Vector<String8> mimes;
- for (size_t j = 0; j < mimes_in.size(); j++) {
- String8 mime = mimes_in[j];
- bool exists = false;
- for (size_t i = 0; i < mimes.size() && !exists; i++) {
- if (mimes[i] == mime) {
- exists = true;
- }
- } // for i
-
- if (!exists) {
- mimes.add(mime);
- }
- } // for j
-
-
// 1) PSSH bytes
parcel->writeUint32(psshsize);
parcel->writeByteArray(psshsize, (const uint8_t*)pssh);
@@ -242,18 +224,6 @@
ALOGV("retrieveDrmInfo: MEDIA_DRM_INFO supportedScheme[%zu] %s", i,
uuid.toHexString().string());
}
-
- // TODO: remove mimes after it's removed from Java DrmInfo
- // 3) mimes
- parcel->writeUint32(mimes.size());
- for (size_t i = 0; i < mimes.size(); i++) {
- // writing as String16 so the Java framework side can unpack it to Java String
- String16 mime(mimes[i]);
- parcel->writeString16(mime);
-
- ALOGV("retrieveDrmInfo: MEDIA_DRM_INFO MIME[%zu] %s",
- i, mimes[i].string());
- }
}
////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.h b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.h
index 6704bd1..6b8a2d9 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.h
@@ -84,8 +84,7 @@
static sp<ICrypto> createCryptoAndPlugin(const uint8_t uuid[16],
const Vector<uint8_t> &drmSessionId, status_t &status);
// Parcel has only private copy constructor so passing it in rather than returning
- static void retrieveDrmInfo(const void *pssh, size_t psshsize,
- const Vector<String8> &mimes_in, Parcel *parcel);
+ static void retrieveDrmInfo(const void *pssh, size_t psshsize, Parcel *parcel);
////////////////////////////////////////////////////////////////////////////////////////////
/// Helpers for NuPlayerDecoder
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 8b91541..2877ba2 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -251,6 +251,7 @@
virtual PortMode getPortMode(OMX_U32 portIndex);
+ virtual void stateExited();
virtual bool onMessageReceived(const sp<AMessage> &msg);
virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
@@ -553,6 +554,7 @@
mTunneled(false),
mDescribeColorAspectsIndex((OMX_INDEXTYPE)0),
mDescribeHDRStaticInfoIndex((OMX_INDEXTYPE)0),
+ mStateGeneration(0),
mVendorExtensionsStatus(kExtensionsUnchecked) {
mUninitializedState = new UninitializedState(this);
mLoadedState = new LoadedState(this);
@@ -5322,6 +5324,10 @@
return KEEP_BUFFERS;
}
+void ACodec::BaseState::stateExited() {
+ ++mCodec->mStateGeneration;
+}
+
bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatInputBufferFilled:
@@ -5398,6 +5404,12 @@
break;
}
+ case ACodec::kWhatForceStateTransition:
+ {
+ ALOGV("Already transitioned --- ignore");
+ break;
+ }
+
default:
return false;
}
@@ -6988,7 +7000,6 @@
void ACodec::ExecutingState::stateEntered() {
ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
-
mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC));
mCodec->processDeferredMessages();
}
@@ -7614,6 +7625,30 @@
mCallback->onSignaledInputEOS(err);
}
+void ACodec::forceStateTransition(int generation) {
+ if (generation != mStateGeneration) {
+ ALOGV("Ignoring stale force state transition message: #%d (now #%d)",
+ generation, mStateGeneration);
+ return;
+ }
+ ALOGE("State machine stuck");
+ // Error must have already been signalled to the client.
+
+ // Deferred messages will be handled at LoadedState at the end of the
+ // transition.
+ mShutdownInProgress = true;
+ // No shutdown complete callback at the end of the transition.
+ mExplicitShutdown = false;
+ mKeepComponentAllocated = true;
+
+ status_t err = mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateIdle);
+ if (err != OK) {
+ // TODO: do some recovery here.
+ } else {
+ changeState(mExecutingToIdleState);
+ }
+}
+
bool ACodec::ExecutingState::onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) {
mCodec->onFrameRendered(mediaTimeUs, systemNano);
return true;
@@ -7680,7 +7715,14 @@
switch (msg->what()) {
case kWhatFlush:
- case kWhatShutdown:
+ case kWhatShutdown: {
+ if (mCodec->mFatalError) {
+ sp<AMessage> msg = new AMessage(ACodec::kWhatForceStateTransition, mCodec);
+ msg->setInt32("generation", mCodec->mStateGeneration);
+ msg->post(3000000);
+ }
+ // fall-through
+ }
case kWhatResume:
case kWhatSetParameters:
{
@@ -7693,6 +7735,16 @@
break;
}
+ case kWhatForceStateTransition:
+ {
+ int32_t generation = 0;
+ CHECK(msg->findInt32("generation", &generation));
+ mCodec->forceStateTransition(generation);
+
+ handled = true;
+ break;
+ }
+
default:
handled = BaseState::onMessageReceived(msg);
break;
@@ -7752,15 +7804,7 @@
if (err != OK) {
mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
-
- // This is technically not correct, but appears to be
- // the only way to free the component instance.
- // Controlled transitioning from excecuting->idle
- // and idle->loaded seem impossible probably because
- // the output port never finishes re-enabling.
- mCodec->mShutdownInProgress = true;
- mCodec->mKeepComponentAllocated = false;
- mCodec->changeState(mCodec->mLoadedState);
+ ALOGE("Error occurred while disabling the output port");
}
return true;
@@ -7785,7 +7829,7 @@
}
default:
- return false;
+ return BaseState::onOMXEvent(event, data1, data2);
}
}
@@ -7987,6 +8031,11 @@
case kWhatShutdown:
{
mCodec->deferMessage(msg);
+ if (mCodec->mFatalError) {
+ sp<AMessage> msg = new AMessage(ACodec::kWhatForceStateTransition, mCodec);
+ msg->setInt32("generation", mCodec->mStateGeneration);
+ msg->post(3000000);
+ }
break;
}
@@ -7997,6 +8046,16 @@
break;
}
+ case kWhatForceStateTransition:
+ {
+ int32_t generation = 0;
+ CHECK(msg->findInt32("generation", &generation));
+ mCodec->forceStateTransition(generation);
+
+ handled = true;
+ break;
+ }
+
default:
handled = BaseState::onMessageReceived(msg);
break;
diff --git a/media/libstagefright/include/ACodec.h b/media/libstagefright/include/ACodec.h
index 06ee0e8..22b8657 100644
--- a/media/libstagefright/include/ACodec.h
+++ b/media/libstagefright/include/ACodec.h
@@ -150,6 +150,7 @@
kWhatSubmitOutputMetadataBufferIfEOS = 'subm',
kWhatOMXDied = 'OMXd',
kWhatReleaseCodecInstance = 'relC',
+ kWhatForceStateTransition = 'fstt',
};
enum {
@@ -305,6 +306,8 @@
std::shared_ptr<ACodecBufferChannel> mBufferChannel;
+ int32_t mStateGeneration;
+
enum {
kExtensionsUnchecked,
kExtensionsNone,
@@ -569,6 +572,9 @@
// Send EOS on input stream.
void onSignalEndOfInputStream();
+ // Force EXEC->IDLE->LOADED shutdown sequence if not stale.
+ void forceStateTransition(int generation);
+
DISALLOW_EVIL_CONSTRUCTORS(ACodec);
};
diff --git a/media/libstagefright/omx/1.0/OmxStore.cpp b/media/libstagefright/omx/1.0/OmxStore.cpp
new file mode 100644
index 0000000..0e37af9
--- /dev/null
+++ b/media/libstagefright/omx/1.0/OmxStore.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2017, 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 <ios>
+#include <list>
+
+#include <android-base/logging.h>
+
+#include "Conversion.h"
+#include "OmxStore.h"
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+namespace implementation {
+
+OmxStore::OmxStore() {
+}
+
+OmxStore::~OmxStore() {
+}
+
+Return<void> OmxStore::listServiceAttributes(listServiceAttributes_cb _hidl_cb) {
+ _hidl_cb(toStatus(NO_ERROR), hidl_vec<ServiceAttribute>());
+ return Void();
+}
+
+Return<void> OmxStore::getNodePrefix(getNodePrefix_cb _hidl_cb) {
+ _hidl_cb(hidl_string());
+ return Void();
+}
+
+Return<void> OmxStore::listRoles(listRoles_cb _hidl_cb) {
+ _hidl_cb(hidl_vec<RoleInfo>());
+ return Void();
+}
+
+Return<sp<IOmx>> OmxStore::getOmx(hidl_string const& omxName) {
+ return IOmx::tryGetService(omxName);
+}
+
+// Methods from ::android::hidl::base::V1_0::IBase follow.
+
+IOmxStore* HIDL_FETCH_IOmxStore(const char* /* name */) {
+ return new OmxStore();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace omx
+} // namespace media
+} // namespace hardware
+} // namespace android
diff --git a/media/libstagefright/omx/1.0/OmxStore.h b/media/libstagefright/omx/1.0/OmxStore.h
new file mode 100644
index 0000000..f377f5a
--- /dev/null
+++ b/media/libstagefright/omx/1.0/OmxStore.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2017, 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_HARDWARE_MEDIA_OMX_V1_0_OMXSTORE_H
+#define ANDROID_HARDWARE_MEDIA_OMX_V1_0_OMXSTORE_H
+
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <android/hardware/media/omx/1.0/IOmxStore.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace omx {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::media::omx::V1_0::IOmxStore;
+using ::android::hardware::media::omx::V1_0::IOmx;
+using ::android::hardware::media::omx::V1_0::Status;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::wp;
+
+struct OmxStore : public IOmxStore {
+ OmxStore();
+ virtual ~OmxStore();
+
+ // Methods from IOmx
+ Return<void> listServiceAttributes(listServiceAttributes_cb) override;
+ Return<void> getNodePrefix(getNodePrefix_cb) override;
+ Return<void> listRoles(listRoles_cb) override;
+ Return<sp<IOmx>> getOmx(hidl_string const&) override;
+};
+
+extern "C" IOmxStore* HIDL_FETCH_IOmxStore(const char* name);
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace omx
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_MEDIA_OMX_V1_0_OMXSTORE_H
diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk
index 90333ef..29e2ccc 100644
--- a/media/libstagefright/omx/Android.mk
+++ b/media/libstagefright/omx/Android.mk
@@ -15,6 +15,7 @@
SoftVideoDecoderOMXComponent.cpp \
SoftVideoEncoderOMXComponent.cpp \
1.0/Omx.cpp \
+ 1.0/OmxStore.cpp \
1.0/WGraphicBufferProducer.cpp \
1.0/WProducerListener.cpp \
1.0/WGraphicBufferSource.cpp \
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 0521460..103a3e9 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -766,7 +766,6 @@
status_t GraphicBufferSource::submitBuffer_l(const VideoBuffer &item) {
CHECK(!mFreeCodecBuffers.empty());
IOMX::buffer_id codecBufferId = *mFreeCodecBuffers.begin();
- mFreeCodecBuffers.erase(mFreeCodecBuffers.begin());
ALOGV("submitBuffer_l [slot=%d, bufferId=%d]", item.mBuffer->getSlot(), codecBufferId);
@@ -797,6 +796,8 @@
return err;
}
+ mFreeCodecBuffers.erase(mFreeCodecBuffers.begin());
+
ssize_t cbix = mSubmittedCodecBuffers.add(codecBufferId, buffer);
ALOGV("emptyGraphicBuffer succeeded, bufferId=%u@%zd bufhandle=%p",
codecBufferId, cbix, graphicBuffer->handle);
@@ -815,7 +816,6 @@
return;
}
IOMX::buffer_id codecBufferId = *mFreeCodecBuffers.begin();
- mFreeCodecBuffers.erase(mFreeCodecBuffers.begin());
// We reject any additional incoming graphic buffers. There is no acquired buffer used for EOS
status_t err = mOMXNode->emptyBuffer(
@@ -823,6 +823,7 @@
if (err != OK) {
ALOGW("emptyDirectBuffer EOS failed: 0x%x", err);
} else {
+ mFreeCodecBuffers.erase(mFreeCodecBuffers.begin());
ssize_t cbix = mSubmittedCodecBuffers.add(codecBufferId, nullptr);
ALOGV("submitEndOfInputStream_l: buffer submitted, bufferId=%u@%zd", codecBufferId, cbix);
mEndOfStreamSent = true;
@@ -897,7 +898,7 @@
++mNumAvailableUnacquiredBuffers;
// For BufferQueue we cannot acquire a buffer if we cannot immediately feed it to the codec
- // OR we are discarding this buffer (acquiring and immediately releasing it), which makes
+ // UNLESS we are discarding this buffer (acquiring and immediately releasing it), which makes
// this an ugly logic.
// NOTE: We could also rely on our debug counter but that is meant only as a debug counter.
if (!areWeDiscardingAvailableBuffers_l() && mFreeCodecBuffers.empty()) {
@@ -906,6 +907,7 @@
ALOGV("onFrameAvailable: cannot acquire buffer right now, do it later");
++mRepeatLastFrameGeneration; // cancel any pending frame repeat
+ return;
}
VideoBuffer buffer;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 3665875..8d018d1 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -8296,22 +8296,24 @@
mEffectChains[0]->setVolume_l(&vol, &vol);
volume = (float)vol / (1 << 24);
}
-
- mOutput->stream->setVolume(volume, volume);
-
- sp<MmapStreamCallback> callback = mCallback.promote();
- if (callback != 0) {
- int channelCount;
- if (isOutput()) {
- channelCount = audio_channel_count_from_out_mask(mChannelMask);
+ // Try to use HW volume control and fall back to SW control if not implemented
+ if (mOutput->stream->setVolume(volume, volume) != NO_ERROR) {
+ sp<MmapStreamCallback> callback = mCallback.promote();
+ if (callback != 0) {
+ int channelCount;
+ if (isOutput()) {
+ channelCount = audio_channel_count_from_out_mask(mChannelMask);
+ } else {
+ channelCount = audio_channel_count_from_in_mask(mChannelMask);
+ }
+ Vector<float> values;
+ for (int i = 0; i < channelCount; i++) {
+ values.add(volume);
+ }
+ callback->onVolumeChanged(mChannelMask, values);
} else {
- channelCount = audio_channel_count_from_in_mask(mChannelMask);
+ ALOGW("Could not set MMAP stream volume: no volume callback!");
}
- Vector<float> values;
- for (int i = 0; i < channelCount; i++) {
- values.add(volume);
- }
- callback->onVolumeChanged(mChannelMask, values);
}
}
}
diff --git a/services/mediacodec/main_codecservice.cpp b/services/mediacodec/main_codecservice.cpp
index c4e4cff..c59944a 100644
--- a/services/mediacodec/main_codecservice.cpp
+++ b/services/mediacodec/main_codecservice.cpp
@@ -31,9 +31,9 @@
#include "MediaCodecService.h"
#include "minijail.h"
-#include <android/hardware/media/omx/1.0/IOmx.h>
#include <hidl/HidlTransportSupport.h>
#include <omx/1.0/Omx.h>
+#include <omx/1.0/OmxStore.h>
using namespace android;
@@ -61,17 +61,23 @@
if (treble) {
using namespace ::android::hardware::media::omx::V1_0;
+ sp<IOmxStore> omxStore = new implementation::OmxStore();
+ if (omxStore == nullptr) {
+ LOG(ERROR) << "Cannot create IOmxStore HAL service.";
+ } else if (omxStore->registerAsService() != OK) {
+ LOG(ERROR) << "Cannot register IOmxStore HAL service.";
+ }
sp<IOmx> omx = new implementation::Omx();
if (omx == nullptr) {
- LOG(ERROR) << "Cannot create a Treble IOmx service.";
+ LOG(ERROR) << "Cannot create IOmx HAL service.";
} else if (omx->registerAsService() != OK) {
- LOG(ERROR) << "Cannot register a Treble IOmx service.";
+ LOG(ERROR) << "Cannot register IOmx HAL service.";
} else {
- LOG(INFO) << "Treble IOmx service created.";
+ LOG(INFO) << "Treble OMX service created.";
}
} else {
MediaCodecService::instantiate();
- LOG(INFO) << "Non-Treble IOMX service created.";
+ LOG(INFO) << "Non-Treble OMX service created.";
}
ProcessState::self()->startThreadPool();