blob: 17a5142d0989c78f7cd4699620b7ff7d3871599d [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.
59 *
60 * All the timestamps used here are of arbitrary units and origin. They just need to be consistent
61 * between all the calls and with the Options provided for determining freshness and rate limiting.
62 */
63class ModeSelector {
64 public:
65 struct Options {
66 int64_t freshnessTimeout = std::numeric_limits<int64_t>::max();
67 };
68
69 ModeSelector(const Options& options, HeadTrackingMode initialMode = HeadTrackingMode::STATIC);
70
71 /** Sets the desired head-tracking mode. */
72 void setDesiredMode(HeadTrackingMode mode);
73
74 /**
75 * Set the screen-to-stage pose, used in all modes.
76 */
77 void setScreenToStagePose(const Pose3f& screenToStage);
78
79 /**
80 * Set the screen-to-head pose, used in screen-relative mode.
81 * The timestamp needs to reflect how fresh the sample is (not necessarily which point in time
82 * it applies to). nullopt can be used if it is determined that the listener is not in front of
83 * the screen.
84 */
85 void setScreenToHeadPose(int64_t timestamp, const std::optional<Pose3f>& screenToHead);
86
87 /**
88 * Set the world-to-head pose, used in world-relative mode.
89 * The timestamp needs to reflect how fresh the sample is (not necessarily which point in time
90 * it applies to).
91 */
92 void setWorldToHeadPose(int64_t timestamp, const Pose3f& worldToHead);
93
94 /**
95 * Process all the previous inputs and update the outputs.
96 */
97 void calculate(int64_t timestamp);
98
99 /**
100 * Get the aggregate head-to-stage pose (primary output of this module).
101 */
102 Pose3f getHeadToStagePose() const;
103
104 /**
105 * Get the actual head-tracking mode (which may deviate from the desired one as mentioned in the
106 * class documentation above).
107 */
108 HeadTrackingMode getActualMode() const;
109
110 private:
111 const Options mOptions;
112
113 HeadTrackingMode mDesiredMode;
114 Pose3f mScreenToStage;
115 std::optional<Pose3f> mScreenToHead;
116 int64_t mScreenToHeadTimestamp;
117 std::optional<Pose3f> mWorldToHead;
118 int64_t mWorldToHeadTimestamp;
119
120 HeadTrackingMode mActualMode;
121 Pose3f mHeadToStage;
122
123 void calculateActualMode(int64_t timestamp);
124};
125
126} // namespace media
127} // namespace android