1*ec779b8eSAndroid Build Coastguard Worker /* 2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2021 The Android Open Source Project 3*ec779b8eSAndroid Build Coastguard Worker * 4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*ec779b8eSAndroid Build Coastguard Worker * 8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*ec779b8eSAndroid Build Coastguard Worker * 10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License. 15*ec779b8eSAndroid Build Coastguard Worker */ 16*ec779b8eSAndroid Build Coastguard Worker #pragma once 17*ec779b8eSAndroid Build Coastguard Worker 18*ec779b8eSAndroid Build Coastguard Worker #include <optional> 19*ec779b8eSAndroid Build Coastguard Worker #include <audio_utils/SimpleLog.h> 20*ec779b8eSAndroid Build Coastguard Worker 21*ec779b8eSAndroid Build Coastguard Worker #include "media/HeadTrackingMode.h" 22*ec779b8eSAndroid Build Coastguard Worker #include "media/Pose.h" 23*ec779b8eSAndroid Build Coastguard Worker 24*ec779b8eSAndroid Build Coastguard Worker #include "PoseRateLimiter.h" 25*ec779b8eSAndroid Build Coastguard Worker 26*ec779b8eSAndroid Build Coastguard Worker namespace android { 27*ec779b8eSAndroid Build Coastguard Worker namespace media { 28*ec779b8eSAndroid Build Coastguard Worker 29*ec779b8eSAndroid Build Coastguard Worker /** 30*ec779b8eSAndroid Build Coastguard Worker * Head-tracking mode selector. 31*ec779b8eSAndroid Build Coastguard Worker * 32*ec779b8eSAndroid Build Coastguard Worker * This class is responsible for production of the determining pose for audio virtualization, based 33*ec779b8eSAndroid Build Coastguard Worker * on a number of available sources and a selectable mode. 34*ec779b8eSAndroid Build Coastguard Worker * 35*ec779b8eSAndroid Build Coastguard Worker * Typical flow is: 36*ec779b8eSAndroid Build Coastguard Worker * ModeSelector selector(...); 37*ec779b8eSAndroid Build Coastguard Worker * while (...) { 38*ec779b8eSAndroid Build Coastguard Worker * // Set inputs. 39*ec779b8eSAndroid Build Coastguard Worker * selector.setFoo(...); 40*ec779b8eSAndroid Build Coastguard Worker * selector.setBar(...); 41*ec779b8eSAndroid Build Coastguard Worker * 42*ec779b8eSAndroid Build Coastguard Worker * // Update outputs based on inputs. 43*ec779b8eSAndroid Build Coastguard Worker * selector.calculate(...); 44*ec779b8eSAndroid Build Coastguard Worker * 45*ec779b8eSAndroid Build Coastguard Worker * // Get outputs. 46*ec779b8eSAndroid Build Coastguard Worker * Pose3f pose = selector.getHeadToStagePose(); 47*ec779b8eSAndroid Build Coastguard Worker * } 48*ec779b8eSAndroid Build Coastguard Worker * 49*ec779b8eSAndroid Build Coastguard Worker * This class is not thread-safe, but thread-compatible. 50*ec779b8eSAndroid Build Coastguard Worker * 51*ec779b8eSAndroid Build Coastguard Worker * For details on the frames of reference involved, their composition and the definitions to the 52*ec779b8eSAndroid Build Coastguard Worker * different modes, refer to: 53*ec779b8eSAndroid Build Coastguard Worker * go/immersive-audio-frames 54*ec779b8eSAndroid Build Coastguard Worker * 55*ec779b8eSAndroid Build Coastguard Worker * The actual mode may deviate from the desired mode in the following cases: 56*ec779b8eSAndroid Build Coastguard Worker * - When we cannot get a valid and fresh estimate of the screen-to-head pose, we will fall back 57*ec779b8eSAndroid Build Coastguard Worker * from screen-relative to world-relative. 58*ec779b8eSAndroid Build Coastguard Worker * - When we cannot get a fresh estimate of the world-to-head pose, we will fall back from 59*ec779b8eSAndroid Build Coastguard Worker * world-relative to static. 60*ec779b8eSAndroid Build Coastguard Worker * - In world-relative mode, if the screen is unstable, we will fall back to static. 61*ec779b8eSAndroid Build Coastguard Worker * 62*ec779b8eSAndroid Build Coastguard Worker * All the timestamps used here are of arbitrary units and origin. They just need to be consistent 63*ec779b8eSAndroid Build Coastguard Worker * between all the calls and with the Options provided for determining freshness and rate limiting. 64*ec779b8eSAndroid Build Coastguard Worker */ 65*ec779b8eSAndroid Build Coastguard Worker class ModeSelector { 66*ec779b8eSAndroid Build Coastguard Worker public: 67*ec779b8eSAndroid Build Coastguard Worker struct Options { 68*ec779b8eSAndroid Build Coastguard Worker int64_t freshnessTimeout = std::numeric_limits<int64_t>::max(); 69*ec779b8eSAndroid Build Coastguard Worker }; 70*ec779b8eSAndroid Build Coastguard Worker 71*ec779b8eSAndroid Build Coastguard Worker ModeSelector(const Options& options, HeadTrackingMode initialMode = HeadTrackingMode::STATIC); 72*ec779b8eSAndroid Build Coastguard Worker 73*ec779b8eSAndroid Build Coastguard Worker /** Sets the desired head-tracking mode. */ 74*ec779b8eSAndroid Build Coastguard Worker void setDesiredMode(HeadTrackingMode mode); 75*ec779b8eSAndroid Build Coastguard Worker 76*ec779b8eSAndroid Build Coastguard Worker /** 77*ec779b8eSAndroid Build Coastguard Worker * Set the screen-to-stage pose, used in all modes. 78*ec779b8eSAndroid Build Coastguard Worker */ 79*ec779b8eSAndroid Build Coastguard Worker void setScreenToStagePose(const Pose3f& screenToStage); 80*ec779b8eSAndroid Build Coastguard Worker 81*ec779b8eSAndroid Build Coastguard Worker /** 82*ec779b8eSAndroid Build Coastguard Worker * Set the screen-to-head pose, used in screen-relative mode. 83*ec779b8eSAndroid Build Coastguard Worker * The timestamp needs to reflect how fresh the sample is (not necessarily which point in time 84*ec779b8eSAndroid Build Coastguard Worker * it applies to). nullopt can be used if it is determined that the listener is not in front of 85*ec779b8eSAndroid Build Coastguard Worker * the screen. 86*ec779b8eSAndroid Build Coastguard Worker */ 87*ec779b8eSAndroid Build Coastguard Worker void setScreenToHeadPose(int64_t timestamp, const std::optional<Pose3f>& screenToHead); 88*ec779b8eSAndroid Build Coastguard Worker 89*ec779b8eSAndroid Build Coastguard Worker /** 90*ec779b8eSAndroid Build Coastguard Worker * Set the world-to-head pose, used in world-relative mode. 91*ec779b8eSAndroid Build Coastguard Worker * The timestamp needs to reflect how fresh the sample is (not necessarily which point in time 92*ec779b8eSAndroid Build Coastguard Worker * it applies to). 93*ec779b8eSAndroid Build Coastguard Worker */ 94*ec779b8eSAndroid Build Coastguard Worker void setWorldToHeadPose(int64_t timestamp, const Pose3f& worldToHead); 95*ec779b8eSAndroid Build Coastguard Worker 96*ec779b8eSAndroid Build Coastguard Worker /** 97*ec779b8eSAndroid Build Coastguard Worker * Set whether the screen is considered stable. 98*ec779b8eSAndroid Build Coastguard Worker * The timestamp needs to reflect how fresh the sample is. 99*ec779b8eSAndroid Build Coastguard Worker */ 100*ec779b8eSAndroid Build Coastguard Worker void setScreenStable(int64_t timestamp, bool stable); 101*ec779b8eSAndroid Build Coastguard Worker 102*ec779b8eSAndroid Build Coastguard Worker /** 103*ec779b8eSAndroid Build Coastguard Worker * Process all the previous inputs and update the outputs. 104*ec779b8eSAndroid Build Coastguard Worker */ 105*ec779b8eSAndroid Build Coastguard Worker void calculate(int64_t timestamp); 106*ec779b8eSAndroid Build Coastguard Worker 107*ec779b8eSAndroid Build Coastguard Worker /** 108*ec779b8eSAndroid Build Coastguard Worker * Get the aggregate head-to-stage pose (primary output of this module). 109*ec779b8eSAndroid Build Coastguard Worker */ 110*ec779b8eSAndroid Build Coastguard Worker Pose3f getHeadToStagePose() const; 111*ec779b8eSAndroid Build Coastguard Worker 112*ec779b8eSAndroid Build Coastguard Worker /** 113*ec779b8eSAndroid Build Coastguard Worker * Get the actual head-tracking mode (which may deviate from the desired one as mentioned in the 114*ec779b8eSAndroid Build Coastguard Worker * class documentation above). 115*ec779b8eSAndroid Build Coastguard Worker */ 116*ec779b8eSAndroid Build Coastguard Worker HeadTrackingMode getActualMode() const; 117*ec779b8eSAndroid Build Coastguard Worker 118*ec779b8eSAndroid Build Coastguard Worker std::string toString(unsigned level) const; 119*ec779b8eSAndroid Build Coastguard Worker 120*ec779b8eSAndroid Build Coastguard Worker private: 121*ec779b8eSAndroid Build Coastguard Worker const Options mOptions; 122*ec779b8eSAndroid Build Coastguard Worker 123*ec779b8eSAndroid Build Coastguard Worker HeadTrackingMode mDesiredMode; 124*ec779b8eSAndroid Build Coastguard Worker Pose3f mScreenToStage; 125*ec779b8eSAndroid Build Coastguard Worker std::optional<Pose3f> mScreenToHead; 126*ec779b8eSAndroid Build Coastguard Worker int64_t mScreenToHeadTimestamp; 127*ec779b8eSAndroid Build Coastguard Worker std::optional<Pose3f> mWorldToHead; 128*ec779b8eSAndroid Build Coastguard Worker int64_t mWorldToHeadTimestamp; 129*ec779b8eSAndroid Build Coastguard Worker std::optional<bool> mScreenStable; 130*ec779b8eSAndroid Build Coastguard Worker int64_t mScreenStableTimestamp; 131*ec779b8eSAndroid Build Coastguard Worker 132*ec779b8eSAndroid Build Coastguard Worker HeadTrackingMode mActualMode; 133*ec779b8eSAndroid Build Coastguard Worker Pose3f mHeadToStage; 134*ec779b8eSAndroid Build Coastguard Worker 135*ec779b8eSAndroid Build Coastguard Worker static constexpr std::size_t sMaxLocalLogLine = 10; 136*ec779b8eSAndroid Build Coastguard Worker SimpleLog mLocalLog{sMaxLocalLogLine}; 137*ec779b8eSAndroid Build Coastguard Worker 138*ec779b8eSAndroid Build Coastguard Worker void calculateActualMode(int64_t timestamp); 139*ec779b8eSAndroid Build Coastguard Worker }; 140*ec779b8eSAndroid Build Coastguard Worker 141*ec779b8eSAndroid Build Coastguard Worker } // namespace media 142*ec779b8eSAndroid Build Coastguard Worker } // namespace android 143