blob: 619dc7bb9b39b893d156879e3fe68c6ebc1e5a0c [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 *
41 * This class is thread-safe. Callbacks are invoked with the lock held, so it is illegal to call
42 * into this module from the callbacks.
43 */
44class SpatializerPoseController : private media::SensorPoseProvider::Listener {
45 public:
46 /**
47 * Listener interface for getting pose and mode updates.
48 * Methods will always be invoked from a designated thread. Calling into the parent class from
49 * within the callbacks is disallowed (will result in a deadlock).
50 */
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.
73 * nullptr can be used to disable head-tracking.
74 */
75 void setHeadSensor(const ASensor* sensor);
76
77 /**
78 * Set the sensor that is to be used for screen-tracking.
79 * nullptr can be used to disable screen-tracking.
80 */
81 void setScreenSensor(const ASensor* sensor);
82
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
112 * once.
113 */
114 void waitUntilCalculated();
115
116 private:
117 mutable std::mutex mMutex;
118 Listener* const mListener;
119 const std::chrono::microseconds mSensorPeriod;
120 std::unique_ptr<media::SensorPoseProvider> mPoseProvider;
121 std::unique_ptr<media::HeadTrackingProcessor> mProcessor;
122 int32_t mHeadSensor = media::SensorPoseProvider::INVALID_HANDLE;
123 int32_t mScreenSensor = media::SensorPoseProvider::INVALID_HANDLE;
124 std::optional<media::HeadTrackingMode> mActualMode;
125 std::thread mThread;
126 std::condition_variable mCondVar;
127 bool mShouldCalculate = true;
128 bool mShouldExit = false;
129 bool mCalculated = false;
130
131 void onPose(int64_t timestamp, int32_t sensor, const media::Pose3f& pose,
132 const std::optional<media::Twist3f>& twist) override;
133
134 void calculate_l();
135};
136
137} // namespace android