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