blob: 284ad05b23efe74ad92deb99eb3af061dbfd0f8c [file] [log] [blame]
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "VirtualCameraSessionContext.h"
#include <memory>
#include <mutex>
#include <unordered_set>
#include "VirtualCameraStream.h"
#include "aidl/android/hardware/camera/device/StreamConfiguration.h"
namespace android {
namespace companion {
namespace virtualcamera {
using ::aidl::android::hardware::camera::device::BufferCache;
using ::aidl::android::hardware::camera::device::Stream;
using ::aidl::android::hardware::camera::device::StreamBuffer;
using ::aidl::android::hardware::camera::device::StreamConfiguration;
bool VirtualCameraSessionContext::initializeStream(
const ::aidl::android::hardware::camera::device::Stream& stream) {
std::lock_guard<std::mutex> lock(mLock);
auto s = std::make_unique<VirtualCameraStream>(stream);
const auto& [_, newlyInserted] = mStreams.emplace(
std::piecewise_construct, std::forward_as_tuple(stream.id),
std::forward_as_tuple(std::move(s)));
return newlyInserted;
}
void VirtualCameraSessionContext::closeAllStreams() {
std::lock_guard<std::mutex> lock(mLock);
mStreams.clear();
}
bool VirtualCameraSessionContext::importBuffersFromCaptureRequest(
const ::aidl::android::hardware::camera::device::CaptureRequest&
captureRequest) {
std::lock_guard<std::mutex> lock(mLock);
for (const StreamBuffer& buffer : captureRequest.outputBuffers) {
auto it = mStreams.find(buffer.streamId);
if (it == mStreams.end()) {
ALOGE("%s: Cannot import buffer for unknown stream with id %d", __func__,
buffer.streamId);
return false;
}
VirtualCameraStream& stream = *it->second;
if (stream.getHardwareBuffer(buffer.bufferId) != nullptr) {
// This buffer is already imported.
continue;
}
if (stream.importBuffer(buffer) == nullptr) {
ALOGE("%s: Failed to import buffer %" PRId64 " for streamId %d", __func__,
buffer.bufferId, buffer.streamId);
return false;
}
}
return true;
}
void VirtualCameraSessionContext::removeBufferCaches(
const std::vector<BufferCache>& cachesToRemove) {
std::lock_guard<std::mutex> lock(mLock);
for (const auto& bufferCache : cachesToRemove) {
auto it = mStreams.find(bufferCache.streamId);
if (it == mStreams.end()) {
ALOGE("%s: Ask to remove buffer %" PRId64 " from unknown stream %d",
__func__, bufferCache.bufferId, bufferCache.streamId);
continue;
}
if (it->second->removeBuffer(bufferCache.bufferId)) {
ALOGD("%s: Successfully removed buffer %" PRId64
" from cache of stream %d",
__func__, bufferCache.bufferId, bufferCache.streamId);
} else {
ALOGE("%s: Failed to remove buffer %" PRId64 " from cache of stream %d",
__func__, bufferCache.bufferId, bufferCache.streamId);
}
}
}
void VirtualCameraSessionContext::removeStreamsNotInStreamConfiguration(
const StreamConfiguration& streamConfiguration) {
std::unordered_set<int> newConfigurationStreamIds;
for (const Stream& stream : streamConfiguration.streams) {
newConfigurationStreamIds.insert(stream.id);
}
std::lock_guard<std::mutex> lock(mLock);
for (auto it = mStreams.begin(); it != mStreams.end();) {
if (newConfigurationStreamIds.find(it->first) ==
newConfigurationStreamIds.end()) {
ALOGV(
"Disposing of stream %d, since it is not referenced by new "
"configuration.",
it->first);
it = mStreams.erase(it);
} else {
++it;
}
}
}
std::optional<Stream> VirtualCameraSessionContext::getStreamConfig(
int streamId) const {
std::lock_guard<std::mutex> lock(mLock);
auto it = mStreams.find(streamId);
if (it == mStreams.end()) {
ALOGE("%s: StreamBuffer references buffer of unknown streamId %d", __func__,
streamId);
return std::optional<Stream>();
}
return {it->second->getStreamConfig()};
}
std::shared_ptr<AHardwareBuffer> VirtualCameraSessionContext::fetchHardwareBuffer(
const int streamId, const int bufferId) const {
std::lock_guard<std::mutex> lock(mLock);
auto it = mStreams.find(streamId);
if (it == mStreams.end()) {
ALOGE("%s: StreamBuffer references buffer of unknown streamId %d", __func__,
streamId);
return nullptr;
}
return it->second->getHardwareBuffer(bufferId);
}
std::shared_ptr<EglFrameBuffer>
VirtualCameraSessionContext::fetchOrCreateEglFramebuffer(
const EGLDisplay eglDisplay, const int streamId, const int bufferId) {
std::lock_guard<std::mutex> lock(mLock);
auto it = mStreams.find(streamId);
if (it == mStreams.end()) {
ALOGE("%s: StreamBuffer references buffer of unknown streamId %d", __func__,
streamId);
return nullptr;
}
return it->second->getEglFrameBuffer(eglDisplay, bufferId);
}
std::set<int> VirtualCameraSessionContext::getStreamIds() const {
std::set<int> result;
std::lock_guard<std::mutex> lock(mLock);
for (const auto& [streamId, _] : mStreams) {
result.insert(streamId);
}
return result;
}
} // namespace virtualcamera
} // namespace companion
} // namespace android