• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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