1 /* 2 * Copyright (C) 2023 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 17 #include <mutex> 18 19 #include <audio_utils/clock.h> 20 21 #include <media/nbaio/MonoPipe.h> 22 #include <media/nbaio/MonoPipeReader.h> 23 24 #include <aidl/android/media/audio/common/AudioChannelLayout.h> 25 26 #include "core-impl/Stream.h" 27 28 using aidl::android::media::audio::common::AudioChannelLayout; 29 using aidl::android::media::audio::common::AudioFormatDescription; 30 using aidl::android::media::audio::common::AudioFormatType; 31 using aidl::android::media::audio::common::PcmType; 32 using ::android::MonoPipe; 33 using ::android::MonoPipeReader; 34 using ::android::sp; 35 36 namespace aidl::android::hardware::audio::core::r_submix { 37 38 static constexpr int kDefaultSampleRateHz = 48000; 39 // Size at default sample rate 40 // NOTE: This value will be rounded up to the nearest power of 2 by MonoPipe(). 41 static constexpr int kDefaultPipeSizeInFrames = (1024 * 4); 42 43 // Configuration of the audio stream. 44 struct AudioConfig { 45 int sampleRate = kDefaultSampleRateHz; 46 AudioFormatDescription format = 47 AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = PcmType::INT_16_BIT}; 48 AudioChannelLayout channelLayout = 49 AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>( 50 AudioChannelLayout::LAYOUT_STEREO); 51 size_t frameSize; 52 size_t frameCount; 53 }; 54 55 class SubmixRoute { 56 public: 57 AudioConfig mPipeConfig; 58 isStreamInOpen()59 bool isStreamInOpen() { 60 std::lock_guard guard(mLock); 61 return mStreamInOpen; 62 } getStreamInStandby()63 bool getStreamInStandby() { 64 std::lock_guard guard(mLock); 65 return mStreamInStandby; 66 } isStreamOutOpen()67 bool isStreamOutOpen() { 68 std::lock_guard guard(mLock); 69 return mStreamOutOpen; 70 } getStreamOutStandby()71 bool getStreamOutStandby() { 72 std::lock_guard guard(mLock); 73 return mStreamOutStandby; 74 } getReadCounterFrames()75 long getReadCounterFrames() { 76 std::lock_guard guard(mLock); 77 return mReadCounterFrames; 78 } getReadErrorCount()79 int getReadErrorCount() { 80 std::lock_guard guard(mLock); 81 return mReadErrorCount; 82 } getRecordStartTime()83 std::chrono::time_point<std::chrono::steady_clock> getRecordStartTime() { 84 std::lock_guard guard(mLock); 85 return mRecordStartTime; 86 } getSink()87 sp<MonoPipe> getSink() { 88 std::lock_guard guard(mLock); 89 return mSink; 90 } getSource()91 sp<MonoPipeReader> getSource() { 92 std::lock_guard guard(mLock); 93 return mSource; 94 } 95 96 bool isStreamConfigValid(bool isInput, const AudioConfig& streamConfig); 97 void closeStream(bool isInput); 98 ::android::status_t createPipe(const AudioConfig& streamConfig); 99 void exitStandby(bool isInput); 100 bool hasAtleastOneStreamOpen(); 101 int notifyReadError(); 102 void openStream(bool isInput); 103 void releasePipe(); 104 ::android::status_t resetPipe(); 105 bool shouldBlockWrite(); 106 void standby(bool isInput); 107 long updateReadCounterFrames(size_t frameCount); 108 109 private: 110 bool isStreamConfigCompatible(const AudioConfig& streamConfig); 111 112 std::mutex mLock; 113 114 bool mStreamInOpen GUARDED_BY(mLock) = false; 115 int mInputRefCount GUARDED_BY(mLock) = 0; 116 bool mStreamInStandby GUARDED_BY(mLock) = true; 117 bool mStreamOutStandbyTransition GUARDED_BY(mLock) = false; 118 bool mStreamOutOpen GUARDED_BY(mLock) = false; 119 bool mStreamOutStandby GUARDED_BY(mLock) = true; 120 // how many frames have been requested to be read since standby 121 long mReadCounterFrames GUARDED_BY(mLock) = 0; 122 int mReadErrorCount GUARDED_BY(mLock) = 0; 123 // wall clock when recording starts 124 std::chrono::time_point<std::chrono::steady_clock> mRecordStartTime GUARDED_BY(mLock); 125 126 // Pipe variables: they handle the ring buffer that "pipes" audio: 127 // - from the submix virtual audio output == what needs to be played 128 // remotely, seen as an output for the client 129 // - to the virtual audio source == what is captured by the component 130 // which "records" the submix / virtual audio source, and handles it as needed. 131 // A usecase example is one where the component capturing the audio is then sending it over 132 // Wifi for presentation on a remote Wifi Display device (e.g. a dongle attached to a TV, or a 133 // TV with Wifi Display capabilities), or to a wireless audio player. 134 sp<MonoPipe> mSink GUARDED_BY(mLock); 135 sp<MonoPipeReader> mSource GUARDED_BY(mLock); 136 }; 137 138 } // namespace aidl::android::hardware::audio::core::r_submix 139