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