1 /*
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 #include <mediaplayer2/JAudioTrack.h>
23 #include <mediaplayer2/JObjectHolder.h>
24 
25 #include <utility>
26 #include <utils/String16.h>
27 #include <utils/Vector.h>
28 
29 #include "jni.h"
30 
31 namespace android {
32 
33 class AudioTrack;
34 
35 class MediaPlayer2AudioOutput : public MediaPlayer2Interface::AudioSink
36 {
37     class CallbackData;
38 
39 public:
40     MediaPlayer2AudioOutput(int32_t sessionId,
41                             uid_t uid,
42                             int pid,
43                             const jobject attributes);
44     virtual ~MediaPlayer2AudioOutput();
45 
ready()46     virtual bool ready() const {
47         return mJAudioTrack != nullptr;
48     }
49     virtual ssize_t bufferSize() const;
50     virtual ssize_t frameCount() const;
51     virtual ssize_t channelCount() const;
52     virtual ssize_t frameSize() const;
53     virtual uint32_t latency() const;
54     virtual float msecsPerFrame() const;
55     virtual status_t getPosition(uint32_t *position) const;
56     virtual status_t getTimestamp(AudioTimestamp &ts) const;
57     virtual int64_t getPlayedOutDurationUs(int64_t nowUs) const;
58     virtual status_t getFramesWritten(uint32_t *frameswritten) const;
59     virtual int32_t getSessionId() const;
60     virtual void setSessionId(const int32_t id);
61     virtual uint32_t getSampleRate() const;
62     virtual int64_t getBufferDurationInUs() const;
63 
64     virtual status_t open(
65             uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
66             audio_format_t format,
67             AudioCallback cb, void *cookie,
68             audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
69             const audio_offload_info_t *offloadInfo = NULL,
70             uint32_t suggestedFrameCount = 0);
71 
72     virtual status_t start();
73     virtual ssize_t write(const void* buffer, size_t size, bool blocking = true);
74     virtual void stop();
75     virtual void flush();
76     virtual void pause();
77     virtual void close();
78     void setAudioAttributes(const jobject attributes);
79     virtual audio_stream_type_t getAudioStreamType() const;
80 
81     void setVolume(float volume);
82     virtual status_t setPlaybackRate(const AudioPlaybackRate& rate);
83     virtual status_t getPlaybackRate(AudioPlaybackRate* rate /* nonnull */);
84 
85     status_t setAuxEffectSendLevel(float level);
86     status_t attachAuxEffect(int effectId);
87     virtual status_t dump(int fd, const Vector<String16>& args) const;
88 
89     static bool isOnEmulator();
90     static int getMinBufferCount();
needsTrailingPadding()91     virtual bool needsTrailingPadding() {
92         return true;
93         // TODO: return correct value.
94         //return mNextOutput == NULL;
95     }
96     // AudioRouting
97     virtual status_t setPreferredDevice(jobject device);
98     virtual jobject getRoutedDevice();
99     virtual status_t addAudioDeviceCallback(jobject routingDelegate);
100     virtual status_t removeAudioDeviceCallback(jobject listener);
101 
102 private:
103     static void setMinBufferCount();
104     static void CallbackWrapper(int event, void *me, void *info);
105     void deleteRecycledTrack_l();
106     void close_l();
107     status_t updateTrack_l();
108 
109     sp<JAudioTrack>         mJAudioTrack;
110     AudioCallback           mCallback;
111     void *                  mCallbackCookie;
112     CallbackData *          mCallbackData;
113     sp<JObjectHolder>       mAttributes;
114     float                   mVolume;
115     AudioPlaybackRate       mPlaybackRate;
116     uint32_t                mSampleRateHz; // sample rate of the content, as set in open()
117     float                   mMsecsPerFrame;
118     size_t                  mFrameSize;
119     int32_t                 mSessionId;
120     uid_t                   mUid;
121     int                     mPid;
122     float                   mSendLevel;
123     int                     mAuxEffectId;
124     audio_output_flags_t    mFlags;
125     sp<JObjectHolder>       mPreferredDevice;
126     mutable Mutex           mLock;
127 
128     // <listener, routingDelegate>
129     Vector<std::pair<sp<JObjectHolder>, sp<JObjectHolder>>> mRoutingDelegates;
130 
131     // static variables below not protected by mutex
132     static bool             mIsOnEmulator;
133     static int              mMinBufferCount;  // 12 for emulator; otherwise 4
134 
135     // CallbackData is what is passed to the AudioTrack as the "user" data.
136     // We need to be able to target this to a different Output on the fly,
137     // so we can't use the Output itself for this.
138     class CallbackData {
139         friend MediaPlayer2AudioOutput;
140     public:
CallbackData(MediaPlayer2AudioOutput * cookie)141         explicit CallbackData(MediaPlayer2AudioOutput *cookie) {
142             mData = cookie;
143             mSwitching = false;
144         }
getOutput()145         MediaPlayer2AudioOutput *getOutput() const {
146             return mData;
147         }
setOutput(MediaPlayer2AudioOutput * newcookie)148         void setOutput(MediaPlayer2AudioOutput* newcookie) {
149             mData = newcookie;
150         }
151         // lock/unlock are used by the callback before accessing the payload of this object
lock()152         void lock() const {
153             mLock.lock();
154         }
unlock()155         void unlock() const {
156             mLock.unlock();
157         }
158 
159         // tryBeginTrackSwitch/endTrackSwitch are used when the CallbackData is handed over
160         // to the next sink.
161 
162         // tryBeginTrackSwitch() returns true only if it obtains the lock.
tryBeginTrackSwitch()163         bool tryBeginTrackSwitch() {
164             LOG_ALWAYS_FATAL_IF(mSwitching, "tryBeginTrackSwitch() already called");
165             if (mLock.tryLock() != OK) {
166                 return false;
167             }
168             mSwitching = true;
169             return true;
170         }
endTrackSwitch()171         void endTrackSwitch() {
172             if (mSwitching) {
173                 mLock.unlock();
174             }
175             mSwitching = false;
176         }
177 
178     private:
179         MediaPlayer2AudioOutput *mData;
180         mutable Mutex mLock; // a recursive mutex might make this unnecessary.
181         bool mSwitching;
182         DISALLOW_EVIL_CONSTRUCTORS(CallbackData);
183     };
184 };
185 
186 }; // namespace android
187 
188 #endif // ANDROID_MEDIAPLAYER2AUDIOOUTPUT_H
189