blob: f38b7cc2c34f4adbe58e86a9235c94fba3e0d563 [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>
Dichen Zhangf8726912018-10-17 13:31:26 -070022#include <mediaplayer2/JAudioTrack.h>
Dongwon Kang0d7042d2018-10-12 16:52:14 -070023#include <mediaplayer2/JObjectHolder.h>
Wei Jiaec044b02018-02-19 12:41:23 -080024
Dichen Zhangf8726912018-10-17 13:31:26 -070025#include <utility>
Wei Jiaec044b02018-02-19 12:41:23 -080026#include <utils/String16.h>
27#include <utils/Vector.h>
28
Dongwon Kang0d7042d2018-10-12 16:52:14 -070029#include "jni.h"
30
Wei Jiaec044b02018-02-19 12:41:23 -080031namespace android {
32
33class AudioTrack;
34
35class MediaPlayer2AudioOutput : public MediaPlayer2Interface::AudioSink
36{
37 class CallbackData;
38
39public:
Dichen Zhang23658642018-11-15 10:26:16 -080040 MediaPlayer2AudioOutput(int32_t sessionId,
Wei Jiaec044b02018-02-19 12:41:23 -080041 uid_t uid,
42 int pid,
Dichen Zhanga60eaa82018-11-13 17:14:34 +000043 const jobject attributes);
Wei Jiaec044b02018-02-19 12:41:23 -080044 virtual ~MediaPlayer2AudioOutput();
45
46 virtual bool ready() const {
Dichen Zhangf8726912018-10-17 13:31:26 -070047 return mJAudioTrack != nullptr;
Wei Jiaec044b02018-02-19 12:41:23 -080048 }
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;
Dichen Zhang23658642018-11-15 10:26:16 -080059 virtual int32_t getSessionId() const;
60 virtual void setSessionId(const int32_t id);
Wei Jiaec044b02018-02-19 12:41:23 -080061 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,
Dichen Zhang303bd2d2018-09-28 12:52:49 -070066 audio_format_t format,
Wei Jiaec044b02018-02-19 12:41:23 -080067 AudioCallback cb, void *cookie,
68 audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
69 const audio_offload_info_t *offloadInfo = NULL,
Wei Jiaec044b02018-02-19 12:41:23 -080070 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();
Dichen Zhangc2465c52018-11-12 11:56:05 -080078 void setAudioAttributes(const jobject attributes);
Dichen Zhangf8726912018-10-17 13:31:26 -070079 virtual audio_stream_type_t getAudioStreamType() const;
Wei Jiaec044b02018-02-19 12:41:23 -080080
Dichen Zhang7398ca02018-10-15 10:25:12 -070081 void setVolume(float volume);
Wei Jiaec044b02018-02-19 12:41:23 -080082 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();
Wei Jiaec044b02018-02-19 12:41:23 -080091 virtual bool needsTrailingPadding() {
92 return true;
93 // TODO: return correct value.
94 //return mNextOutput == NULL;
95 }
Wei Jiaec044b02018-02-19 12:41:23 -080096 // AudioRouting
Dongwon Kang0d7042d2018-10-12 16:52:14 -070097 virtual status_t setPreferredDevice(jobject device);
98 virtual jobject getRoutedDevice();
Dichen Zhangf8726912018-10-17 13:31:26 -070099 virtual status_t addAudioDeviceCallback(jobject routingDelegate);
100 virtual status_t removeAudioDeviceCallback(jobject listener);
Wei Jiaec044b02018-02-19 12:41:23 -0800101
102private:
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
Dichen Zhangf8726912018-10-17 13:31:26 -0700109 sp<JAudioTrack> mJAudioTrack;
Wei Jiaec044b02018-02-19 12:41:23 -0800110 AudioCallback mCallback;
111 void * mCallbackCookie;
112 CallbackData * mCallbackData;
Dichen Zhangc2465c52018-11-12 11:56:05 -0800113 sp<JObjectHolder> mAttributes;
Dichen Zhang7398ca02018-10-15 10:25:12 -0700114 float mVolume;
Wei Jiaec044b02018-02-19 12:41:23 -0800115 AudioPlaybackRate mPlaybackRate;
116 uint32_t mSampleRateHz; // sample rate of the content, as set in open()
117 float mMsecsPerFrame;
118 size_t mFrameSize;
Dichen Zhang23658642018-11-15 10:26:16 -0800119 int32_t mSessionId;
Wei Jiaec044b02018-02-19 12:41:23 -0800120 uid_t mUid;
121 int mPid;
122 float mSendLevel;
123 int mAuxEffectId;
124 audio_output_flags_t mFlags;
Dongwon Kang0d7042d2018-10-12 16:52:14 -0700125 sp<JObjectHolder> mPreferredDevice;
Wei Jiaec044b02018-02-19 12:41:23 -0800126 mutable Mutex mLock;
Dichen Zhang2a1a52c2019-03-14 16:57:47 -0700127
128 // <listener, routingDelegate>
129 Vector<std::pair<sp<JObjectHolder>, sp<JObjectHolder>>> mRoutingDelegates;
Wei Jiaec044b02018-02-19 12:41:23 -0800130
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:
141 explicit CallbackData(MediaPlayer2AudioOutput *cookie) {
142 mData = cookie;
143 mSwitching = false;
144 }
145 MediaPlayer2AudioOutput *getOutput() const {
146 return mData;
147 }
148 void setOutput(MediaPlayer2AudioOutput* newcookie) {
149 mData = newcookie;
150 }
151 // lock/unlock are used by the callback before accessing the payload of this object
152 void lock() const {
153 mLock.lock();
154 }
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.
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 }
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