1 /* 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 25 namespace android { 26 namespace 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 */ 63 class 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 128