Merge "DNG/TIFF support: Add NOTICE" into nyc-dev
diff --git a/include/media/AudioPolicy.h b/include/media/AudioPolicy.h
index c769a62..8528c7a 100644
--- a/include/media/AudioPolicy.h
+++ b/include/media/AudioPolicy.h
@@ -51,6 +51,7 @@
#define MIX_ROUTE_FLAG_RENDER 0x1
#define MIX_ROUTE_FLAG_LOOP_BACK (0x1 << 1)
+#define MIX_ROUTE_FLAG_ALL (MIX_ROUTE_FLAG_RENDER | MIX_ROUTE_FLAG_LOOP_BACK)
#define MAX_MIXES_PER_POLICY 10
#define MAX_CRITERIA_PER_MIX 20
@@ -81,7 +82,7 @@
AudioMix(Vector<AudioMixMatchCriterion> criteria, uint32_t mixType, audio_config_t format,
uint32_t routeFlags, String8 registrationId, uint32_t flags) :
mCriteria(criteria), mMixType(mixType), mFormat(format),
- mRouteFlags(routeFlags), mRegistrationId(registrationId), mCbFlags(flags){}
+ mRouteFlags(routeFlags), mDeviceAddress(registrationId), mCbFlags(flags){}
status_t readFromParcel(Parcel *parcel);
status_t writeToParcel(Parcel *parcel) const;
@@ -90,7 +91,8 @@
uint32_t mMixType;
audio_config_t mFormat;
uint32_t mRouteFlags;
- String8 mRegistrationId;
+ audio_devices_t mDeviceType;
+ String8 mDeviceAddress;
uint32_t mCbFlags; // flags indicating which callbacks to use, see kCbFlag*
};
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 69dc062..4de55a2 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -836,6 +836,8 @@
// check sample rate and speed is compatible with AudioTrack
bool isSampleRateSpeedAllowed_l(uint32_t sampleRate, float speed) const;
+ void restartIfDisabled();
+
// Next 4 fields may be changed if IAudioTrack is re-created, but always != 0
sp<IAudioTrack> mAudioTrack;
sp<IMemory> mCblkMemory;
diff --git a/include/media/stagefright/foundation/ALookup.h b/include/media/stagefright/foundation/ALookup.h
index d8af407..5a68806 100644
--- a/include/media/stagefright/foundation/ALookup.h
+++ b/include/media/stagefright/foundation/ALookup.h
@@ -27,14 +27,14 @@
struct ALookup {
ALookup(std::initializer_list<std::pair<T, U>> list);
- bool lookup(const T& from, U *to);
- bool rlookup(const U& from, T *to);
+ bool lookup(const T& from, U *to) const;
+ bool rlookup(const U& from, T *to) const;
template<typename V, typename = typename std::enable_if<!std::is_same<T, V>::value>::type>
- inline bool map(const T& from, V *to) { return lookup(from, to); }
+ inline bool map(const T& from, V *to) const { return lookup(from, to); }
template<typename V, typename = typename std::enable_if<!std::is_same<T, V>::value>::type>
- inline bool map(const V& from, T *to) { return rlookup(from, to); }
+ inline bool map(const V& from, T *to) const { return rlookup(from, to); }
private:
std::vector<std::pair<T, U>> mTable;
@@ -46,7 +46,7 @@
}
template<typename T, typename U>
-bool ALookup<T, U>::lookup(const T& from, U *to) {
+bool ALookup<T, U>::lookup(const T& from, U *to) const {
for (auto elem : mTable) {
if (elem.first == from) {
*to = elem.second;
@@ -57,7 +57,7 @@
}
template<typename T, typename U>
-bool ALookup<T, U>::rlookup(const U& from, T *to) {
+bool ALookup<T, U>::rlookup(const U& from, T *to) const {
for (auto elem : mTable) {
if (elem.second == from) {
*to = elem.first;
diff --git a/include/media/stagefright/foundation/ColorUtils.h b/include/media/stagefright/foundation/ColorUtils.h
index c4971bf..f01a210 100644
--- a/include/media/stagefright/foundation/ColorUtils.h
+++ b/include/media/stagefright/foundation/ColorUtils.h
@@ -129,6 +129,15 @@
static status_t convertCodecColorAspectsToPlatformAspects(
const ColorAspects &aspects, int32_t *range, int32_t *standard, int32_t *transfer);
+ // converts Other values to Unspecified
+ static void convertCodecColorAspectsToIsoAspects(
+ const ColorAspects &aspects,
+ int32_t *primaries, int32_t *transfer, int32_t *coeffs, bool *fullRange);
+ // converts unsupported values to Other
+ static void convertIsoColorAspectsToCodecAspects(
+ int32_t primaries, int32_t transfer, int32_t coeffs, bool fullRange,
+ ColorAspects &aspects);
+
// updates Unspecified color aspects to their defaults based on the video size
static void setDefaultCodecColorAspectsIfNeeded(
ColorAspects &aspects, int32_t width, int32_t height);
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index ea8a78e..2dfb850 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -268,6 +268,8 @@
// DEAD_OBJECT Server has died or invalidated, caller should destroy this proxy and re-create.
// -EINTR Call has been interrupted. Look around to see why, and then perhaps try again.
// NO_INIT Shared memory is corrupt.
+ // NOT_ENOUGH_DATA Server has disabled the track because of underrun: restart the track
+ // if still in active state.
// Assertion failure on entry, if buffer == NULL or buffer->mFrameCount == 0.
status_t obtainBuffer(Buffer* buffer, const struct timespec *requested = NULL,
struct timespec *elapsed = NULL);
diff --git a/media/libmedia/AudioPolicy.cpp b/media/libmedia/AudioPolicy.cpp
index ea22b6c..d1f7525 100644
--- a/media/libmedia/AudioPolicy.cpp
+++ b/media/libmedia/AudioPolicy.cpp
@@ -67,7 +67,8 @@
mFormat.channel_mask = (audio_channel_mask_t)parcel->readInt32();
mFormat.format = (audio_format_t)parcel->readInt32();
mRouteFlags = parcel->readInt32();
- mRegistrationId = parcel->readString8();
+ mDeviceType = (audio_devices_t) parcel->readInt32();
+ mDeviceAddress = parcel->readString8();
mCbFlags = (uint32_t)parcel->readInt32();
size_t size = (size_t)parcel->readInt32();
if (size > MAX_CRITERIA_PER_MIX) {
@@ -89,7 +90,8 @@
parcel->writeInt32(mFormat.channel_mask);
parcel->writeInt32(mFormat.format);
parcel->writeInt32(mRouteFlags);
- parcel->writeString8(mRegistrationId);
+ parcel->writeInt32(mDeviceType);
+ parcel->writeString8(mDeviceAddress);
parcel->writeInt32(mCbFlags);
size_t size = mCriteria.size();
if (size > MAX_CRITERIA_PER_MIX) {
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 9eb5ec7..1767385 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -522,6 +522,14 @@
// After fast request is denied, we will request again if IAudioRecord is re-created.
status_t status;
+
+ // Not a conventional loop, but a retry loop for at most two iterations total.
+ // Try first maybe with FAST flag then try again without FAST flag if that fails.
+ // Exits loop normally via a return at the bottom, or with error via a break.
+ // The sp<> references will be dropped when re-entering scope.
+ // The lack of indentation is deliberate, to reduce code churn and ease merges.
+ for (;;) {
+
status = AudioSystem::getInputForAttr(&mAttributes, &input,
(audio_session_t)mSessionId,
// FIXME compare to AudioTrack
@@ -535,7 +543,7 @@
mSessionId, mAttributes.source, mSampleRate, mFormat, mChannelMask, mFlags);
return BAD_VALUE;
}
- {
+
// Now that we have a reference to an I/O handle and have not yet handed it off to AudioFlinger,
// we must release it ourselves if anything goes wrong.
@@ -544,7 +552,7 @@
status = AudioSystem::getFrameCount(input, &afFrameCount);
if (status != NO_ERROR) {
ALOGE("getFrameCount(input=%d) status %d", input, status);
- goto release;
+ break;
}
#endif
@@ -552,7 +560,7 @@
status = AudioSystem::getSamplingRate(input, &afSampleRate);
if (status != NO_ERROR) {
ALOGE("getSamplingRate(input=%d) status %d", input, status);
- goto release;
+ break;
}
if (mSampleRate == 0) {
mSampleRate = afSampleRate;
@@ -572,7 +580,10 @@
ALOGW("AUDIO_INPUT_FLAG_FAST denied by client; transfer %d, "
"track %u Hz, input %u Hz",
mTransfer, mSampleRate, afSampleRate);
- mFlags = (audio_input_flags_t) (mFlags & ~AUDIO_INPUT_FLAG_FAST);
+ mFlags = (audio_input_flags_t) (mFlags & ~(AUDIO_INPUT_FLAG_FAST |
+ AUDIO_INPUT_FLAG_RAW));
+ AudioSystem::releaseInput(input, (audio_session_t)mSessionId);
+ continue; // retry
}
}
@@ -616,13 +627,26 @@
if (status != NO_ERROR) {
ALOGE("AudioFlinger could not create record track, status: %d", status);
- goto release;
+ break;
}
ALOG_ASSERT(record != 0);
// AudioFlinger now owns the reference to the I/O handle,
// so we are no longer responsible for releasing it.
+ mAwaitBoost = false;
+ if (mFlags & AUDIO_INPUT_FLAG_FAST) {
+ if (trackFlags & IAudioFlinger::TRACK_FAST) {
+ ALOGI("AUDIO_INPUT_FLAG_FAST successful; frameCount %zu", frameCount);
+ mAwaitBoost = true;
+ } else {
+ ALOGW("AUDIO_INPUT_FLAG_FAST denied by server; frameCount %zu", frameCount);
+ mFlags = (audio_input_flags_t) (mFlags & ~(AUDIO_INPUT_FLAG_FAST |
+ AUDIO_INPUT_FLAG_RAW));
+ continue; // retry
+ }
+ }
+
if (iMem == 0) {
ALOGE("Could not get control block");
return NO_INIT;
@@ -665,17 +689,6 @@
}
frameCount = temp;
- mAwaitBoost = false;
- if (mFlags & AUDIO_INPUT_FLAG_FAST) {
- if (trackFlags & IAudioFlinger::TRACK_FAST) {
- ALOGV("AUDIO_INPUT_FLAG_FAST successful; frameCount %zu", frameCount);
- mAwaitBoost = true;
- } else {
- ALOGW("AUDIO_INPUT_FLAG_FAST denied by server; frameCount %zu", frameCount);
- mFlags = (audio_input_flags_t) (mFlags & ~AUDIO_INPUT_FLAG_FAST);
- }
- }
-
// Make sure that application is notified with sufficient margin before overrun.
// The computation is done on server side.
if (mNotificationFramesReq > 0 && notificationFrames != mNotificationFramesReq) {
@@ -708,9 +721,12 @@
}
return NO_ERROR;
+
+ // End of retry loop.
+ // The lack of indentation is deliberate, to reduce code churn and ease merges.
}
-release:
+// Arrive here on error, via a break
AudioSystem::releaseInput(input, (audio_session_t)mSessionId);
if (status == NO_ERROR) {
status = NO_INIT;
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 423273d..ab18c27 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -1532,6 +1532,10 @@
}
oldSequence = newSequence;
+ if (status == NOT_ENOUGH_DATA) {
+ restartIfDisabled();
+ }
+
// Keep the extra references
proxy = mProxy;
iMem = mCblkMemory;
@@ -1554,8 +1558,7 @@
buffer.mFrameCount = audioBuffer->frameCount;
// FIXME starts the requested timeout and elapsed over from scratch
status = proxy->obtainBuffer(&buffer, requested, elapsed);
-
- } while ((status == DEAD_OBJECT) && (tryCounter-- > 0));
+ } while (((status == DEAD_OBJECT) || (status == NOT_ENOUGH_DATA)) && (tryCounter-- > 0));
audioBuffer->frameCount = buffer.mFrameCount;
audioBuffer->size = buffer.mFrameCount * mFrameSize;
@@ -1588,13 +1591,16 @@
mProxy->releaseBuffer(&buffer);
// restart track if it was disabled by audioflinger due to previous underrun
- if (mState == STATE_ACTIVE) {
- audio_track_cblk_t* cblk = mCblk;
- if (android_atomic_and(~CBLK_DISABLED, &cblk->mFlags) & CBLK_DISABLED) {
- ALOGW("releaseBuffer() track %p disabled due to previous underrun, restarting", this);
- // FIXME ignoring status
- mAudioTrack->start();
- }
+ restartIfDisabled();
+}
+
+void AudioTrack::restartIfDisabled()
+{
+ int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
+ if ((mState == STATE_ACTIVE) && (flags & CBLK_DISABLED)) {
+ ALOGW("releaseBuffer() track %p disabled due to previous underrun, restarting", this);
+ // FIXME ignoring status
+ mAudioTrack->start();
}
}
diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp
index 1d15495..6b6865b 100644
--- a/media/libmedia/AudioTrackShared.cpp
+++ b/media/libmedia/AudioTrackShared.cpp
@@ -129,6 +129,11 @@
status = DEAD_OBJECT;
goto end;
}
+ if (flags & CBLK_DISABLED) {
+ ALOGV("Track disabled");
+ status = NOT_ENOUGH_DATA;
+ goto end;
+ }
// check for obtainBuffer interrupted by client
if (!ignoreInitialPendingInterrupt && (flags & CBLK_INTERRUPT)) {
ALOGV("obtainBuffer() interrupted by client");
@@ -425,7 +430,8 @@
status = DEAD_OBJECT;
goto end;
}
- if (flags & CBLK_STREAM_END_DONE) {
+ // a track is not supposed to underrun at this stage but consider it done
+ if (flags & (CBLK_STREAM_END_DONE | CBLK_DISABLED)) {
ALOGV("stream end received");
status = NO_ERROR;
goto end;
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 1ac098c..ea4a966 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -24,6 +24,7 @@
#include <binder/Parcel.h>
#include <media/IOMX.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/openmax/OMX_IndexExt.h>
namespace android {
@@ -717,7 +718,8 @@
void *params = NULL;
size_t pageSize = 0;
size_t allocSize = 0;
- if (code != SET_INTERNAL_OPTION && size < 8) {
+ if ((index == (OMX_INDEXTYPE) OMX_IndexParamConsumerUsageBits && size < 4) ||
+ (code != SET_INTERNAL_OPTION && size < 8)) {
// we expect the structure to contain at least the size and
// version, 8 bytes total
ALOGE("b/27207275 (%zu)", size);
@@ -739,7 +741,9 @@
} else {
err = NOT_ENOUGH_DATA;
OMX_U32 declaredSize = *(OMX_U32*)params;
- if (code != SET_INTERNAL_OPTION && declaredSize > size) {
+ if (code != SET_INTERNAL_OPTION &&
+ index != (OMX_INDEXTYPE) OMX_IndexParamConsumerUsageBits &&
+ declaredSize > size) {
// the buffer says it's bigger than it actually is
ALOGE("b/27207275 (%u/%zu)", declaredSize, size);
android_errorWriteLog(0x534e4554, "27207275");
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index d7c8faa..e0fe7e3 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -3846,13 +3846,6 @@
h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
}
- // XXX
- if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
- ALOGW("Use baseline profile instead of %d for AVC recording",
- h264type.eProfile);
- h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
- }
-
if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
h264type.nSliceHeaderSpacing = 0;
h264type.bUseHadamard = OMX_TRUE;
@@ -3870,6 +3863,23 @@
h264type.bDirect8x8Inference = OMX_FALSE;
h264type.bDirectSpatialTemporal = OMX_FALSE;
h264type.nCabacInitIdc = 0;
+ } else if (h264type.eProfile == OMX_VIDEO_AVCProfileMain ||
+ h264type.eProfile == OMX_VIDEO_AVCProfileHigh) {
+ h264type.nSliceHeaderSpacing = 0;
+ h264type.bUseHadamard = OMX_TRUE;
+ h264type.nRefFrames = 2;
+ h264type.nBFrames = 1;
+ h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
+ h264type.nAllowedPictureTypes =
+ OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP | OMX_VIDEO_PictureTypeB;
+ h264type.nRefIdx10ActiveMinus1 = 0;
+ h264type.nRefIdx11ActiveMinus1 = 0;
+ h264type.bEntropyCodingCABAC = OMX_TRUE;
+ h264type.bWeightedPPrediction = OMX_TRUE;
+ h264type.bconstIpred = OMX_TRUE;
+ h264type.bDirect8x8Inference = OMX_TRUE;
+ h264type.bDirectSpatialTemporal = OMX_TRUE;
+ h264type.nCabacInitIdc = 1;
}
if (h264type.nBFrames != 0) {
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 59f839c..cb974ae 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -758,7 +758,7 @@
mStartTimeUs = 0;
mNumInputBuffers = 0;
mEncoderFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
- mEncoderDataSpace = HAL_DATASPACE_BT709;
+ mEncoderDataSpace = HAL_DATASPACE_V0_BT709;
if (meta) {
int64_t startTimeUs;
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index d5a869d..322eab9 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -34,6 +34,7 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AUtils.h>
+#include <media/stagefright/foundation/ColorUtils.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDefs.h>
@@ -2083,6 +2084,21 @@
break;
}
+ case FOURCC('c', 'o', 'l', 'r'):
+ {
+ *offset += chunk_size;
+ // this must be in a VisualSampleEntry box under the Sample Description Box ('stsd')
+ // ignore otherwise
+ if (depth >= 2 && mPath[depth - 2] == FOURCC('s', 't', 's', 'd')) {
+ status_t err = parseColorInfo(data_offset, chunk_data_size);
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ break;
+ }
+
case FOURCC('t', 'i', 't', 'l'):
case FOURCC('p', 'e', 'r', 'f'):
case FOURCC('a', 'u', 't', 'h'):
@@ -2663,6 +2679,49 @@
return OK;
}
+status_t MPEG4Extractor::parseColorInfo(off64_t offset, size_t size) {
+ if (size < 4 || size == SIZE_MAX || mLastTrack == NULL) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t *buffer = new (std::nothrow) uint8_t[size + 1];
+ if (buffer == NULL) {
+ return ERROR_MALFORMED;
+ }
+ if (mDataSource->readAt(offset, buffer, size) != (ssize_t)size) {
+ delete[] buffer;
+ buffer = NULL;
+
+ return ERROR_IO;
+ }
+
+ int32_t type = U32_AT(&buffer[0]);
+ if ((type == FOURCC('n', 'c', 'l', 'x') && size >= 11)
+ || (type == FOURCC('n', 'c', 'l', 'c' && size >= 10))) {
+ int32_t primaries = U16_AT(&buffer[4]);
+ int32_t transfer = U16_AT(&buffer[6]);
+ int32_t coeffs = U16_AT(&buffer[8]);
+ bool fullRange = (type == FOURCC('n', 'c', 'l', 'x')) && (buffer[10] & 128);
+
+ ColorAspects aspects;
+ ColorUtils::convertIsoColorAspectsToCodecAspects(
+ primaries, transfer, coeffs, fullRange, aspects);
+
+ // only store the first color specification
+ if (!mLastTrack->meta->hasData(kKeyColorPrimaries)) {
+ mLastTrack->meta->setInt32(kKeyColorPrimaries, aspects.mPrimaries);
+ mLastTrack->meta->setInt32(kKeyTransferFunction, aspects.mTransfer);
+ mLastTrack->meta->setInt32(kKeyColorMatrix, aspects.mMatrixCoeffs);
+ mLastTrack->meta->setInt32(kKeyColorRange, aspects.mRange);
+ }
+ }
+
+ delete[] buffer;
+ buffer = NULL;
+
+ return OK;
+}
+
status_t MPEG4Extractor::parse3GPPMetaData(off64_t offset, size_t size, int depth) {
if (size < 4 || size == SIZE_MAX) {
return ERROR_MALFORMED;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index ef0e17f..7c03886 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -30,6 +30,7 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/ColorUtils.h>
#include <media/stagefright/MPEG4Writer.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MetaData.h>
@@ -371,6 +372,7 @@
void writeVmhdBox();
void writeHdlrBox();
void writeTkhdBox(uint32_t now);
+ void writeColrBox();
void writeMp4aEsdsBox();
void writeMp4vEsdsBox();
void writeAudioFourCCBox();
@@ -2353,6 +2355,7 @@
if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
&& isCodecConfig) {
CHECK(!mGotAllCodecSpecificData);
+ mMeta = mSource->getFormat(); // get output format after format change
if (mIsAvc) {
status_t err = makeAVCCodecSpecificData(
@@ -2960,9 +2963,32 @@
}
writePaspBox();
+ writeColrBox();
mOwner->endBox(); // mp4v, s263 or avc1
}
+void MPEG4Writer::Track::writeColrBox() {
+ ColorAspects aspects;
+ memset(&aspects, 0, sizeof(aspects));
+ // TRICKY: using | instead of || because we want to execute all findInt32-s
+ if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries)
+ | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer)
+ | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs)
+ | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) {
+ int32_t primaries, transfer, coeffs;
+ bool fullRange;
+ ColorUtils::convertCodecColorAspectsToIsoAspects(
+ aspects, &primaries, &transfer, &coeffs, &fullRange);
+ mOwner->beginBox("colr");
+ mOwner->writeFourcc("nclx");
+ mOwner->writeInt16(primaries);
+ mOwner->writeInt16(transfer);
+ mOwner->writeInt16(coeffs);
+ mOwner->writeInt8(fullRange ? 128 : 0);
+ mOwner->endBox(); // colr
+ }
+}
+
void MPEG4Writer::Track::writeAudioFourCCBox() {
const char *mime;
bool success = mMeta->findCString(kKeyMIMEType, &mime);
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 772a5c4..0a052d2 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -42,7 +42,7 @@
const int32_t kDefaultSwVideoEncoderFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
const int32_t kDefaultHwVideoEncoderFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
-const int32_t kDefaultVideoEncoderDataSpace = HAL_DATASPACE_BT709;
+const int32_t kDefaultVideoEncoderDataSpace = HAL_DATASPACE_V0_BT709;
const int kStopTimeoutUs = 300000; // allow 1 sec for shutting down encoder
@@ -781,6 +781,13 @@
mAvailEncoderInputIndices.push_back(index);
feedEncoderInputBuffers();
+ } else if (cbID == MediaCodec::CB_OUTPUT_FORMAT_CHANGED) {
+ status_t err = mEncoder->getOutputFormat(&mOutputFormat);
+ if (err != OK) {
+ signalEOS(err);
+ break;
+ }
+ convertMessageToMetaData(mOutputFormat, mMeta);
} else if (cbID == MediaCodec::CB_OUTPUT_AVAILABLE) {
int32_t index;
size_t offset;
diff --git a/media/libstagefright/codecs/amrwbenc/inc/basic_op.h b/media/libstagefright/codecs/amrwbenc/inc/basic_op.h
index db3e058..8165f69 100644
--- a/media/libstagefright/codecs/amrwbenc/inc/basic_op.h
+++ b/media/libstagefright/codecs/amrwbenc/inc/basic_op.h
@@ -51,11 +51,11 @@
#define vo_shr_r(var1, var2) ((var1+((Word16)(1L<<(var2-1))))>>var2)
#define vo_sub(a,b) (a - b)
#define vo_L_deposit_h(a) ((Word32)((a) << 16))
-#define vo_round(a) ((a + 0x00008000) >> 16)
+#define vo_round(a) ((((a) >> 15) + 1) >> 1)
#define vo_extract_l(a) ((Word16)(a))
#define vo_L_add(a,b) (a + b)
#define vo_L_sub(a,b) (a - b)
-#define vo_mult_r(a,b) ((( a * b ) + 0x4000 ) >> 15 )
+#define vo_mult_r(a,b) (((( a * b ) >> 14) + 1 ) >> 1 )
#define vo_negate(a) (-a)
#define vo_L_shr_r(L_var1, var2) ((L_var1+((Word32)(1L<<(var2-1))))>>var2)
diff --git a/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c b/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
index 8bf15ea..4d877f1 100644
--- a/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
+++ b/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
@@ -267,13 +267,13 @@
for (i = 0; i < L_SUBFR/4; i++)
{
- s = (k_cn* (*p0++))+(k_dn * (*p1++));
+ s = L_add((k_cn* (*p0++)), (k_dn * (*p1++)));
*p2++ = s >> 7;
- s = (k_cn* (*p0++))+(k_dn * (*p1++));
+ s = L_add((k_cn* (*p0++)), (k_dn * (*p1++)));
*p2++ = s >> 7;
- s = (k_cn* (*p0++))+(k_dn * (*p1++));
+ s = L_add((k_cn* (*p0++)), (k_dn * (*p1++)));
*p2++ = s >> 7;
- s = (k_cn* (*p0++))+(k_dn * (*p1++));
+ s = L_add((k_cn* (*p0++)), (k_dn * (*p1++)));
*p2++ = s >> 7;
}
@@ -342,7 +342,7 @@
{
*h++ = 0;
*h_inv++ = 0;
- L_tmp += (H[i] * H[i]) << 1;
+ L_tmp = L_add(L_tmp, (H[i] * H[i]) << 1);
}
/* scale h[] down (/2) when energy of h[] is high with many pulses used */
val = extract_h(L_tmp);
@@ -386,16 +386,16 @@
cor = 0x00008000L; /* for rounding */
for (i = 0; i < NB_POS; i++)
{
- cor += vo_L_mult((*ptr_h1), (*ptr_h1));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h1)));
ptr_h1++;
*p3-- = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h1));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h1)));
ptr_h1++;
*p2-- = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h1));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h1)));
ptr_h1++;
*p1-- = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h1));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h1)));
ptr_h1++;
*p0-- = extract_h(cor);
}
@@ -425,19 +425,19 @@
for (i = k + 1; i < NB_POS; i++)
{
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p3 = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p2 = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p1 = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p0 = extract_h(cor);
@@ -447,15 +447,15 @@
p1 -= (NB_POS + 1);
p0 -= (NB_POS + 1);
}
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p3 = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p2 = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p1 = extract_h(cor);
@@ -482,19 +482,19 @@
for (i = k + 1; i < NB_POS; i++)
{
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p3 = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p2 = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p1 = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p0 = extract_h(cor);
@@ -504,7 +504,7 @@
p1 -= (NB_POS + 1);
p0 -= (NB_POS + 1);
}
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p3 = extract_h(cor);
@@ -698,7 +698,7 @@
}
/* memorise the best codevector */
ps = vo_mult(ps, ps);
- s = vo_L_msu(vo_L_mult(alpk, ps), psk, alp);
+ s = L_sub(vo_L_mult(alpk, ps), vo_L_mult(psk, alp));
if (s > 0)
{
psk = ps;
diff --git a/media/libstagefright/foundation/ColorUtils.cpp b/media/libstagefright/foundation/ColorUtils.cpp
index 30d5b45..99031ca 100644
--- a/media/libstagefright/foundation/ColorUtils.cpp
+++ b/media/libstagefright/foundation/ColorUtils.cpp
@@ -29,6 +29,7 @@
typedef ColorAspects CA;
typedef ColorUtils CU;
+const static
ALookup<CU::ColorRange, CA::Range> sRanges{
{
{ CU::kColorRangeLimited, CA::RangeLimited },
@@ -37,6 +38,7 @@
}
};
+const static
ALookup<CU::ColorStandard, std::pair<CA::Primaries, CA::MatrixCoeffs>> sStandards {
{
{ CU::kColorStandardUnspecified, { CA::PrimariesUnspecified, CA::MatrixUnspecified } },
@@ -56,6 +58,7 @@
}
};
+const static
ALookup<CU::ColorTransfer, CA::Transfer> sTransfers{
{
{ CU::kColorTransferUnspecified, CA::TransferUnspecified },
@@ -243,6 +246,97 @@
}
}
+const static
+ALookup<int32_t, ColorAspects::Primaries> sIsoPrimaries {
+ {
+ { 1, ColorAspects::PrimariesBT709_5 },
+ { 2, ColorAspects::PrimariesUnspecified },
+ { 4, ColorAspects::PrimariesBT470_6M },
+ { 5, ColorAspects::PrimariesBT601_6_625 },
+ { 6, ColorAspects::PrimariesBT601_6_525 /* main */},
+ { 7, ColorAspects::PrimariesBT601_6_525 },
+ // -- ITU T.832 201201 ends here
+ { 8, ColorAspects::PrimariesGenericFilm },
+ { 9, ColorAspects::PrimariesBT2020 },
+ { 10, ColorAspects::PrimariesOther /* XYZ */ },
+ }
+};
+
+const static
+ALookup<int32_t, ColorAspects::Transfer> sIsoTransfers {
+ {
+ { 1, ColorAspects::TransferSMPTE170M /* main */},
+ { 2, ColorAspects::TransferUnspecified },
+ { 4, ColorAspects::TransferGamma22 },
+ { 5, ColorAspects::TransferGamma28 },
+ { 6, ColorAspects::TransferSMPTE170M },
+ { 7, ColorAspects::TransferSMPTE240M },
+ { 8, ColorAspects::TransferLinear },
+ { 9, ColorAspects::TransferOther /* log 100:1 */ },
+ { 10, ColorAspects::TransferOther /* log 316:1 */ },
+ { 11, ColorAspects::TransferXvYCC },
+ { 12, ColorAspects::TransferBT1361 },
+ { 13, ColorAspects::TransferSRGB },
+ // -- ITU T.832 201201 ends here
+ { 14, ColorAspects::TransferSMPTE170M },
+ { 15, ColorAspects::TransferSMPTE170M },
+ { 16, ColorAspects::TransferST2084 },
+ { 17, ColorAspects::TransferST428 },
+ }
+};
+
+const static
+ALookup<int32_t, ColorAspects::MatrixCoeffs> sIsoMatrixCoeffs {
+ {
+ { 0, ColorAspects::MatrixOther },
+ { 1, ColorAspects::MatrixBT709_5 },
+ { 2, ColorAspects::MatrixUnspecified },
+ { 4, ColorAspects::MatrixBT470_6M },
+ { 6, ColorAspects::MatrixBT601_6 /* main */ },
+ { 5, ColorAspects::MatrixBT601_6 },
+ { 7, ColorAspects::MatrixSMPTE240M },
+ { 8, ColorAspects::MatrixOther /* YCgCo */ },
+ // -- ITU T.832 201201 ends here
+ { 9, ColorAspects::MatrixBT2020 },
+ { 10, ColorAspects::MatrixBT2020Constant },
+ }
+};
+
+// static
+void ColorUtils::convertCodecColorAspectsToIsoAspects(
+ const ColorAspects &aspects,
+ int32_t *primaries, int32_t *transfer, int32_t *coeffs, bool *fullRange) {
+ if (aspects.mPrimaries == ColorAspects::PrimariesOther ||
+ !sIsoPrimaries.map(aspects.mPrimaries, primaries)) {
+ CHECK(sIsoPrimaries.map(ColorAspects::PrimariesUnspecified, primaries));
+ }
+ if (aspects.mTransfer == ColorAspects::TransferOther ||
+ !sIsoTransfers.map(aspects.mTransfer, transfer)) {
+ CHECK(sIsoTransfers.map(ColorAspects::TransferUnspecified, transfer));
+ }
+ if (aspects.mMatrixCoeffs == ColorAspects::MatrixOther ||
+ !sIsoMatrixCoeffs.map(aspects.mMatrixCoeffs, coeffs)) {
+ CHECK(sIsoMatrixCoeffs.map(ColorAspects::MatrixUnspecified, coeffs));
+ }
+ *fullRange = aspects.mRange == ColorAspects::RangeFull;
+}
+
+// static
+void ColorUtils::convertIsoColorAspectsToCodecAspects(
+ int32_t primaries, int32_t transfer, int32_t coeffs, bool fullRange,
+ ColorAspects &aspects) {
+ if (!sIsoPrimaries.map(primaries, &aspects.mPrimaries)) {
+ aspects.mPrimaries = ColorAspects::PrimariesUnspecified;
+ }
+ if (!sIsoTransfers.map(transfer, &aspects.mTransfer)) {
+ aspects.mTransfer = ColorAspects::TransferUnspecified;
+ }
+ if (!sIsoMatrixCoeffs.map(coeffs, &aspects.mMatrixCoeffs)) {
+ aspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
+ }
+ aspects.mRange = fullRange ? ColorAspects::RangeFull : ColorAspects::RangeLimited;
+}
+
// static
void ColorUtils::setDefaultCodecColorAspectsIfNeeded(
ColorAspects &aspects, int32_t width, int32_t height) {
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index 3e8fb7c..18b14e1 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -110,6 +110,7 @@
status_t readMetaData();
status_t parseChunk(off64_t *offset, int depth);
status_t parseITunesMetaData(off64_t offset, size_t size);
+ status_t parseColorInfo(off64_t offset, size_t size);
status_t parse3GPPMetaData(off64_t offset, size_t size, int depth);
void parseID3v2MetaData(off64_t offset);
status_t parseQTMetaKey(off64_t data_offset, size_t data_size);
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 5fcc0fe..27149ed 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -139,18 +139,18 @@
status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle)
{
- ALOGV("createAudioPatch() num_sources %d num_sinks %d handle %d",
- patch->num_sources, patch->num_sinks, *handle);
status_t status = NO_ERROR;
audio_patch_handle_t halHandle = AUDIO_PATCH_HANDLE_NONE;
sp<AudioFlinger> audioflinger = mAudioFlinger.promote();
+ if (handle == NULL || patch == NULL) {
+ return BAD_VALUE;
+ }
+ ALOGV("createAudioPatch() num_sources %d num_sinks %d handle %d",
+ patch->num_sources, patch->num_sinks, *handle);
if (audioflinger == 0) {
return NO_INIT;
}
- if (handle == NULL || patch == NULL) {
- return BAD_VALUE;
- }
if (patch->num_sources == 0 || patch->num_sources > AUDIO_PATCH_PORTS_MAX ||
(patch->num_sinks == 0 && patch->num_sources != 2) ||
patch->num_sinks > AUDIO_PATCH_PORTS_MAX) {
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index fa61af2..6e0c46d 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -110,10 +110,13 @@
// audioHalFrames is derived from output latency
// FIXME parameters not needed, could get them from the thread
bool presentationComplete(int64_t framesWritten, size_t audioHalFrames);
+ void signalClientFlag(int32_t flag);
public:
void triggerEvents(AudioSystem::sync_event_t type);
void invalidate();
+ void disable();
+
bool isInvalid() const { return mIsInvalid; }
int fastIndex() const { return mFastIndex; }
@@ -200,6 +203,8 @@
uint32_t waitTimeMs);
void clearBufferQueue();
+ void restartIfDisabled();
+
// Maximum number of pending buffers allocated by OutputTrack::write()
static const uint8_t kMaxOverFlowBuffers = 10;
@@ -224,6 +229,10 @@
IAudioFlinger::track_flags_t flags);
virtual ~PatchTrack();
+ virtual status_t start(AudioSystem::sync_event_t event =
+ AudioSystem::SYNC_EVENT_NONE,
+ int triggerSession = 0);
+
// AudioBufferProvider interface
virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
@@ -236,6 +245,8 @@
void setPeerProxy(PatchProxyBufferProvider *proxy) { mPeerProxy = proxy; }
private:
+ void restartIfDisabled();
+
sp<ClientProxy> mProxy;
PatchProxyBufferProvider* mPeerProxy;
struct timespec mPeerTimeout;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 96c5f59..f206e96 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1113,7 +1113,7 @@
status_t status;
status = mPowerManager->updateWakeLockUids(mWakeLockToken, uids.size(), uids.array(),
true /* FIXME force oneway contrary to .aidl */);
- ALOGV("acquireWakeLock_l() %s status %d", mThreadName, status);
+ ALOGV("updateWakeLockUids_l() %s status %d", mThreadName, status);
}
}
@@ -3961,7 +3961,7 @@
}
// indicate to client process that the track was disabled because of underrun;
// it will then automatically call start() when data is available
- android_atomic_or(CBLK_DISABLED, &track->mCblk->mFlags);
+ track->disable();
// remove from active list, but state remains ACTIVE [confusing but true]
isActive = false;
break;
@@ -4322,7 +4322,7 @@
tracksToRemove->add(track);
// indicate to client process that the track was disabled because of underrun;
// it will then automatically call start() when data is available
- android_atomic_or(CBLK_DISABLED, &cblk->mFlags);
+ track->disable();
// If one track is not ready, mark the mixer also not ready if:
// - the mixer was ready during previous round OR
// - no other track is ready
@@ -4869,7 +4869,7 @@
tracksToRemove->add(track);
// indicate to client process that the track was disabled because of underrun;
// it will then automatically call start() when data is available
- android_atomic_or(CBLK_DISABLED, &cblk->mFlags);
+ track->disable();
} else if (last) {
ALOGW("pause because of UNDERRUN, framesReady = %zu,"
"minFrames = %u, mFormat = %#x",
@@ -5423,7 +5423,7 @@
tracksToRemove->add(track);
// indicate to client process that the track was disabled because of underrun;
// it will then automatically call start() when data is available
- android_atomic_or(CBLK_DISABLED, &cblk->mFlags);
+ track->disable();
} else if (last){
mixerStatus = MIXER_TRACKS_ENABLED;
}
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 8b49062..0c51e81 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1027,13 +1027,23 @@
void AudioFlinger::PlaybackThread::Track::invalidate()
{
+ signalClientFlag(CBLK_INVALID);
+ mIsInvalid = true;
+}
+
+void AudioFlinger::PlaybackThread::Track::disable()
+{
+ signalClientFlag(CBLK_DISABLED);
+}
+
+void AudioFlinger::PlaybackThread::Track::signalClientFlag(int32_t flag)
+{
// FIXME should use proxy, and needs work
audio_track_cblk_t* cblk = mCblk;
- android_atomic_or(CBLK_INVALID, &cblk->mFlags);
+ android_atomic_or(flag, &cblk->mFlags);
android_atomic_release_store(0x40000000, &cblk->mFutex);
// client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
(void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
- mIsInvalid = true;
}
void AudioFlinger::PlaybackThread::Track::signal()
@@ -1199,7 +1209,7 @@
mOutBuffer.frameCount = pInBuffer->frameCount;
nsecs_t startTime = systemTime();
status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
- if (status != NO_ERROR) {
+ if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
ALOGV("OutputTrack::write() %p thread %p no more output buffers; status %d", this,
mThread.unsafe_get(), status);
outputBufferFull = true;
@@ -1211,6 +1221,10 @@
} else {
waitTimeLeftMs = 0;
}
+ if (status == NOT_ENOUGH_DATA) {
+ restartIfDisabled();
+ continue;
+ }
}
uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
@@ -1220,6 +1234,7 @@
buf.mFrameCount = outFrames;
buf.mRaw = NULL;
mClientProxy->releaseBuffer(&buf);
+ restartIfDisabled();
pInBuffer->frameCount -= outFrames;
pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
mOutBuffer.frameCount -= outFrames;
@@ -1293,6 +1308,13 @@
mBufferQueue.clear();
}
+void AudioFlinger::PlaybackThread::OutputTrack::restartIfDisabled()
+{
+ int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
+ if (mActive && (flags & CBLK_DISABLED)) {
+ start();
+ }
+}
AudioFlinger::PlaybackThread::PatchTrack::PatchTrack(PlaybackThread *playbackThread,
audio_stream_type_t streamType,
@@ -1322,6 +1344,17 @@
{
}
+status_t AudioFlinger::PlaybackThread::PatchTrack::start(AudioSystem::sync_event_t event,
+ int triggerSession)
+{
+ status_t status = Track::start(event, triggerSession);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
+ return status;
+}
+
// AudioBufferProvider interface
status_t AudioFlinger::PlaybackThread::PatchTrack::getNextBuffer(
AudioBufferProvider::Buffer* buffer)
@@ -1352,17 +1385,31 @@
status_t AudioFlinger::PlaybackThread::PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
const struct timespec *timeOut)
{
- return mProxy->obtainBuffer(buffer, timeOut);
+ status_t status = NO_ERROR;
+ static const int32_t kMaxTries = 5;
+ int32_t tryCounter = kMaxTries;
+ do {
+ if (status == NOT_ENOUGH_DATA) {
+ restartIfDisabled();
+ }
+ status = mProxy->obtainBuffer(buffer, timeOut);
+ } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
+ return status;
}
void AudioFlinger::PlaybackThread::PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
{
mProxy->releaseBuffer(buffer);
+ restartIfDisabled();
+ android_atomic_or(CBLK_FORCEREADY, &mCblk->mFlags);
+}
+
+void AudioFlinger::PlaybackThread::PatchTrack::restartIfDisabled()
+{
if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
ALOGW("PatchTrack::releaseBuffer() disabled due to previous underrun, restarting");
start();
}
- android_atomic_or(CBLK_FORCEREADY, &mCblk->mFlags);
}
// ----------------------------------------------------------------------------
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index 6968a74..f73548d 100755
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -42,9 +42,9 @@
* A device mask for all audio input and output devices where matching inputs/outputs on device
* type alone is not enough: the address must match too
*/
-#define APM_AUDIO_DEVICE_OUT_MATCH_ADDRESS_ALL (AUDIO_DEVICE_OUT_REMOTE_SUBMIX)
+#define APM_AUDIO_DEVICE_OUT_MATCH_ADDRESS_ALL (AUDIO_DEVICE_OUT_REMOTE_SUBMIX|AUDIO_DEVICE_OUT_BUS)
-#define APM_AUDIO_DEVICE_IN_MATCH_ADDRESS_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX)
+#define APM_AUDIO_DEVICE_IN_MATCH_ADDRESS_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX|AUDIO_DEVICE_IN_BUS)
/**
* Check if the state given correspond to an in call state.
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index c952831..8f5ebef 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -54,7 +54,7 @@
public:
status_t getAudioPolicyMix(String8 address, sp<AudioPolicyMix> &policyMix) const;
- status_t registerMix(String8 address, AudioMix mix);
+ status_t registerMix(String8 address, AudioMix mix, sp<SwAudioOutputDescriptor> desc);
status_t unregisterMix(String8 address);
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 0fe1a84..c5fee50 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -315,14 +315,14 @@
if ((oldGlobalRefCount == 0) && (mGlobalRefCount > 0)) {
if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
{
- mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId,
+ mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
MIX_STATE_MIXING);
}
} else if ((oldGlobalRefCount > 0) && (mGlobalRefCount == 0)) {
if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
{
- mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId,
+ mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
MIX_STATE_IDLE);
}
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 3735c05..4af3d54 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -51,7 +51,8 @@
return &mMix;
}
-status_t AudioPolicyMixCollection::registerMix(String8 address, AudioMix mix)
+status_t AudioPolicyMixCollection::registerMix(String8 address, AudioMix mix,
+ sp<SwAudioOutputDescriptor> desc)
{
ssize_t index = indexOfKey(address);
if (index >= 0) {
@@ -61,6 +62,11 @@
sp<AudioPolicyMix> policyMix = new AudioPolicyMix();
policyMix->setMix(mix);
add(address, policyMix);
+
+ if (desc != 0) {
+ desc->mPolicyMix = policyMix->getMix();
+ policyMix->setOutput(desc);
+ }
return NO_ERROR;
}
@@ -128,7 +134,7 @@
// if there is an address match, prioritize that match
if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
strncmp(attributes.tags + strlen("addr="),
- mix->mRegistrationId.string(),
+ mix->mDeviceAddress.string(),
AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
hasAddrMatch = true;
break;
@@ -207,7 +213,7 @@
if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE &&
strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
strncmp(attributes.tags + strlen("addr="),
- mix->mRegistrationId.string(),
+ mix->mDeviceAddress.string(),
AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
desc = policyMix->getOutput();
}
@@ -260,7 +266,7 @@
for (size_t i = 0; i < size(); i++) {
sp<AudioPolicyMix> policyMix = valueAt(i);
AudioMix *mix = policyMix->getMix();
- ALOGV("\tmix %zu address=%s", i, mix->mRegistrationId.string());
+ ALOGV("\tmix %zu address=%s", i, mix->mDeviceAddress.string());
}
#endif
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
index ce9c170..da983c5 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
@@ -79,7 +79,7 @@
// if input maps to a dynamic policy with an activity listener, notify of state change
if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
{
- mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId,
+ mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
(event == RECORD_CONFIG_EVENT_START) ? MIX_STATE_MIXING : MIX_STATE_IDLE);
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index c3b1529..1d7849c 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1096,7 +1096,7 @@
outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- outputDesc->mPolicyMix->mRegistrationId,
+ outputDesc->mPolicyMix->mDeviceAddress,
"remote-submix");
}
@@ -1213,7 +1213,7 @@
outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- outputDesc->mPolicyMix->mRegistrationId,
+ outputDesc->mPolicyMix->mDeviceAddress,
"remote-submix");
}
}
@@ -1388,7 +1388,7 @@
return BAD_VALUE;
}
if (policyMix != NULL) {
- address = policyMix->mRegistrationId;
+ address = policyMix->mDeviceAddress;
if (policyMix->mMixType == MIX_TYPE_RECORDERS) {
// there is an external policy, but this input is attached to a mix of recorders,
// meaning it receives audio injected into the framework, so the recorder doesn't
@@ -1622,7 +1622,7 @@
// if input maps to a dynamic policy with an activity listener, notify of state change
if ((inputDesc->mPolicyMix != NULL)
&& ((inputDesc->mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
- mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mRegistrationId,
+ mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mDeviceAddress,
MIX_STATE_MIXING);
}
@@ -1639,7 +1639,7 @@
if (inputDesc->mPolicyMix == NULL) {
address = String8("0");
} else if (inputDesc->mPolicyMix->mMixType == MIX_TYPE_PLAYERS) {
- address = inputDesc->mPolicyMix->mRegistrationId;
+ address = inputDesc->mPolicyMix->mDeviceAddress;
}
if (address != "") {
setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
@@ -1686,7 +1686,7 @@
// if input maps to a dynamic policy with an activity listener, notify of state change
if ((inputDesc->mPolicyMix != NULL)
&& ((inputDesc->mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
- mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mRegistrationId,
+ mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mDeviceAddress,
MIX_STATE_IDLE);
}
@@ -1697,7 +1697,7 @@
if (inputDesc->mPolicyMix == NULL) {
address = String8("0");
} else if (inputDesc->mPolicyMix->mMixType == MIX_TYPE_PLAYERS) {
- address = inputDesc->mPolicyMix->mRegistrationId;
+ address = inputDesc->mPolicyMix->mDeviceAddress;
}
if (address != "") {
setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
@@ -2010,94 +2010,152 @@
status_t AudioPolicyManager::registerPolicyMixes(Vector<AudioMix> mixes)
{
- sp<HwModule> module;
- for (size_t i = 0; i < mHwModules.size(); i++) {
- if (strcmp(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, mHwModules[i]->mName) == 0 &&
- mHwModules[i]->mHandle != 0) {
- module = mHwModules[i];
+ ALOGV("registerPolicyMixes() %zu mix(es)", mixes.size());
+ status_t res = NO_ERROR;
+
+ sp<HwModule> rSubmixModule;
+ // examine each mix's route type
+ for (size_t i = 0; i < mixes.size(); i++) {
+ // we only support MIX_ROUTE_FLAG_LOOP_BACK or MIX_ROUTE_FLAG_RENDER, not the combination
+ if ((mixes[i].mRouteFlags & MIX_ROUTE_FLAG_ALL) == MIX_ROUTE_FLAG_ALL) {
+ res = INVALID_OPERATION;
break;
}
- }
+ if ((mixes[i].mRouteFlags & MIX_ROUTE_FLAG_LOOP_BACK) == MIX_ROUTE_FLAG_LOOP_BACK) {
+ // Loop back through "remote submix"
+ if (rSubmixModule == 0) {
+ for (size_t j = 0; i < mHwModules.size(); j++) {
+ if (strcmp(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, mHwModules[j]->mName) == 0
+ && mHwModules[j]->mHandle != 0) {
+ rSubmixModule = mHwModules[j];
+ break;
+ }
+ }
+ }
- if (module == 0) {
- return INVALID_OPERATION;
- }
+ ALOGV("registerPolicyMixes() mix %zu of %zu is LOOP_BACK", i, mixes.size());
- ALOGV("registerPolicyMixes() num mixes %zu", mixes.size());
+ if (rSubmixModule == 0) {
+ ALOGE(" Unable to find audio module for submix, aborting mix %zu registration", i);
+ res = INVALID_OPERATION;
+ break;
+ }
- for (size_t i = 0; i < mixes.size(); i++) {
- String8 address = mixes[i].mRegistrationId;
+ String8 address = mixes[i].mDeviceAddress;
- if (mPolicyMixes.registerMix(address, mixes[i]) != NO_ERROR) {
- continue;
- }
- audio_config_t outputConfig = mixes[i].mFormat;
- audio_config_t inputConfig = mixes[i].mFormat;
- // NOTE: audio flinger mixer does not support mono output: configure remote submix HAL in
- // stereo and let audio flinger do the channel conversion if needed.
- outputConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
- inputConfig.channel_mask = AUDIO_CHANNEL_IN_STEREO;
- module->addOutputProfile(address, &outputConfig,
- AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address);
- module->addInputProfile(address, &inputConfig,
- AUDIO_DEVICE_IN_REMOTE_SUBMIX, address);
+ if (mPolicyMixes.registerMix(address, mixes[i], 0 /*output desc*/) != NO_ERROR) {
+ ALOGE(" Error regisering mix %zu for address %s", i, address.string());
+ res = INVALID_OPERATION;
+ break;
+ }
+ audio_config_t outputConfig = mixes[i].mFormat;
+ audio_config_t inputConfig = mixes[i].mFormat;
+ // NOTE: audio flinger mixer does not support mono output: configure remote submix HAL in
+ // stereo and let audio flinger do the channel conversion if needed.
+ outputConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ inputConfig.channel_mask = AUDIO_CHANNEL_IN_STEREO;
+ rSubmixModule->addOutputProfile(address, &outputConfig,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address);
+ rSubmixModule->addInputProfile(address, &inputConfig,
+ AUDIO_DEVICE_IN_REMOTE_SUBMIX, address);
- if (mixes[i].mMixType == MIX_TYPE_PLAYERS) {
- setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- address.string(), "remote-submix");
- } else {
- setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- address.string(), "remote-submix");
+ if (mixes[i].mMixType == MIX_TYPE_PLAYERS) {
+ setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ address.string(), "remote-submix");
+ } else {
+ setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ address.string(), "remote-submix");
+ }
+ } else if ((mixes[i].mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) {
+ ALOGV("registerPolicyMixes() mix %zu of %zu is RENDER", i, mixes.size());
+ String8 address = mixes[i].mDeviceAddress;
+
+ audio_devices_t device = mixes[i].mDeviceType;
+
+ for (size_t j = 0 ; j < mOutputs.size() ; j++) {
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(j);
+ sp<AudioPatch> patch = mAudioPatches.valueFor(desc->getPatchHandle());
+ if ((patch != 0) && (patch->mPatch.num_sinks != 0)
+ && (patch->mPatch.sinks[0].type == AUDIO_PORT_TYPE_DEVICE)
+ && (patch->mPatch.sinks[0].ext.device.type == device)
+ && (patch->mPatch.sinks[0].ext.device.address == address)) {
+
+ if (mPolicyMixes.registerMix(address, mixes[i], desc) != NO_ERROR) {
+ res = INVALID_OPERATION;
+ }
+ break;
+ }
+ }
+
+ if (res != NO_ERROR) {
+ ALOGE(" Error registering mix %zu for device 0x%X addr %s",
+ i,device, address.string());
+ res = INVALID_OPERATION;
+ break;
+ }
}
}
- return NO_ERROR;
+ if (res != NO_ERROR) {
+ unregisterPolicyMixes(mixes);
+ }
+ return res;
}
status_t AudioPolicyManager::unregisterPolicyMixes(Vector<AudioMix> mixes)
{
- sp<HwModule> module;
- for (size_t i = 0; i < mHwModules.size(); i++) {
- if (strcmp(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, mHwModules[i]->mName) == 0 &&
- mHwModules[i]->mHandle != 0) {
- module = mHwModules[i];
- break;
- }
- }
-
- if (module == 0) {
- return INVALID_OPERATION;
- }
-
ALOGV("unregisterPolicyMixes() num mixes %zu", mixes.size());
-
+ status_t res = NO_ERROR;
+ sp<HwModule> rSubmixModule;
+ // examine each mix's route type
for (size_t i = 0; i < mixes.size(); i++) {
- String8 address = mixes[i].mRegistrationId;
+ if ((mixes[i].mRouteFlags & MIX_ROUTE_FLAG_LOOP_BACK) == MIX_ROUTE_FLAG_LOOP_BACK) {
- if (mPolicyMixes.unregisterMix(address) != NO_ERROR) {
- continue;
- }
+ if (rSubmixModule == 0) {
+ for (size_t j = 0; i < mHwModules.size(); j++) {
+ if (strcmp(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, mHwModules[j]->mName) == 0
+ && mHwModules[j]->mHandle != 0) {
+ rSubmixModule = mHwModules[j];
+ break;
+ }
+ }
+ }
+ if (rSubmixModule == 0) {
+ res = INVALID_OPERATION;
+ continue;
+ }
- if (getDeviceConnectionState(AUDIO_DEVICE_IN_REMOTE_SUBMIX, address.string()) ==
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE)
- {
- setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- address.string(), "remote-submix");
- }
+ String8 address = mixes[i].mDeviceAddress;
- if (getDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address.string()) ==
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE)
- {
- setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- address.string(), "remote-submix");
+ if (mPolicyMixes.unregisterMix(address) != NO_ERROR) {
+ res = INVALID_OPERATION;
+ continue;
+ }
+
+ if (getDeviceConnectionState(AUDIO_DEVICE_IN_REMOTE_SUBMIX, address.string()) ==
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
+ setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ address.string(), "remote-submix");
+ }
+ if (getDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address.string()) ==
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
+ setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ address.string(), "remote-submix");
+ }
+ rSubmixModule->removeOutputProfile(address);
+ rSubmixModule->removeInputProfile(address);
+
+ } if ((mixes[i].mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) {
+ if (mPolicyMixes.unregisterMix(mixes[i].mDeviceAddress) != NO_ERROR) {
+ res = INVALID_OPERATION;
+ continue;
+ }
}
- module->removeOutputProfile(address);
- module->removeInputProfile(address);
}
- return NO_ERROR;
+ return res;
}
diff --git a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
index 5f4fb22..b4b269a 100644
--- a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
@@ -155,7 +155,7 @@
callbackFormat, params.previewFormat);
res = device->createStream(mCallbackWindow,
params.previewWidth, params.previewHeight, callbackFormat,
- HAL_DATASPACE_JFIF, CAMERA3_STREAM_ROTATION_0, &mCallbackStreamId);
+ HAL_DATASPACE_V0_JFIF, CAMERA3_STREAM_ROTATION_0, &mCallbackStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for callbacks: "
"%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
index 3923853..e97618c 100644
--- a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
@@ -145,7 +145,7 @@
// Create stream for HAL production
res = device->createStream(mCaptureWindow,
params.pictureWidth, params.pictureHeight,
- HAL_PIXEL_FORMAT_BLOB, HAL_DATASPACE_JFIF,
+ HAL_PIXEL_FORMAT_BLOB, HAL_DATASPACE_V0_JFIF,
CAMERA3_STREAM_ROTATION_0, &mCaptureStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for capture: "
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index d4022cd..5779176 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -872,7 +872,7 @@
// Set up initial state for non-Camera.Parameters state variables
videoFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
- videoDataSpace = HAL_DATASPACE_BT709;
+ videoDataSpace = HAL_DATASPACE_V0_BT709;
videoBufferMode = hardware::ICamera::VIDEO_BUFFER_MODE_DATA_CALLBACK_YUV;
playShutterSound = true;
enableFaceDetect = false;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 05c5323..331f10d 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -410,6 +410,31 @@
return measured;
}
+/**
+ * Map Android N dataspace definitions back to Android M definitions, for
+ * use with HALv3.3 or older.
+ *
+ * Only map where correspondences exist, and otherwise preserve the value.
+ */
+android_dataspace Camera3Device::mapToLegacyDataspace(android_dataspace dataSpace) {
+ switch (dataSpace) {
+ case HAL_DATASPACE_V0_SRGB_LINEAR:
+ return HAL_DATASPACE_SRGB_LINEAR;
+ case HAL_DATASPACE_V0_SRGB:
+ return HAL_DATASPACE_SRGB;
+ case HAL_DATASPACE_V0_JFIF:
+ return HAL_DATASPACE_JFIF;
+ case HAL_DATASPACE_V0_BT601_625:
+ return HAL_DATASPACE_BT601_625;
+ case HAL_DATASPACE_V0_BT601_525:
+ return HAL_DATASPACE_BT601_525;
+ case HAL_DATASPACE_V0_BT709:
+ return HAL_DATASPACE_BT709;
+ default:
+ return dataSpace;
+ }
+}
+
ssize_t Camera3Device::getJpegBufferSize(uint32_t width, uint32_t height) const {
// Get max jpeg size (area-wise).
Size maxJpegResolution = getMaxJpegResolution();
@@ -1006,6 +1031,10 @@
if (mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_2) {
streamSetId = CAMERA3_STREAM_SET_ID_INVALID;
}
+ // Use legacy dataspace values for older HALs
+ if (mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_3) {
+ dataSpace = mapToLegacyDataspace(dataSpace);
+ }
if (format == HAL_PIXEL_FORMAT_BLOB) {
ssize_t blobBufferSize;
if (dataSpace != HAL_DATASPACE_DEPTH) {
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 5b1c87e..ba092d0 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -404,6 +404,11 @@
*/
static nsecs_t getMonoToBoottimeOffset();
+ /**
+ * Helper function to map between legacy and new dataspace enums
+ */
+ static android_dataspace mapToLegacyDataspace(android_dataspace dataSpace);
+
struct RequestTrigger {
// Metadata tag number, e.g. android.control.aePrecaptureTrigger
uint32_t metadataTag;
diff --git a/services/medialog/MediaLogService.cpp b/services/medialog/MediaLogService.cpp
index 98a71bb..f85aa13 100644
--- a/services/medialog/MediaLogService.cpp
+++ b/services/medialog/MediaLogService.cpp
@@ -26,6 +26,8 @@
namespace android {
+static const char kDeadlockedString[] = "MediaLogService may be deadlocked\n";
+
void MediaLogService::registerWriter(const sp<IMemory>& shared, size_t size, const char *name)
{
if (IPCThreadState::self()->getCallingUid() != AID_AUDIOSERVER || shared == 0 ||
@@ -54,6 +56,19 @@
}
}
+bool MediaLogService::dumpTryLock(Mutex& mutex)
+{
+ bool locked = false;
+ for (int i = 0; i < kDumpLockRetries; ++i) {
+ if (mutex.tryLock() == NO_ERROR) {
+ locked = true;
+ break;
+ }
+ usleep(kDumpLockSleepUs);
+ }
+ return locked;
+}
+
status_t MediaLogService::dump(int fd, const Vector<String16>& args __unused)
{
// FIXME merge with similar but not identical code at services/audioflinger/ServiceUtilities.cpp
@@ -68,9 +83,22 @@
Vector<NamedReader> namedReaders;
{
- Mutex::Autolock _l(mLock);
+ bool locked = dumpTryLock(mLock);
+
+ // failed to lock - MediaLogService is probably deadlocked
+ if (!locked) {
+ String8 result(kDeadlockedString);
+ if (fd >= 0) {
+ write(fd, result.string(), result.size());
+ } else {
+ ALOGW("%s:", result.string());
+ }
+ return NO_ERROR;
+ }
namedReaders = mNamedReaders;
+ mLock.unlock();
}
+
for (size_t i = 0; i < namedReaders.size(); i++) {
const NamedReader& namedReader = namedReaders[i];
if (fd >= 0) {
diff --git a/services/medialog/MediaLogService.h b/services/medialog/MediaLogService.h
index 2d89a41..c9bf2eb 100644
--- a/services/medialog/MediaLogService.h
+++ b/services/medialog/MediaLogService.h
@@ -43,6 +43,12 @@
uint32_t flags);
private:
+
+ // Internal dump
+ static const int kDumpLockRetries = 50;
+ static const int kDumpLockSleepUs = 20000;
+ static bool dumpTryLock(Mutex& mutex);
+
Mutex mLock;
class NamedReader {
public: