blob: 2b5c18917eb965817971667da3a638a611030c53 [file] [log] [blame]
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -07001/*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#pragma once
17
18#include <chrono>
19#include <condition_variable>
20#include <limits>
21#include <memory>
22#include <mutex>
23#include <thread>
24
25#include <media/HeadTrackingProcessor.h>
26#include <media/SensorPoseProvider.h>
27
28namespace android {
29
30/**
31 * This class encapsulates the logic for pose processing, intended for driving a spatializer effect.
32 * This includes integration with the Sensor sub-system for retrieving sensor data, doing all the
33 * necessary processing, etc.
34 *
35 * Calculations happen on a dedicated thread and published to the client via the Listener interface.
36 * A calculation may be triggered in one of two ways:
37 * - By calling calculateAsync() - calculation will be kicked off in the background.
38 * - By setting a timeout in the ctor, a calculation will be triggered after the timeout elapsed
39 * from the last calculateAsync() call.
40 *
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -070041 * This class is thread-safe.
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070042 */
43class SpatializerPoseController : private media::SensorPoseProvider::Listener {
44 public:
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -070045 static constexpr int32_t INVALID_SENSOR = media::SensorPoseProvider::INVALID_HANDLE;
46
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070047 /**
48 * Listener interface for getting pose and mode updates.
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -070049 * Methods will always be invoked from a designated thread.
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070050 */
51 class Listener {
52 public:
53 virtual ~Listener() = default;
54
55 virtual void onHeadToStagePose(const media::Pose3f&) = 0;
56 virtual void onActualModeChange(media::HeadTrackingMode) = 0;
57 };
58
59 /**
60 * Ctor.
61 * sensorPeriod determines how often to receive updates from the sensors (input rate).
62 * maxUpdatePeriod determines how often to produce an output when calculateAsync() isn't
63 * invoked.
64 */
65 SpatializerPoseController(Listener* listener, std::chrono::microseconds sensorPeriod,
66 std::chrono::microseconds maxUpdatePeriod);
67
68 /** Dtor. */
69 ~SpatializerPoseController();
70
71 /**
72 * Set the sensor that is to be used for head-tracking.
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -070073 * INVALID_SENSOR can be used to disable head-tracking.
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070074 */
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -070075 void setHeadSensor(int32_t sensor);
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070076
77 /**
78 * Set the sensor that is to be used for screen-tracking.
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -070079 * INVALID_SENSOR can be used to disable screen-tracking.
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070080 */
Ytai Ben-Tsvi9f12f172021-09-23 16:47:25 -070081 void setScreenSensor(int32_t sensor);
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -070082
83 /** Sets the desired head-tracking mode. */
84 void setDesiredMode(media::HeadTrackingMode mode);
85
86 /**
87 * Set the screen-to-stage pose, used in all modes.
88 */
89 void setScreenToStagePose(const media::Pose3f& screenToStage);
90
91 /**
92 * Sets the display orientation.
93 * Orientation is expressed in the angle of rotation from the physical "up" side of the screen
94 * to the logical "up" side of the content displayed the screen. Counterclockwise angles, as
95 * viewed while facing the screen are positive.
96 */
97 void setDisplayOrientation(float physicalToLogicalAngle);
98
99 /**
100 * This causes the current poses for both the head and screen to be considered "center".
101 */
102 void recenter();
103
104 /**
105 * This call triggers the recalculation of the output and the invocation of the relevant
106 * callbacks. This call is async and the callbacks will be triggered shortly after.
107 */
108 void calculateAsync();
109
110 /**
111 * Blocks until calculation and invocation of the respective callbacks has happened at least
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -0700112 * once. Do not call from within callbacks.
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700113 */
114 void waitUntilCalculated();
115
116 private:
117 mutable std::mutex mMutex;
118 Listener* const mListener;
119 const std::chrono::microseconds mSensorPeriod;
Ytai Ben-Tsvi8b6fe3a2021-09-13 15:55:44 -0700120 // Order matters for the following two members to ensure correct destruction.
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700121 std::unique_ptr<media::HeadTrackingProcessor> mProcessor;
Ytai Ben-Tsvi8b6fe3a2021-09-13 15:55:44 -0700122 std::unique_ptr<media::SensorPoseProvider> mPoseProvider;
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700123 int32_t mHeadSensor = media::SensorPoseProvider::INVALID_HANDLE;
124 int32_t mScreenSensor = media::SensorPoseProvider::INVALID_HANDLE;
125 std::optional<media::HeadTrackingMode> mActualMode;
126 std::thread mThread;
127 std::condition_variable mCondVar;
128 bool mShouldCalculate = true;
129 bool mShouldExit = false;
130 bool mCalculated = false;
131
132 void onPose(int64_t timestamp, int32_t sensor, const media::Pose3f& pose,
Ytai Ben-Tsvi2c694be2021-10-06 17:12:49 -0700133 const std::optional<media::Twist3f>& twist, bool isNewReference) override;
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700134
Ytai Ben-Tsvi7c2acd12021-09-09 15:50:00 -0700135 /**
136 * Calculates the new outputs and updates internal state. Must be called with the lock held.
137 * Returns values that should be passed to the respective callbacks.
138 */
139 std::tuple<media::Pose3f, std::optional<media::HeadTrackingMode>> calculate_l();
Ytai Ben-Tsvid83c42d2021-08-25 14:19:34 -0700140};
141
142} // namespace android