Merge "SoftVorbis: handle flush as well as flush with CSD"
diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp
index 97cf6bf..838dd4a 100644
--- a/camera/ndk/Android.bp
+++ b/camera/ndk/Android.bp
@@ -30,3 +30,42 @@
srcs: ["include/camera/**/*.h"],
license: "NOTICE",
}
+
+cc_library_shared {
+ name: "libcamera2",
+ srcs: [
+ "NdkCameraManager.cpp",
+ "NdkCameraMetadata.cpp",
+ "NdkCameraDevice.cpp",
+ "NdkCaptureRequest.cpp",
+ "NdkCameraCaptureSession.cpp",
+ "impl/ACameraManager.cpp",
+ "impl/ACameraMetadata.cpp",
+ "impl/ACameraDevice.cpp",
+ "impl/ACameraCaptureSession.cpp",
+ ],
+ shared_libs: [
+ "libbinder",
+ "liblog",
+ "libgui",
+ "libutils",
+ "libandroid_runtime",
+ "libcamera_client",
+ "libstagefright_foundation",
+ "libcutils",
+ "libcamera_metadata",
+ "libmediandk",
+ "libnativewindow",
+ ],
+ cflags: [
+ "-fvisibility=hidden",
+ "-DEXPORT=__attribute__ ((visibility (\"default\")))",
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+ export_include_dirs: ["include"],
+ export_shared_lib_headers: [
+ "libnativewindow",
+ ]
+}
diff --git a/camera/ndk/Android.mk b/camera/ndk/Android.mk
index f5ff69d..a5aab07 100644
--- a/camera/ndk/Android.mk
+++ b/camera/ndk/Android.mk
@@ -14,6 +14,8 @@
# limitations under the License.
#
+# TODO(b/118434782): Remove this file and change name of the libcamera2
+# module in the existing Android.bp file to libcamera2ndk.
LOCAL_PATH:= $(call my-dir)
ifneq ($(TARGET_BUILD_PDK), true)
diff --git a/include/soundtrigger/ISoundTrigger.h b/include/soundtrigger/ISoundTrigger.h
index 5fd8eb2..ea1aea6 100644
--- a/include/soundtrigger/ISoundTrigger.h
+++ b/include/soundtrigger/ISoundTrigger.h
@@ -40,6 +40,8 @@
virtual status_t startRecognition(sound_model_handle_t handle,
const sp<IMemory>& dataMemory) = 0;
virtual status_t stopRecognition(sound_model_handle_t handle) = 0;
+ virtual status_t getModelState(sound_model_handle_t handle,
+ sp<IMemory>& eventMemory) = 0;
};
diff --git a/include/soundtrigger/SoundTrigger.h b/include/soundtrigger/SoundTrigger.h
index 7a29e31..dcf9ce8 100644
--- a/include/soundtrigger/SoundTrigger.h
+++ b/include/soundtrigger/SoundTrigger.h
@@ -52,6 +52,7 @@
status_t startRecognition(sound_model_handle_t handle, const sp<IMemory>& dataMemory);
status_t stopRecognition(sound_model_handle_t handle);
+ status_t getModelState(sound_model_handle_t handle, sp<IMemory>& eventMemory);
// BpSoundTriggerClient
virtual void onRecognitionEvent(const sp<IMemory>& eventMemory);
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index eec0392..3a58aa6 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -150,6 +150,8 @@
status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
status_t parseClearEncryptedSizes(off64_t offset, bool isSubsampleEncryption, uint32_t flags);
status_t parseSampleEncryption(off64_t offset);
+ // returns -1 for invalid layer ID
+ int32_t parseHEVCLayerId(const uint8_t *data, size_t size);
struct TrackFragmentHeaderInfo {
enum Flags {
@@ -4935,6 +4937,35 @@
return 0;
}
+int32_t MPEG4Source::parseHEVCLayerId(const uint8_t *data, size_t size) {
+ CHECK(data != nullptr && size >= (mNALLengthSize + 2));
+
+ // HEVC NAL-header (16-bit)
+ // 1 6 6 3
+ // |-|uuuuuu|------|iii|
+ // ^ ^
+ // NAL_type layer_id + 1
+ //
+ // Layer-id is non-zero only for Temporal Sub-layer Access pictures (TSA)
+ enum {
+ TSA_N = 2,
+ TSA_R = 3,
+ STSA_N = 4,
+ STSA_R = 5,
+ };
+
+ data += mNALLengthSize;
+ uint16_t nalHeader = data[0] << 8 | data[1];
+
+ uint16_t nalType = (nalHeader >> 9) & 0x3Fu;
+ if (nalType == TSA_N || nalType == TSA_R || nalType == STSA_N || nalType == STSA_R) {
+ int32_t layerIdPlusOne = nalHeader & 0x7u;
+ ALOGD_IF(layerIdPlusOne == 0, "got layerId 0 for TSA picture");
+ return layerIdPlusOne - 1;
+ }
+ return 0;
+}
+
status_t MPEG4Source::read(
MediaBufferBase **out, const ReadOptions *options) {
Mutex::Autolock autoLock(mLock);
@@ -5368,6 +5399,12 @@
uint32_t layerId = FindAVCLayerId(
(const uint8_t *)mBuffer->data(), mBuffer->range_length());
mBuffer->meta_data().setInt32(kKeyTemporalLayerId, layerId);
+ } else if (mIsHEVC) {
+ int32_t layerId = parseHEVCLayerId(
+ (const uint8_t *)mBuffer->data(), mBuffer->range_length());
+ if (layerId >= 0) {
+ mBuffer->meta_data().setInt32(kKeyTemporalLayerId, layerId);
+ }
}
if (isSyncSample) {
@@ -5566,6 +5603,12 @@
uint32_t layerId = FindAVCLayerId(
(const uint8_t *)mBuffer->data(), mBuffer->range_length());
mBuffer->meta_data().setInt32(kKeyTemporalLayerId, layerId);
+ } else if (mIsHEVC) {
+ int32_t layerId = parseHEVCLayerId(
+ (const uint8_t *)mBuffer->data(), mBuffer->range_length());
+ if (layerId >= 0) {
+ mBuffer->meta_data().setInt32(kKeyTemporalLayerId, layerId);
+ }
}
if (isSyncSample) {
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index 2ae9b5a..a52ccb1 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -987,11 +987,10 @@
AMediaFormat_setBuffer(mMeta, AMEDIAFORMAT_KEY_CSD_0, data, size);
AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_SAMPLE_RATE, kOpusSampleRate);
AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, mChannelCount);
- // are these actually used anywhere?
- // (they are kKeyOpusSeekPreRoll and kKeyOpusCodecDelay respectively)
- AMediaFormat_setInt64(mMeta, AMEDIAFORMAT_KEY_CSD_2, kOpusSeekPreRollUs * 1000 /* = 80 ms*/);
- AMediaFormat_setInt64(mMeta, AMEDIAFORMAT_KEY_CSD_1,
- mCodecDelay /* sample/s */ * 1000000000ll / kOpusSampleRate);
+ int64_t codecdelay = mCodecDelay /* sample/s */ * 1000000000ll / kOpusSampleRate;
+ AMediaFormat_setBuffer(mMeta, AMEDIAFORMAT_KEY_CSD_1, &codecdelay, sizeof(codecdelay));
+ int64_t preroll = kOpusSeekPreRollUs * 1000 /* = 80 ms*/;
+ AMediaFormat_setBuffer(mMeta, AMEDIAFORMAT_KEY_CSD_2, &preroll, sizeof(preroll));
return AMEDIA_OK;
}
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index c86d4ce..8b35a85 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -399,9 +399,10 @@
}
break;
case TRANSFER_CALLBACK:
+ case TRANSFER_SYNC_NOTIF_CALLBACK:
if (cbf == NULL || sharedBuffer != 0) {
- ALOGE("%s(): Transfer type TRANSFER_CALLBACK but cbf == NULL || sharedBuffer != 0",
- __func__);
+ ALOGE("%s(): Transfer type %s but cbf == NULL || sharedBuffer != 0",
+ convertTransferToText(transferType), __func__);
status = BAD_VALUE;
goto exit;
}
@@ -1406,6 +1407,7 @@
MEDIA_CASE_ENUM(TRANSFER_OBTAIN);
MEDIA_CASE_ENUM(TRANSFER_SYNC);
MEDIA_CASE_ENUM(TRANSFER_SHARED);
+ MEDIA_CASE_ENUM(TRANSFER_SYNC_NOTIF_CALLBACK);
default:
return "UNRECOGNIZED";
}
@@ -1438,7 +1440,8 @@
// use case 3: obtain/release mode
(mTransfer == TRANSFER_OBTAIN) ||
// use case 4: synchronous write
- ((mTransfer == TRANSFER_SYNC) && mThreadCanCallJava);
+ ((mTransfer == TRANSFER_SYNC || mTransfer == TRANSFER_SYNC_NOTIF_CALLBACK)
+ && mThreadCanCallJava);
bool fastAllowed = sharedBuffer || transferAllowed;
if (!fastAllowed) {
@@ -1795,7 +1798,7 @@
ssize_t AudioTrack::write(const void* buffer, size_t userSize, bool blocking)
{
- if (mTransfer != TRANSFER_SYNC) {
+ if (mTransfer != TRANSFER_SYNC && mTransfer != TRANSFER_SYNC_NOTIF_CALLBACK) {
return INVALID_OPERATION;
}
@@ -1846,7 +1849,17 @@
if (written > 0) {
mFramesWritten += written / mFrameSize;
+
+ if (mTransfer == TRANSFER_SYNC_NOTIF_CALLBACK) {
+ const sp<AudioTrackThread> t = mAudioTrackThread;
+ if (t != 0) {
+ // causes wake up of the playback thread, that will callback the client for
+ // more data (with EVENT_CAN_WRITE_MORE_DATA) in processAudioBuffer()
+ t->wake();
+ }
+ }
}
+
return written;
}
@@ -2100,8 +2113,8 @@
if (ns < 0) ns = 0;
}
- // If not supplying data by EVENT_MORE_DATA, then we're done
- if (mTransfer != TRANSFER_CALLBACK) {
+ // If not supplying data by EVENT_MORE_DATA or EVENT_CAN_WRITE_MORE_DATA, then we're done
+ if (mTransfer != TRANSFER_CALLBACK && mTransfer != TRANSFER_SYNC_NOTIF_CALLBACK) {
return ns;
}
@@ -2163,7 +2176,13 @@
}
size_t reqSize = audioBuffer.size;
- mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
+ if (mTransfer == TRANSFER_SYNC_NOTIF_CALLBACK) {
+ // when notifying client it can write more data, pass the total size that can be
+ // written in the next write() call, since it's not passed through the callback
+ audioBuffer.size += nonContig;
+ }
+ mCbf(mTransfer == TRANSFER_CALLBACK ? EVENT_MORE_DATA : EVENT_CAN_WRITE_MORE_DATA,
+ mUserData, &audioBuffer);
size_t writtenSize = audioBuffer.size;
// Sanity check on returned size
@@ -2174,6 +2193,14 @@
}
if (writtenSize == 0) {
+ if (mTransfer == TRANSFER_SYNC_NOTIF_CALLBACK) {
+ // The callback EVENT_CAN_WRITE_MORE_DATA was processed in the JNI of
+ // android.media.AudioTrack. The JNI is not using the callback to provide data,
+ // it only signals to the Java client that it can provide more data, which
+ // this track is read to accept now.
+ // The playback thread will be awaken at the next ::write()
+ return NS_WHENEVER;
+ }
// The callback is done filling buffers
// Keep this thread going to handle timed events and
// still try to get more data in intervals of WAIT_PERIOD_MS
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index c5105af..4b84fd1 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -74,6 +74,8 @@
// in the mapping from frame position to presentation time.
// See AudioTimestamp for the information included with event.
#endif
+ EVENT_CAN_WRITE_MORE_DATA = 9,// Notification that more data can be given by write()
+ // This event only occurs for TRANSFER_SYNC_NOTIF_CALLBACK.
};
/* Client should declare a Buffer and pass the address to obtainBuffer()
@@ -153,6 +155,7 @@
TRANSFER_OBTAIN, // call obtainBuffer() and releaseBuffer()
TRANSFER_SYNC, // synchronous write()
TRANSFER_SHARED, // shared memory
+ TRANSFER_SYNC_NOTIF_CALLBACK, // synchronous write(), notif EVENT_CAN_WRITE_MORE_DATA
};
/* Constructs an uninitialized AudioTrack. No connection with
@@ -295,6 +298,8 @@
* Parameters not listed in the AudioTrack constructors above:
*
* threadCanCallJava: Whether callbacks are made from an attached thread and thus can call JNI.
+ * Only set to true when AudioTrack object is used for a java android.media.AudioTrack
+ * in its JNI code.
*
* Internal state post condition:
* (mStreamType == AUDIO_STREAM_DEFAULT) implies this AudioTrack has valid attributes
diff --git a/media/libmedia/include/media/DataSourceDesc.h b/media/libmedia/include/media/DataSourceDesc.h
index c190261..4336767 100644
--- a/media/libmedia/include/media/DataSourceDesc.h
+++ b/media/libmedia/include/media/DataSourceDesc.h
@@ -30,6 +30,11 @@
// A binder interface for implementing a stagefright DataSource remotely.
struct DataSourceDesc : public RefBase {
public:
+ // intentionally less than INT64_MAX
+ // keep consistent with JAVA code
+ static const int64_t kMaxTimeMs = 0x7ffffffffffffffll / 1000;
+ static const int64_t kMaxTimeUs = kMaxTimeMs * 1000;
+
enum {
/* No data source has been set yet */
TYPE_NONE = 0,
diff --git a/media/libmedia/include/media/mediametadataretriever.h b/media/libmedia/include/media/mediametadataretriever.h
index cdef637..1e5fa07 100644
--- a/media/libmedia/include/media/mediametadataretriever.h
+++ b/media/libmedia/include/media/mediametadataretriever.h
@@ -68,6 +68,9 @@
METADATA_KEY_VIDEO_FRAME_COUNT = 32,
METADATA_KEY_EXIF_OFFSET = 33,
METADATA_KEY_EXIF_LENGTH = 34,
+ METADATA_KEY_COLOR_STANDARD = 35,
+ METADATA_KEY_COLOR_TRANSFER = 36,
+ METADATA_KEY_COLOR_RANGE = 37,
// Add more here...
};
diff --git a/media/libmediaplayer2/mediaplayer2.cpp b/media/libmediaplayer2/mediaplayer2.cpp
index 3b155c5..480a630 100644
--- a/media/libmediaplayer2/mediaplayer2.cpp
+++ b/media/libmediaplayer2/mediaplayer2.cpp
@@ -404,12 +404,12 @@
return BAD_VALUE;
}
// Microsecond is used in NuPlayer2.
- if (dsd->mStartPositionMs > INT64_MAX / 1000) {
- dsd->mStartPositionMs = INT64_MAX / 1000;
+ if (dsd->mStartPositionMs > DataSourceDesc::kMaxTimeMs) {
+ dsd->mStartPositionMs = DataSourceDesc::kMaxTimeMs;
ALOGW("setDataSource, start poistion clamped to %lld ms", (long long)dsd->mStartPositionMs);
}
- if (dsd->mEndPositionMs > INT64_MAX / 1000) {
- dsd->mEndPositionMs = INT64_MAX / 1000;
+ if (dsd->mEndPositionMs > DataSourceDesc::kMaxTimeMs) {
+ dsd->mEndPositionMs = DataSourceDesc::kMaxTimeMs;
ALOGW("setDataSource, end poistion clamped to %lld ms", (long long)dsd->mStartPositionMs);
}
ALOGV("setDataSource type(%d), srcId(%lld)", dsd->mType, (long long)dsd->mId);
diff --git a/media/libmediaplayer2/nuplayer2/GenericSource2.cpp b/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
index 6056ad9..f795478 100644
--- a/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
+++ b/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
@@ -79,6 +79,7 @@
void NuPlayer2::GenericSource2::resetDataSource() {
ALOGV("resetDataSource");
+ mDisconnected = false;
mUri.clear();
mUriHeaders.clear();
if (mFd >= 0) {
@@ -196,7 +197,11 @@
}
sp<AMediaExtractorWrapper> trackExtractor = new AMediaExtractorWrapper(AMediaExtractor_new());
- trackExtractor->setDataSource(mDataSourceWrapper->getAMediaDataSource());
+ if (aSourceWrapper != NULL) {
+ trackExtractor->setDataSource(aSourceWrapper->getAMediaDataSource());
+ } else {
+ trackExtractor->setDataSource(fd, mOffset, mLength);
+ }
const char *mime;
sp<MetaData> meta = convertMediaFormatWrapperToMetaData(trackFormat);
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
index 7b9ff30..bc17d13 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
@@ -1753,8 +1753,13 @@
}
void NuPlayer2::addEndTimeMonitor() {
- sp<AMessage> msg = new AMessage(kWhatEOSMonitor, this);
++mEOSMonitorGeneration;
+
+ if (mCurrentSourceInfo.mEndTimeUs == DataSourceDesc::kMaxTimeUs) {
+ return;
+ }
+
+ sp<AMessage> msg = new AMessage(kWhatEOSMonitor, this);
msg->setInt32("generation", mEOSMonitorGeneration);
mMediaClock->addTimer(msg, mCurrentSourceInfo.mEndTimeUs);
}
@@ -3216,7 +3221,7 @@
mSrcId(0),
mSourceFlags(0),
mStartTimeUs(0),
- mEndTimeUs(INT64_MAX) {
+ mEndTimeUs(DataSourceDesc::kMaxTimeUs) {
}
NuPlayer2::SourceInfo & NuPlayer2::SourceInfo::operator=(const NuPlayer2::SourceInfo &other) {
diff --git a/media/libstagefright/MediaTrack.cpp b/media/libstagefright/MediaTrack.cpp
index 5ad5295..9fbb20e 100644
--- a/media/libstagefright/MediaTrack.cpp
+++ b/media/libstagefright/MediaTrack.cpp
@@ -135,13 +135,13 @@
uint32_t opts = 0;
- if (options->getNonBlocking()) {
+ if (options && options->getNonBlocking()) {
opts |= CMediaTrackReadOptions::NONBLOCKING;
}
int64_t seekPosition = 0;
MediaTrack::ReadOptions::SeekMode seekMode;
- if (options->getSeekTo(&seekPosition, &seekMode)) {
+ if (options && options->getSeekTo(&seekPosition, &seekMode)) {
opts |= SEEK;
opts |= (uint32_t) seekMode;
}
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index e010b3e..610b961 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -132,6 +132,9 @@
{ "date", METADATA_KEY_DATE },
{ "width", METADATA_KEY_VIDEO_WIDTH },
{ "height", METADATA_KEY_VIDEO_HEIGHT },
+ { "colorstandard", METADATA_KEY_COLOR_STANDARD },
+ { "colortransfer", METADATA_KEY_COLOR_TRANSFER },
+ { "colorrange", METADATA_KEY_COLOR_RANGE },
};
static const size_t kNumEntries = sizeof(kKeyMap) / sizeof(kKeyMap[0]);
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index 231d540..1a01350 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -36,6 +36,7 @@
#include <media/stagefright/MediaExtractor.h>
#include <media/stagefright/MediaExtractorFactory.h>
#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
#include <media/CharacterEncodingDetector.h>
namespace android {
@@ -403,6 +404,25 @@
return mMetaData.valueAt(index).string();
}
+void StagefrightMetadataRetriever::parseColorAspects(const sp<MetaData>& meta) {
+ sp<AMessage> format = new AMessage();
+ if (convertMetaDataToMessage(meta, &format) != OK) {
+ return;
+ }
+
+ int32_t standard, transfer, range;
+ if (format->findInt32("color-standard", &standard)
+ && format->findInt32("color-transfer", &transfer)
+ && format->findInt32("color-range", &range)) {
+ ALOGV("found color aspects : standard=%d, transfer=%d, range=%d",
+ standard, transfer, range);
+
+ mMetaData.add(METADATA_KEY_COLOR_STANDARD, String8::format("%d", standard));
+ mMetaData.add(METADATA_KEY_COLOR_TRANSFER, String8::format("%d", transfer));
+ mMetaData.add(METADATA_KEY_COLOR_RANGE, String8::format("%d", range));
+ }
+}
+
void StagefrightMetadataRetriever::parseMetaData() {
sp<MetaData> meta = mExtractor->getMetaData();
@@ -542,6 +562,8 @@
if (!trackMeta->findInt32(kKeyFrameCount, &videoFrameCount)) {
videoFrameCount = 0;
}
+
+ parseColorAspects(trackMeta);
} else if (!strncasecmp("image/", mime, 6)) {
int32_t isPrimary;
if (trackMeta->findInt32(
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 456e2e3..0c6c45b 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -1014,6 +1014,56 @@
msg->setInt32("android._is-hdr", (info & hvcc.kInfoIsHdr) != 0);
}
+ uint32_t isoPrimaries, isoTransfer, isoMatrix, isoRange;
+ if (hvcc.findParam32(kColourPrimaries, &isoPrimaries)
+ && hvcc.findParam32(kTransferCharacteristics, &isoTransfer)
+ && hvcc.findParam32(kMatrixCoeffs, &isoMatrix)
+ && hvcc.findParam32(kVideoFullRangeFlag, &isoRange)) {
+ ALOGV("found iso color aspects : primaris=%d, transfer=%d, matrix=%d, range=%d",
+ isoPrimaries, isoTransfer, isoMatrix, isoRange);
+
+ ColorAspects aspects;
+ ColorUtils::convertIsoColorAspectsToCodecAspects(
+ isoPrimaries, isoTransfer, isoMatrix, isoRange, aspects);
+
+ if (aspects.mPrimaries == ColorAspects::PrimariesUnspecified) {
+ int32_t primaries;
+ if (meta->findInt32(kKeyColorPrimaries, &primaries)) {
+ ALOGV("unspecified primaries found, replaced to %d", primaries);
+ aspects.mPrimaries = static_cast<ColorAspects::Primaries>(primaries);
+ }
+ }
+ if (aspects.mTransfer == ColorAspects::TransferUnspecified) {
+ int32_t transferFunction;
+ if (meta->findInt32(kKeyTransferFunction, &transferFunction)) {
+ ALOGV("unspecified transfer found, replaced to %d", transferFunction);
+ aspects.mTransfer = static_cast<ColorAspects::Transfer>(transferFunction);
+ }
+ }
+ if (aspects.mMatrixCoeffs == ColorAspects::MatrixUnspecified) {
+ int32_t colorMatrix;
+ if (meta->findInt32(kKeyColorMatrix, &colorMatrix)) {
+ ALOGV("unspecified matrix found, replaced to %d", colorMatrix);
+ aspects.mMatrixCoeffs = static_cast<ColorAspects::MatrixCoeffs>(colorMatrix);
+ }
+ }
+ if (aspects.mRange == ColorAspects::RangeUnspecified) {
+ int32_t range;
+ if (meta->findInt32(kKeyColorRange, &range)) {
+ ALOGV("unspecified range found, replaced to %d", range);
+ aspects.mRange = static_cast<ColorAspects::Range>(range);
+ }
+ }
+
+ int32_t standard, transfer, range;
+ if (ColorUtils::convertCodecColorAspectsToPlatformAspects(
+ aspects, &range, &standard, &transfer) == OK) {
+ msg->setInt32("color-standard", standard);
+ msg->setInt32("color-transfer", transfer);
+ msg->setInt32("color-range", range);
+ }
+ }
+
parseHevcProfileLevelFromHvcc((const uint8_t *)data, dataSize, msg);
} else if (meta->findData(kKeyESDS, &type, &data, &size)) {
ESDS esds((const char *)data, size);
diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/libstagefright/foundation/ALooper.cpp
index 9921636..768cbd6 100644
--- a/media/libstagefright/foundation/ALooper.cpp
+++ b/media/libstagefright/foundation/ALooper.cpp
@@ -170,7 +170,9 @@
int64_t whenUs;
if (delayUs > 0) {
- whenUs = GetNowUs() + delayUs;
+ int64_t nowUs = GetNowUs();
+ whenUs = (delayUs > INT64_MAX - nowUs ? INT64_MAX : nowUs + delayUs);
+
} else {
whenUs = GetNowUs();
}
@@ -208,6 +210,9 @@
if (whenUs > nowUs) {
int64_t delayUs = whenUs - nowUs;
+ if (delayUs > INT64_MAX / 1000) {
+ delayUs = INT64_MAX / 1000;
+ }
mQueueChangedCondition.waitRelative(mLock, delayUs * 1000ll);
return true;
diff --git a/media/libstagefright/include/StagefrightMetadataRetriever.h b/media/libstagefright/include/StagefrightMetadataRetriever.h
index a7090ad..c50677a 100644
--- a/media/libstagefright/include/StagefrightMetadataRetriever.h
+++ b/media/libstagefright/include/StagefrightMetadataRetriever.h
@@ -65,6 +65,7 @@
sp<ImageDecoder> mImageDecoder;
int mLastImageIndex;
void parseMetaData();
+ void parseColorAspects(const sp<MetaData>& meta);
// Delete album art and clear metadata.
void clearMetadata();
diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp
index 3dd4248..3b298a9 100644
--- a/media/mtp/MtpPacket.cpp
+++ b/media/mtp/MtpPacket.cpp
@@ -157,7 +157,7 @@
request->endpoint,
request->buffer,
request->buffer_length,
- 0);
+ 1000);
request->actual_length = result;
return result;
}
diff --git a/services/soundtrigger/Android.mk b/services/soundtrigger/Android.mk
index 3c7d29d..65f1a44 100644
--- a/services/soundtrigger/Android.mk
+++ b/services/soundtrigger/Android.mk
@@ -55,6 +55,7 @@
libaudiohal_deathhandler \
android.hardware.soundtrigger@2.0 \
android.hardware.soundtrigger@2.1 \
+ android.hardware.soundtrigger@2.2 \
android.hardware.audio.common@2.0 \
android.hidl.allocator@1.0 \
android.hidl.memory@1.0
diff --git a/services/soundtrigger/SoundTriggerHalHidl.cpp b/services/soundtrigger/SoundTriggerHalHidl.cpp
index adf252e..0f9aa15 100644
--- a/services/soundtrigger/SoundTriggerHalHidl.cpp
+++ b/services/soundtrigger/SoundTriggerHalHidl.cpp
@@ -356,6 +356,50 @@
return hidlReturn;
}
+int SoundTriggerHalHidl::getModelState(sound_model_handle_t handle,
+ struct sound_trigger_recognition_event** event)
+{
+ sp<ISoundTriggerHw> soundtrigger = getService();
+ if (soundtrigger == 0) {
+ return -ENODEV;
+ }
+
+ sp<V2_2_ISoundTriggerHw> soundtrigger_2_2 = toService2_2(soundtrigger);
+ if (soundtrigger_2_2 == 0) {
+ ALOGE("getModelState not supported");
+ return -ENODEV;
+ }
+
+ sp<SoundModel> model = getModel(handle);
+ if (model == 0) {
+ ALOGE("getModelState model not found for handle %u", handle);
+ return -EINVAL;
+ }
+
+ int ret = NO_ERROR;
+ Return<void> hidlReturn;
+ {
+ AutoMutex lock(mHalLock);
+ hidlReturn = soundtrigger_2_2->getModelState(
+ model->mHalHandle,
+ [&](int r, const V2_0_ISoundTriggerHwCallback::RecognitionEvent& halEvent) {
+ ret = r;
+ if (ret != 0) {
+ ALOGE("getModelState returned error code %d", ret);
+ } else {
+ *event = convertRecognitionEventFromHal(&halEvent);
+ }
+ });
+ }
+ if (!hidlReturn.isOk()) {
+ ALOGE("getModelState error %s", hidlReturn.description().c_str());
+ free(*event);
+ *event = nullptr;
+ ret = FAILED_TRANSACTION;
+ }
+ return ret;
+}
+
SoundTriggerHalHidl::SoundTriggerHalHidl(const char *moduleName)
: mModuleName(moduleName), mNextUniqueId(1)
{
@@ -388,6 +432,12 @@
return castResult_2_1.isOk() ? static_cast<sp<V2_1_ISoundTriggerHw>>(castResult_2_1) : nullptr;
}
+sp<V2_2_ISoundTriggerHw> SoundTriggerHalHidl::toService2_2(const sp<ISoundTriggerHw>& s)
+{
+ auto castResult_2_2 = V2_2_ISoundTriggerHw::castFrom(s);
+ return castResult_2_2.isOk() ? static_cast<sp<V2_2_ISoundTriggerHw>>(castResult_2_2) : nullptr;
+}
+
sp<SoundTriggerHalHidl::SoundModel> SoundTriggerHalHidl::getModel(sound_model_handle_t handle)
{
AutoMutex lock(mLock);
diff --git a/services/soundtrigger/SoundTriggerHalHidl.h b/services/soundtrigger/SoundTriggerHalHidl.h
index 0b44ae0..3f4bec3 100644
--- a/services/soundtrigger/SoundTriggerHalHidl.h
+++ b/services/soundtrigger/SoundTriggerHalHidl.h
@@ -27,6 +27,7 @@
#include "SoundTriggerHalInterface.h"
#include <android/hardware/soundtrigger/2.0/types.h>
#include <android/hardware/soundtrigger/2.1/ISoundTriggerHw.h>
+#include <android/hardware/soundtrigger/2.2/ISoundTriggerHw.h>
#include <android/hardware/soundtrigger/2.0/ISoundTriggerHwCallback.h>
#include <android/hardware/soundtrigger/2.1/ISoundTriggerHwCallback.h>
@@ -46,6 +47,8 @@
using V2_1_ISoundTriggerHwCallback =
::android::hardware::soundtrigger::V2_1::ISoundTriggerHwCallback;
using ::android::hidl::memory::V1_0::IMemory;
+using V2_2_ISoundTriggerHw =
+ ::android::hardware::soundtrigger::V2_2::ISoundTriggerHw;
class SoundTriggerHalHidl : public SoundTriggerHalInterface,
public virtual V2_1_ISoundTriggerHwCallback
@@ -92,6 +95,14 @@
*/
virtual int stopAllRecognitions();
+ /* Get the current state of a given model.
+ * Returns 0 or an error code. If successful it also sets indicated the event pointer
+ * and expectes that the caller will free the memory.
+ * Only supported for device api versions SOUND_TRIGGER_DEVICE_API_VERSION_1_2 or above.
+ */
+ virtual int getModelState(sound_model_handle_t handle,
+ struct sound_trigger_recognition_event** event);
+
// ISoundTriggerHwCallback
virtual ::android::hardware::Return<void> recognitionCallback(
const V2_0_ISoundTriggerHwCallback::RecognitionEvent& event, CallbackCookie cookie);
@@ -182,6 +193,7 @@
uint32_t nextUniqueId();
sp<ISoundTriggerHw> getService();
sp<V2_1_ISoundTriggerHw> toService2_1(const sp<ISoundTriggerHw>& s);
+ sp<V2_2_ISoundTriggerHw> toService2_2(const sp<ISoundTriggerHw>& s);
sp<SoundModel> getModel(sound_model_handle_t handle);
sp<SoundModel> removeModel(sound_model_handle_t handle);
diff --git a/services/soundtrigger/SoundTriggerHalInterface.h b/services/soundtrigger/SoundTriggerHalInterface.h
index c083195..076ca23 100644
--- a/services/soundtrigger/SoundTriggerHalInterface.h
+++ b/services/soundtrigger/SoundTriggerHalInterface.h
@@ -71,6 +71,14 @@
*/
virtual int stopAllRecognitions() = 0;
+ /* Get the current state of a given model.
+ * Returns 0 or an error code. If successful it also sets indicated the event pointer
+ * and expectes that the caller will free the memory.
+ * Only supported for device api versions SOUND_TRIGGER_DEVICE_API_VERSION_1_2 or above.
+ */
+ virtual int getModelState(sound_model_handle_t handle,
+ struct sound_trigger_recognition_event** event) = 0;
+
protected:
SoundTriggerHalInterface() {}
};
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
index eb9cd1d..79e9e88 100644
--- a/services/soundtrigger/SoundTriggerHwService.cpp
+++ b/services/soundtrigger/SoundTriggerHwService.cpp
@@ -717,6 +717,40 @@
return NO_ERROR;
}
+status_t SoundTriggerHwService::Module::getModelState(sound_model_handle_t handle,
+ sp<IMemory>& eventMemory)
+{
+ ALOGV("getModelState() model handle %d", handle);
+ if (mHalInterface == 0) {
+ return NO_INIT;
+ }
+ AutoMutex lock(mLock);
+ sp<Model> model = getModel(handle);
+ if (model == 0) {
+ return BAD_VALUE;
+ }
+
+ if (model->mState != Model::STATE_ACTIVE) {
+ return INVALID_OPERATION;
+ }
+
+ if (model->mType != SOUND_MODEL_TYPE_GENERIC) {
+ return BAD_VALUE;
+ }
+
+ struct sound_trigger_recognition_event* event = nullptr;
+ status_t status = mHalInterface->getModelState(handle, &event);
+ if (status == NO_ERROR) {
+ sp<SoundTriggerHwService> service;
+ service = mService.promote();
+ if (service != 0) {
+ eventMemory = service->prepareRecognitionEvent(event);
+ }
+ free(event);
+ }
+ return status;
+}
+
void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event)
{
ALOGV("onCallbackEvent type %d", event->mType);
@@ -1018,6 +1052,22 @@
return module->stopRecognition(handle);
}
+status_t SoundTriggerHwService::ModuleClient::getModelState(sound_model_handle_t handle,
+ sp<IMemory>& eventMemory)
+{
+ ALOGV("getModelState() model handle %d", handle);
+ if (!captureHotwordAllowed(IPCThreadState::self()->getCallingPid(),
+ IPCThreadState::self()->getCallingUid())) {
+ return PERMISSION_DENIED;
+ }
+
+ sp<Module> module = mModule.promote();
+ if (module == 0) {
+ return NO_INIT;
+ }
+ return module->getModelState(handle, eventMemory);
+}
+
void SoundTriggerHwService::ModuleClient::setCaptureState_l(bool active)
{
ALOGV("ModuleClient::setCaptureState_l %d", active);
diff --git a/services/soundtrigger/SoundTriggerHwService.h b/services/soundtrigger/SoundTriggerHwService.h
index 708fc98..c222cd9 100644
--- a/services/soundtrigger/SoundTriggerHwService.h
+++ b/services/soundtrigger/SoundTriggerHwService.h
@@ -122,6 +122,8 @@
virtual status_t startRecognition(sound_model_handle_t handle,
const sp<IMemory>& dataMemory);
virtual status_t stopRecognition(sound_model_handle_t handle);
+ virtual status_t getModelState(sound_model_handle_t handle,
+ sp<IMemory>& eventMemory);
sp<SoundTriggerHalInterface> halInterface() const { return mHalInterface; }
struct sound_trigger_module_descriptor descriptor() { return mDescriptor; }
@@ -169,6 +171,8 @@
virtual status_t startRecognition(sound_model_handle_t handle,
const sp<IMemory>& dataMemory);
virtual status_t stopRecognition(sound_model_handle_t handle);
+ virtual status_t getModelState(sound_model_handle_t handle,
+ sp<IMemory>& eventMemory);
virtual status_t dump(int fd, const Vector<String16>& args);
diff --git a/soundtrigger/ISoundTrigger.cpp b/soundtrigger/ISoundTrigger.cpp
index 25332a4..32882f1 100644
--- a/soundtrigger/ISoundTrigger.cpp
+++ b/soundtrigger/ISoundTrigger.cpp
@@ -32,6 +32,7 @@
UNLOAD_SOUND_MODEL,
START_RECOGNITION,
STOP_RECOGNITION,
+ GET_MODEL_STATE,
};
class BpSoundTrigger: public BpInterface<ISoundTrigger>
@@ -113,6 +114,22 @@
return status;
}
+ virtual status_t getModelState(sound_model_handle_t handle,
+ sp<IMemory>& eventMemory)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
+ data.write(&handle, sizeof(sound_model_handle_t));
+ status_t status = remote()->transact(GET_MODEL_STATE, data, &reply);
+ if (status == NO_ERROR) {
+ status = (status_t)reply.readInt32();
+ if (status == NO_ERROR) {
+ eventMemory = interface_cast<IMemory>(reply.readStrongBinder());
+ }
+ }
+ return status;
+ }
+
};
IMPLEMENT_META_INTERFACE(SoundTrigger, "android.hardware.ISoundTrigger");
@@ -169,6 +186,24 @@
reply->writeInt32(status);
return NO_ERROR;
}
+ case GET_MODEL_STATE: {
+ CHECK_INTERFACE(ISoundTrigger, data, reply);
+ sound_model_handle_t handle;
+ status_t status = UNKNOWN_ERROR;
+ status_t ret = data.read(&handle, sizeof(sound_model_handle_t));
+ if (ret == NO_ERROR) {
+ sp<IMemory> eventMemory;
+ status = getModelState(handle, eventMemory);
+ if (eventMemory != NULL) {
+ ret = reply->writeStrongBinder(
+ IInterface::asBinder(eventMemory));
+ } else {
+ ret = NO_MEMORY;
+ }
+ }
+ reply->writeInt32(status);
+ return ret;
+ }
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/soundtrigger/SoundTrigger.cpp b/soundtrigger/SoundTrigger.cpp
index 289b7b1..bb0650f 100644
--- a/soundtrigger/SoundTrigger.cpp
+++ b/soundtrigger/SoundTrigger.cpp
@@ -188,6 +188,16 @@
return mISoundTrigger->stopRecognition(handle);
}
+status_t SoundTrigger::getModelState(sound_model_handle_t handle,
+ sp<IMemory>& eventMemory)
+{
+ Mutex::Autolock _l(mLock);
+ if (mISoundTrigger == 0) {
+ return NO_INIT;
+ }
+ return mISoundTrigger->getModelState(handle, eventMemory);
+}
+
// BpSoundTriggerClient
void SoundTrigger::onRecognitionEvent(const sp<IMemory>& eventMemory)
{