Merge "aaudio test: add -s to test_steal_exclusive" into rvc-dev
diff --git a/apex/testing/Android.bp b/apex/testing/Android.bp
index 376d3e4..a04ab3f 100644
--- a/apex/testing/Android.bp
+++ b/apex/testing/Android.bp
@@ -17,6 +17,7 @@
manifest: "test_manifest.json",
file_contexts: ":com.android.media-file_contexts",
defaults: ["com.android.media-defaults"],
+ prebuilts: ["sdkinfo_45"],
installable: false,
}
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 0eaa503..e6bb2e1 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -1159,7 +1159,7 @@
readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, mode, &actualTimeUs);
if (mode != MediaPlayerSeekMode::SEEK_CLOSEST) {
- seekTimeUs = actualTimeUs;
+ seekTimeUs = std::max<int64_t>(0, actualTimeUs);
}
mVideoLastDequeueTimeUs = actualTimeUs;
}
diff --git a/media/libstagefright/ACodecBufferChannel.cpp b/media/libstagefright/ACodecBufferChannel.cpp
index fa13f32..88b15ae 100644
--- a/media/libstagefright/ACodecBufferChannel.cpp
+++ b/media/libstagefright/ACodecBufferChannel.cpp
@@ -22,11 +22,14 @@
#include <C2Buffer.h>
+#include <Codec2BufferUtils.h>
+
#include <android/hardware/cas/native/1.0/IDescrambler.h>
#include <android/hardware/drm/1.0/types.h>
#include <binder/MemoryDealer.h>
#include <hidlmemory/FrameworkUtils.h>
#include <media/openmax/OMX_Core.h>
+#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/MediaCodec.h>
@@ -91,15 +94,27 @@
}
status_t ACodecBufferChannel::queueInputBuffer(const sp<MediaCodecBuffer> &buffer) {
- if (mDealer != nullptr) {
- return -ENOSYS;
- }
std::shared_ptr<const std::vector<const BufferInfo>> array(
std::atomic_load(&mInputBuffers));
BufferInfoIterator it = findClientBuffer(array, buffer);
if (it == array->end()) {
return -ENOENT;
}
+ if (it->mClientBuffer != it->mCodecBuffer) {
+ // Copy metadata from client to codec buffer.
+ it->mCodecBuffer->meta()->clear();
+ int64_t timeUs;
+ CHECK(it->mClientBuffer->meta()->findInt64("timeUs", &timeUs));
+ it->mCodecBuffer->meta()->setInt64("timeUs", timeUs);
+ int32_t eos;
+ if (it->mClientBuffer->meta()->findInt32("eos", &eos)) {
+ it->mCodecBuffer->meta()->setInt32("eos", eos);
+ }
+ int32_t csd;
+ if (it->mClientBuffer->meta()->findInt32("csd", &csd)) {
+ it->mCodecBuffer->meta()->setInt32("csd", csd);
+ }
+ }
ALOGV("queueInputBuffer #%d", it->mBufferId);
sp<AMessage> msg = mInputBufferFilled->dup();
msg->setObject("buffer", it->mCodecBuffer);
@@ -267,16 +282,30 @@
}
C2ConstLinearBlock block{c2Buffer->data().linearBlocks().front()};
C2ReadView view{block.map().get()};
- if (view.capacity() > buffer->capacity()) {
- return -ENOSYS;
- }
- memcpy(buffer->base(), view.data(), view.capacity());
- buffer->setRange(0, view.capacity());
+ size_t copyLength = std::min(size_t(view.capacity()), buffer->capacity());
+ ALOGV_IF(view.capacity() > buffer->capacity(),
+ "view.capacity() = %zu, buffer->capacity() = %zu",
+ view.capacity(), buffer->capacity());
+ memcpy(buffer->base(), view.data(), copyLength);
+ buffer->setRange(0, copyLength);
break;
}
case C2BufferData::GRAPHIC: {
- // TODO
- return -ENOSYS;
+ sp<ABuffer> imageData;
+ if (!buffer->format()->findBuffer("image-data", &imageData)) {
+ return -ENOSYS;
+ }
+ if (c2Buffer->data().graphicBlocks().size() != 1u) {
+ return -ENOSYS;
+ }
+ C2ConstGraphicBlock block{c2Buffer->data().graphicBlocks().front()};
+ const C2GraphicView view{block.map().get()};
+ status_t err = ImageCopy(
+ buffer->base(), (const MediaImage2 *)(imageData->base()), view);
+ if (err != OK) {
+ return err;
+ }
+ break;
}
case C2BufferData::LINEAR_CHUNKS: [[fallthrough]];
case C2BufferData::GRAPHIC_CHUNKS: [[fallthrough]];
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 3e49bae..3bccb7b 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -273,6 +273,7 @@
"libutils",
"libmedia_helper",
"libsfplugin_ccodec",
+ "libsfplugin_ccodec_utils",
"libstagefright_codecbase",
"libstagefright_foundation",
"libstagefright_omx_utils",
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 7f5e762..983fa56 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -2496,6 +2496,18 @@
}
break;
}
+ if (!mLeftover.empty()) {
+ ssize_t index = dequeuePortBuffer(kPortIndexInput);
+ CHECK_GE(index, 0);
+
+ status_t err = handleLeftover(index);
+ if (err != OK) {
+ setStickyError(err);
+ postActivityNotificationIfPossible();
+ cancelPendingDequeueOperations();
+ }
+ break;
+ }
if (mFlags & kFlagIsAsync) {
if (!mHaveInputSurface) {
@@ -3185,7 +3197,15 @@
break;
}
- status_t err = onQueueInputBuffer(msg);
+ status_t err = UNKNOWN_ERROR;
+ if (!mLeftover.empty()) {
+ mLeftover.push_back(msg);
+ size_t index;
+ msg->findSize("index", &index);
+ err = handleLeftover(index);
+ } else {
+ err = onQueueInputBuffer(msg);
+ }
PostReplyWithError(replyID, err);
break;
@@ -3472,8 +3492,8 @@
sp<hardware::HidlMemory> memory;
size_t offset = 0;
- if ((mFlags & kFlagUseBlockModel) && mOwnerName.startsWith("codec2::")) {
- if (mCrypto) {
+ if (mFlags & kFlagUseBlockModel) {
+ if (hasCryptoOrDescrambler()) {
constexpr size_t kInitialDealerCapacity = 1048576; // 1MB
thread_local sp<MemoryDealer> sDealer = new MemoryDealer(
kInitialDealerCapacity, "CSD(1MB)");
@@ -3598,6 +3618,9 @@
CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
Mutex::Autolock al(mBufferLock);
+ if (portIndex == kPortIndexInput) {
+ mLeftover.clear();
+ }
for (size_t i = 0; i < mPortBuffers[portIndex].size(); ++i) {
BufferInfo *info = &mPortBuffers[portIndex][i];
@@ -3728,7 +3751,26 @@
err = mBufferChannel->attachEncryptedBuffer(
memory, (mFlags & kFlagIsSecure), key, iv, mode, pattern,
offset, subSamples, numSubSamples, buffer);
+ } else {
+ err = UNKNOWN_ERROR;
}
+
+ if (err == OK && !buffer->asC2Buffer()
+ && c2Buffer && c2Buffer->data().type() == C2BufferData::LINEAR) {
+ C2ConstLinearBlock block{c2Buffer->data().linearBlocks().front()};
+ if (block.size() > buffer->size()) {
+ C2ConstLinearBlock leftover = block.subBlock(
+ block.offset() + buffer->size(), block.size() - buffer->size());
+ sp<WrapperObject<std::shared_ptr<C2Buffer>>> obj{
+ new WrapperObject<std::shared_ptr<C2Buffer>>{
+ C2Buffer::CreateLinearBuffer(leftover)}};
+ msg->setObject("c2buffer", obj);
+ mLeftover.push_front(msg);
+ // Not sending EOS if we have leftovers
+ flags &= ~BUFFER_FLAG_EOS;
+ }
+ }
+
offset = buffer->offset();
size = buffer->size();
if (err != OK) {
@@ -3793,6 +3835,16 @@
return err;
}
+status_t MediaCodec::handleLeftover(size_t index) {
+ if (mLeftover.empty()) {
+ return OK;
+ }
+ sp<AMessage> msg = mLeftover.front();
+ mLeftover.pop_front();
+ msg->setSize("index", index);
+ return onQueueInputBuffer(msg);
+}
+
//static
size_t MediaCodec::CreateFramesRenderedMessage(
const std::list<FrameRenderTracker::Info> &done, sp<AMessage> &msg) {
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 7f308c0..02ab4c0 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -515,6 +515,9 @@
class ReleaseSurface;
std::unique_ptr<ReleaseSurface> mReleaseSurface;
+ std::list<sp<AMessage>> mLeftover;
+ status_t handleLeftover(size_t index);
+
sp<BatteryChecker> mBatteryChecker;
void statsBufferSent(int64_t presentationUs);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 849c050..024168b 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -7366,8 +7366,10 @@
// Update server timestamp with server stats
// systemTime() is optional if the hardware supports timestamps.
- mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER] += framesRead;
- mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = lastIoEndNs;
+ if (framesRead >= 0) {
+ mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER] += framesRead;
+ mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = lastIoEndNs;
+ }
// Update server timestamp with kernel stats
if (mPipeSource.get() == nullptr /* don't obtain for FastCapture, could block */) {
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index b00a2d9..deeec7e 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -1777,13 +1777,6 @@
mStatusChanged.broadcast();
}
-void Camera3Device::pauseStateNotify(bool enable) {
- Mutex::Autolock il(mInterfaceLock);
- Mutex::Autolock l(mLock);
-
- mPauseStateNotify = enable;
-}
-
// Pause to reconfigure
status_t Camera3Device::internalPauseAndWaitLocked(nsecs_t maxExpectedDuration) {
if (mRequestThread.get() != nullptr) {
@@ -2359,7 +2352,7 @@
return false;
}
-bool Camera3Device::reconfigureCamera(const CameraMetadata& sessionParams) {
+bool Camera3Device::reconfigureCamera(const CameraMetadata& sessionParams, int clientStatusId) {
ATRACE_CALL();
bool ret = false;
@@ -2373,7 +2366,16 @@
return true;
}
- auto rc = internalPauseAndWaitLocked(maxExpectedDuration);
+ status_t rc = NO_ERROR;
+ bool markClientActive = false;
+ if (mStatus == STATUS_ACTIVE) {
+ markClientActive = true;
+ mPauseStateNotify = true;
+ mStatusTracker->markComponentIdle(clientStatusId, Fence::NO_FENCE);
+
+ rc = internalPauseAndWaitLocked(maxExpectedDuration);
+ }
+
if (rc == NO_ERROR) {
mNeedConfig = true;
rc = configureStreamsLocked(mOperatingMode, sessionParams, /*notifyRequestThread*/ false);
@@ -2401,6 +2403,10 @@
ALOGE("%s: Failed to pause streaming: %d", __FUNCTION__, rc);
}
+ if (markClientActive) {
+ mStatusTracker->markComponentActive(clientStatusId);
+ }
+
return ret;
}
@@ -4277,22 +4283,11 @@
}
if (res == OK) {
- sp<StatusTracker> statusTracker = mStatusTracker.promote();
- if (statusTracker != 0) {
- sp<Camera3Device> parent = mParent.promote();
- if (parent != nullptr) {
- parent->pauseStateNotify(true);
- }
-
- statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
-
- if (parent != nullptr) {
- mReconfigured |= parent->reconfigureCamera(mLatestSessionParams);
- }
-
- statusTracker->markComponentActive(mStatusId);
- setPaused(false);
+ sp<Camera3Device> parent = mParent.promote();
+ if (parent != nullptr) {
+ mReconfigured |= parent->reconfigureCamera(mLatestSessionParams, mStatusId);
}
+ setPaused(false);
if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
mNextRequests[0].captureRequest->mInputStream->restoreConfiguredState();
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index c059f55..2069841 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -638,17 +638,10 @@
const SurfaceMap &surfaceMap);
/**
- * Pause state updates to the client application. Needed to mask out idle/active
- * transitions during internal reconfigure
- */
- void pauseStateNotify(bool enable);
-
- /**
* Internally re-configure camera device using new session parameters.
- * This will get triggered by the request thread. Be sure to call
- * pauseStateNotify(true) before going idle in the requesting location.
+ * This will get triggered by the request thread.
*/
- bool reconfigureCamera(const CameraMetadata& sessionParams);
+ bool reconfigureCamera(const CameraMetadata& sessionParams, int clientStatusId);
/**
* Return true in case of any output or input abandoned streams,