1 /*
2 * Copyright (C) 2009 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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "AudioPlayer"
19 #include <utils/Log.h>
20
21 #include <media/AudioTrack.h>
22 #include <media/stagefright/AudioPlayer.h>
23 #include <media/stagefright/MediaDebug.h>
24 #include <media/stagefright/MediaDefs.h>
25 #include <media/stagefright/MediaSource.h>
26 #include <media/stagefright/MetaData.h>
27
28 namespace android {
29
AudioPlayer(const sp<MediaPlayerBase::AudioSink> & audioSink)30 AudioPlayer::AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink)
31 : mAudioTrack(NULL),
32 mInputBuffer(NULL),
33 mSampleRate(0),
34 mLatencyUs(0),
35 mFrameSize(0),
36 mNumFramesPlayed(0),
37 mPositionTimeMediaUs(-1),
38 mPositionTimeRealUs(-1),
39 mSeeking(false),
40 mStarted(false),
41 mAudioSink(audioSink) {
42 }
43
~AudioPlayer()44 AudioPlayer::~AudioPlayer() {
45 if (mStarted) {
46 stop();
47 }
48 }
49
setSource(const sp<MediaSource> & source)50 void AudioPlayer::setSource(const sp<MediaSource> &source) {
51 CHECK_EQ(mSource, NULL);
52 mSource = source;
53 }
54
start()55 void AudioPlayer::start() {
56 CHECK(!mStarted);
57 CHECK(mSource != NULL);
58
59 status_t err = mSource->start();
60 CHECK_EQ(err, OK);
61
62 sp<MetaData> format = mSource->getFormat();
63 const char *mime;
64 bool success = format->findCString(kKeyMIMEType, &mime);
65 CHECK(success);
66 CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
67
68 success = format->findInt32(kKeySampleRate, &mSampleRate);
69 CHECK(success);
70
71 int32_t numChannels;
72 success = format->findInt32(kKeyChannelCount, &numChannels);
73 CHECK(success);
74
75 if (mAudioSink.get() != NULL) {
76 status_t err = mAudioSink->open(
77 mSampleRate, numChannels, AudioSystem::PCM_16_BIT,
78 DEFAULT_AUDIOSINK_BUFFERCOUNT,
79 &AudioPlayer::AudioSinkCallback, this);
80 CHECK_EQ(err, OK);
81
82 mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
83 mFrameSize = mAudioSink->frameSize();
84
85 mAudioSink->start();
86 } else {
87 mAudioTrack = new AudioTrack(
88 AudioSystem::MUSIC, mSampleRate, AudioSystem::PCM_16_BIT,
89 (numChannels == 2)
90 ? AudioSystem::CHANNEL_OUT_STEREO
91 : AudioSystem::CHANNEL_OUT_MONO,
92 8192, 0, &AudioCallback, this, 0);
93
94 CHECK_EQ(mAudioTrack->initCheck(), OK);
95
96 mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
97 mFrameSize = mAudioTrack->frameSize();
98
99 mAudioTrack->start();
100 }
101
102 mStarted = true;
103 }
104
pause()105 void AudioPlayer::pause() {
106 CHECK(mStarted);
107
108 if (mAudioSink.get() != NULL) {
109 mAudioSink->pause();
110 } else {
111 mAudioTrack->stop();
112 }
113 }
114
resume()115 void AudioPlayer::resume() {
116 CHECK(mStarted);
117
118 if (mAudioSink.get() != NULL) {
119 mAudioSink->start();
120 } else {
121 mAudioTrack->start();
122 }
123 }
124
stop()125 void AudioPlayer::stop() {
126 CHECK(mStarted);
127
128 if (mAudioSink.get() != NULL) {
129 mAudioSink->stop();
130 } else {
131 mAudioTrack->stop();
132
133 delete mAudioTrack;
134 mAudioTrack = NULL;
135 }
136
137 // Make sure to release any buffer we hold onto so that the
138 // source is able to stop().
139 if (mInputBuffer != NULL) {
140 LOGV("AudioPlayer releasing input buffer.");
141
142 mInputBuffer->release();
143 mInputBuffer = NULL;
144 }
145
146 mSource->stop();
147
148 mNumFramesPlayed = 0;
149 mPositionTimeMediaUs = -1;
150 mPositionTimeRealUs = -1;
151 mSeeking = false;
152 mStarted = false;
153 }
154
155 // static
AudioCallback(int event,void * user,void * info)156 void AudioPlayer::AudioCallback(int event, void *user, void *info) {
157 static_cast<AudioPlayer *>(user)->AudioCallback(event, info);
158 }
159
160 // static
AudioSinkCallback(MediaPlayerBase::AudioSink * audioSink,void * buffer,size_t size,void * cookie)161 void AudioPlayer::AudioSinkCallback(
162 MediaPlayerBase::AudioSink *audioSink,
163 void *buffer, size_t size, void *cookie) {
164 AudioPlayer *me = (AudioPlayer *)cookie;
165
166 me->fillBuffer(buffer, size);
167 }
168
AudioCallback(int event,void * info)169 void AudioPlayer::AudioCallback(int event, void *info) {
170 if (event != AudioTrack::EVENT_MORE_DATA) {
171 return;
172 }
173
174 AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
175 fillBuffer(buffer->raw, buffer->size);
176 }
177
fillBuffer(void * data,size_t size)178 void AudioPlayer::fillBuffer(void *data, size_t size) {
179 if (mNumFramesPlayed == 0) {
180 LOGV("AudioCallback");
181 }
182
183 size_t size_done = 0;
184 size_t size_remaining = size;
185 while (size_remaining > 0) {
186 MediaSource::ReadOptions options;
187
188 {
189 Mutex::Autolock autoLock(mLock);
190
191 if (mSeeking) {
192 options.setSeekTo(mSeekTimeUs);
193
194 if (mInputBuffer != NULL) {
195 mInputBuffer->release();
196 mInputBuffer = NULL;
197 }
198 mSeeking = false;
199 }
200 }
201
202 if (mInputBuffer == NULL) {
203 status_t err = mSource->read(&mInputBuffer, &options);
204
205 CHECK((err == OK && mInputBuffer != NULL)
206 || (err != OK && mInputBuffer == NULL));
207
208 if (err != OK) {
209 memset((char *)data + size_done, 0, size_remaining);
210 break;
211 }
212
213 int32_t units, scale;
214 bool success =
215 mInputBuffer->meta_data()->findInt32(kKeyTimeUnits, &units);
216 success = success &&
217 mInputBuffer->meta_data()->findInt32(kKeyTimeScale, &scale);
218 CHECK(success);
219
220 Mutex::Autolock autoLock(mLock);
221 mPositionTimeMediaUs = (int64_t)units * 1000000 / scale;
222
223 mPositionTimeRealUs =
224 ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
225 / mSampleRate;
226
227 LOGV("buffer->size() = %d, "
228 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
229 mInputBuffer->range_length(),
230 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
231 }
232
233 if (mInputBuffer->range_length() == 0) {
234 mInputBuffer->release();
235 mInputBuffer = NULL;
236
237 continue;
238 }
239
240 size_t copy = size_remaining;
241 if (copy > mInputBuffer->range_length()) {
242 copy = mInputBuffer->range_length();
243 }
244
245 memcpy((char *)data + size_done,
246 (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
247 copy);
248
249 mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
250 mInputBuffer->range_length() - copy);
251
252 size_done += copy;
253 size_remaining -= copy;
254 }
255
256 Mutex::Autolock autoLock(mLock);
257 mNumFramesPlayed += size / mFrameSize;
258 }
259
getRealTimeUs()260 int64_t AudioPlayer::getRealTimeUs() {
261 Mutex::Autolock autoLock(mLock);
262 return getRealTimeUsLocked();
263 }
264
getRealTimeUsLocked() const265 int64_t AudioPlayer::getRealTimeUsLocked() const {
266 return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
267 }
268
getMediaTimeUs()269 int64_t AudioPlayer::getMediaTimeUs() {
270 Mutex::Autolock autoLock(mLock);
271
272 return mPositionTimeMediaUs + (getRealTimeUsLocked() - mPositionTimeRealUs);
273 }
274
getMediaTimeMapping(int64_t * realtime_us,int64_t * mediatime_us)275 bool AudioPlayer::getMediaTimeMapping(
276 int64_t *realtime_us, int64_t *mediatime_us) {
277 Mutex::Autolock autoLock(mLock);
278
279 *realtime_us = mPositionTimeRealUs;
280 *mediatime_us = mPositionTimeMediaUs;
281
282 return mPositionTimeRealUs != -1 || mPositionTimeMediaUs != -1;
283 }
284
seekTo(int64_t time_us)285 status_t AudioPlayer::seekTo(int64_t time_us) {
286 Mutex::Autolock autoLock(mLock);
287
288 mSeeking = true;
289 mSeekTimeUs = time_us;
290
291 return OK;
292 }
293
294 }
295