blob: fe1005b6964592039006702ec4957d152808a268 [file] [log] [blame]
Wei Jiaec044b02018-02-19 12:41:23 -08001/*
2**
3** Copyright 2018, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#ifndef ANDROID_MEDIAPLAYER2AUDIOOUTPUT_H
19#define ANDROID_MEDIAPLAYER2AUDIOOUTPUT_H
20
21#include <mediaplayer2/MediaPlayer2Interface.h>
22
23#include <utils/String16.h>
24#include <utils/Vector.h>
25
26namespace android {
27
28class AudioTrack;
29
30class MediaPlayer2AudioOutput : public MediaPlayer2Interface::AudioSink
31{
32 class CallbackData;
33
34public:
35 MediaPlayer2AudioOutput(audio_session_t sessionId,
36 uid_t uid,
37 int pid,
38 const audio_attributes_t * attr,
39 const sp<AudioSystem::AudioDeviceCallback>& deviceCallback);
40 virtual ~MediaPlayer2AudioOutput();
41
42 virtual bool ready() const {
43 return mTrack != 0;
44 }
45 virtual ssize_t bufferSize() const;
46 virtual ssize_t frameCount() const;
47 virtual ssize_t channelCount() const;
48 virtual ssize_t frameSize() const;
49 virtual uint32_t latency() const;
50 virtual float msecsPerFrame() const;
51 virtual status_t getPosition(uint32_t *position) const;
52 virtual status_t getTimestamp(AudioTimestamp &ts) const;
53 virtual int64_t getPlayedOutDurationUs(int64_t nowUs) const;
54 virtual status_t getFramesWritten(uint32_t *frameswritten) const;
55 virtual audio_session_t getSessionId() const;
56 virtual uint32_t getSampleRate() const;
57 virtual int64_t getBufferDurationInUs() const;
58
59 virtual status_t open(
60 uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
Dichen Zhang303bd2d2018-09-28 12:52:49 -070061 audio_format_t format,
Wei Jiaec044b02018-02-19 12:41:23 -080062 AudioCallback cb, void *cookie,
63 audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
64 const audio_offload_info_t *offloadInfo = NULL,
65 bool doNotReconnect = false,
66 uint32_t suggestedFrameCount = 0);
67
68 virtual status_t start();
69 virtual ssize_t write(const void* buffer, size_t size, bool blocking = true);
70 virtual void stop();
71 virtual void flush();
72 virtual void pause();
73 virtual void close();
74 void setAudioStreamType(audio_stream_type_t streamType);
75 virtual audio_stream_type_t getAudioStreamType() const {
76 return mStreamType;
77 }
78 void setAudioAttributes(const audio_attributes_t * attributes);
79
Dichen Zhang7398ca02018-10-15 10:25:12 -070080 void setVolume(float volume);
Wei Jiaec044b02018-02-19 12:41:23 -080081 virtual status_t setPlaybackRate(const AudioPlaybackRate& rate);
82 virtual status_t getPlaybackRate(AudioPlaybackRate* rate /* nonnull */);
83
84 status_t setAuxEffectSendLevel(float level);
85 status_t attachAuxEffect(int effectId);
86 virtual status_t dump(int fd, const Vector<String16>& args) const;
87
88 static bool isOnEmulator();
89 static int getMinBufferCount();
Wei Jiaec044b02018-02-19 12:41:23 -080090 virtual bool needsTrailingPadding() {
91 return true;
92 // TODO: return correct value.
93 //return mNextOutput == NULL;
94 }
95 virtual status_t setParameters(const String8& keyValuePairs);
96 virtual String8 getParameters(const String8& keys);
97
98 // AudioRouting
99 virtual status_t setOutputDevice(audio_port_handle_t deviceId);
100 virtual status_t getRoutedDeviceId(audio_port_handle_t* deviceId);
101 virtual status_t enableAudioDeviceCallback(bool enabled);
102
103private:
104 static void setMinBufferCount();
105 static void CallbackWrapper(int event, void *me, void *info);
106 void deleteRecycledTrack_l();
107 void close_l();
108 status_t updateTrack_l();
109
110 sp<AudioTrack> mTrack;
111 AudioCallback mCallback;
112 void * mCallbackCookie;
113 CallbackData * mCallbackData;
114 audio_stream_type_t mStreamType;
115 audio_attributes_t * mAttributes;
Dichen Zhang7398ca02018-10-15 10:25:12 -0700116 float mVolume;
Wei Jiaec044b02018-02-19 12:41:23 -0800117 AudioPlaybackRate mPlaybackRate;
118 uint32_t mSampleRateHz; // sample rate of the content, as set in open()
119 float mMsecsPerFrame;
120 size_t mFrameSize;
121 audio_session_t mSessionId;
122 uid_t mUid;
123 int mPid;
124 float mSendLevel;
125 int mAuxEffectId;
126 audio_output_flags_t mFlags;
127 audio_port_handle_t mSelectedDeviceId;
128 audio_port_handle_t mRoutedDeviceId;
129 bool mDeviceCallbackEnabled;
130 wp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
131 mutable Mutex mLock;
132
133 // static variables below not protected by mutex
134 static bool mIsOnEmulator;
135 static int mMinBufferCount; // 12 for emulator; otherwise 4
136
137 // CallbackData is what is passed to the AudioTrack as the "user" data.
138 // We need to be able to target this to a different Output on the fly,
139 // so we can't use the Output itself for this.
140 class CallbackData {
141 friend MediaPlayer2AudioOutput;
142 public:
143 explicit CallbackData(MediaPlayer2AudioOutput *cookie) {
144 mData = cookie;
145 mSwitching = false;
146 }
147 MediaPlayer2AudioOutput *getOutput() const {
148 return mData;
149 }
150 void setOutput(MediaPlayer2AudioOutput* newcookie) {
151 mData = newcookie;
152 }
153 // lock/unlock are used by the callback before accessing the payload of this object
154 void lock() const {
155 mLock.lock();
156 }
157 void unlock() const {
158 mLock.unlock();
159 }
160
161 // tryBeginTrackSwitch/endTrackSwitch are used when the CallbackData is handed over
162 // to the next sink.
163
164 // tryBeginTrackSwitch() returns true only if it obtains the lock.
165 bool tryBeginTrackSwitch() {
166 LOG_ALWAYS_FATAL_IF(mSwitching, "tryBeginTrackSwitch() already called");
167 if (mLock.tryLock() != OK) {
168 return false;
169 }
170 mSwitching = true;
171 return true;
172 }
173 void endTrackSwitch() {
174 if (mSwitching) {
175 mLock.unlock();
176 }
177 mSwitching = false;
178 }
179
180 private:
181 MediaPlayer2AudioOutput *mData;
182 mutable Mutex mLock; // a recursive mutex might make this unnecessary.
183 bool mSwitching;
184 DISALLOW_EVIL_CONSTRUCTORS(CallbackData);
185 };
186};
187
188}; // namespace android
189
190#endif // ANDROID_MEDIAPLAYER2AUDIOOUTPUT_H