blob: e5370409ea4099917310f3cf5b86b39ea6dbd7bd [file] [log] [blame]
Ytai Ben-Tsvicbee7d42021-06-15 00:39:31 -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 <optional>
19
20#include "media/HeadTrackingMode.h"
21#include "media/Pose.h"
22
23#include "PoseRateLimiter.h"
24
25namespace android {
26namespace media {
27
28/**
29 * Head-tracking mode selector.
30 *
31 * This class is responsible for production of the determining pose for audio virtualization, based
32 * on a number of available sources and a selectable mode.
33 *
34 * Typical flow is:
35 * ModeSelector selector(...);
36 * while (...) {
37 * // Set inputs.
38 * selector.setFoo(...);
39 * selector.setBar(...);
40 *
41 * // Update outputs based on inputs.
42 * selector.calculate(...);
43 *
44 * // Get outputs.
45 * Pose3f pose = selector.getHeadToStagePose();
46 * }
47 *
48 * This class is not thread-safe, but thread-compatible.
49 *
50 * For details on the frames of reference involved, their composition and the definitions to the
51 * different modes, refer to:
52 * go/immersive-audio-frames
53 *
54 * The actual mode may deviate from the desired mode in the following cases:
55 * - When we cannot get a valid and fresh estimate of the screen-to-head pose, we will fall back
56 * from screen-relative to world-relative.
57 * - When we cannot get a fresh estimate of the world-to-head pose, we will fall back from
58 * world-relative to static.
Ytai Ben-Tsvic7e8a482021-12-20 13:26:34 -080059 * - In world-relative mode, if the screen is unstable, we will fall back to static.
Ytai Ben-Tsvicbee7d42021-06-15 00:39:31 -070060 *
61 * All the timestamps used here are of arbitrary units and origin. They just need to be consistent
62 * between all the calls and with the Options provided for determining freshness and rate limiting.
63 */
64class ModeSelector {
65 public:
66 struct Options {
67 int64_t freshnessTimeout = std::numeric_limits<int64_t>::max();
68 };
69
70 ModeSelector(const Options& options, HeadTrackingMode initialMode = HeadTrackingMode::STATIC);
71
72 /** Sets the desired head-tracking mode. */
73 void setDesiredMode(HeadTrackingMode mode);
74
75 /**
76 * Set the screen-to-stage pose, used in all modes.
77 */
78 void setScreenToStagePose(const Pose3f& screenToStage);
79
80 /**
81 * Set the screen-to-head pose, used in screen-relative mode.
82 * The timestamp needs to reflect how fresh the sample is (not necessarily which point in time
83 * it applies to). nullopt can be used if it is determined that the listener is not in front of
84 * the screen.
85 */
86 void setScreenToHeadPose(int64_t timestamp, const std::optional<Pose3f>& screenToHead);
87
88 /**
89 * Set the world-to-head pose, used in world-relative mode.
90 * The timestamp needs to reflect how fresh the sample is (not necessarily which point in time
91 * it applies to).
92 */
93 void setWorldToHeadPose(int64_t timestamp, const Pose3f& worldToHead);
94
95 /**
Ytai Ben-Tsvic7e8a482021-12-20 13:26:34 -080096 * Set whether the screen is considered stable.
97 * The timestamp needs to reflect how fresh the sample is.
98 */
99 void setScreenStable(int64_t timestamp, bool stable);
100
101 /**
Ytai Ben-Tsvicbee7d42021-06-15 00:39:31 -0700102 * Process all the previous inputs and update the outputs.
103 */
104 void calculate(int64_t timestamp);
105
106 /**
107 * Get the aggregate head-to-stage pose (primary output of this module).
108 */
109 Pose3f getHeadToStagePose() const;
110
111 /**
112 * Get the actual head-tracking mode (which may deviate from the desired one as mentioned in the
113 * class documentation above).
114 */
115 HeadTrackingMode getActualMode() const;
116
117 private:
118 const Options mOptions;
119
120 HeadTrackingMode mDesiredMode;
121 Pose3f mScreenToStage;
122 std::optional<Pose3f> mScreenToHead;
123 int64_t mScreenToHeadTimestamp;
124 std::optional<Pose3f> mWorldToHead;
125 int64_t mWorldToHeadTimestamp;
Ytai Ben-Tsvic7e8a482021-12-20 13:26:34 -0800126 std::optional<bool> mScreenStable;
127 int64_t mScreenStableTimestamp;
Ytai Ben-Tsvicbee7d42021-06-15 00:39:31 -0700128
129 HeadTrackingMode mActualMode;
130 Pose3f mHeadToStage;
131
132 void calculateActualMode(int64_t timestamp);
133};
134
135} // namespace media
136} // namespace android