• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 "AudioPlayerBase"
19 #include <utils/Log.h>
20 
21 #include <binder/IPCThreadState.h>
22 #include <media/AudioTrack.h>
23 #include <media/stagefright/MediaDebug.h>
24 #include <media/stagefright/MediaDefs.h>
25 #include <media/stagefright/MediaErrors.h>
26 #include <media/stagefright/MediaSource.h>
27 #include <media/stagefright/MetaData.h>
28 
29 #include "AudioPlayerBase.h"
30 #include "PreviewPlayerBase.h"
31 
32 namespace android {
33 
AudioPlayerBase(const sp<MediaPlayerBase::AudioSink> & audioSink,PreviewPlayerBase * observer)34 AudioPlayerBase::AudioPlayerBase(
35         const sp<MediaPlayerBase::AudioSink> &audioSink,
36         PreviewPlayerBase *observer)
37     : mAudioTrack(NULL),
38       mInputBuffer(NULL),
39       mSampleRate(0),
40       mLatencyUs(0),
41       mFrameSize(0),
42       mNumFramesPlayed(0),
43       mPositionTimeMediaUs(-1),
44       mPositionTimeRealUs(-1),
45       mSeeking(false),
46       mReachedEOS(false),
47       mFinalStatus(OK),
48       mStarted(false),
49       mIsFirstBuffer(false),
50       mFirstBufferResult(OK),
51       mFirstBuffer(NULL),
52       mAudioSink(audioSink),
53       mObserver(observer) {
54 }
55 
~AudioPlayerBase()56 AudioPlayerBase::~AudioPlayerBase() {
57     if (mStarted) {
58         reset();
59     }
60 }
61 
setSource(const sp<MediaSource> & source)62 void AudioPlayerBase::setSource(const sp<MediaSource> &source) {
63     CHECK_EQ(mSource, NULL);
64     mSource = source;
65 }
66 
start(bool sourceAlreadyStarted)67 status_t AudioPlayerBase::start(bool sourceAlreadyStarted) {
68     CHECK(!mStarted);
69     CHECK(mSource != NULL);
70 
71     status_t err;
72     if (!sourceAlreadyStarted) {
73         err = mSource->start();
74 
75         if (err != OK) {
76             return err;
77         }
78     }
79 
80     // We allow an optional INFO_FORMAT_CHANGED at the very beginning
81     // of playback, if there is one, getFormat below will retrieve the
82     // updated format, if there isn't, we'll stash away the valid buffer
83     // of data to be used on the first audio callback.
84 
85     CHECK(mFirstBuffer == NULL);
86 
87     mFirstBufferResult = mSource->read(&mFirstBuffer);
88     if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
89         LOGV("INFO_FORMAT_CHANGED!!!");
90 
91         CHECK(mFirstBuffer == NULL);
92         mFirstBufferResult = OK;
93         mIsFirstBuffer = false;
94     } else {
95         mIsFirstBuffer = true;
96     }
97 
98     sp<MetaData> format = mSource->getFormat();
99     const char *mime;
100     bool success = format->findCString(kKeyMIMEType, &mime);
101     CHECK(success);
102     CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
103 
104     success = format->findInt32(kKeySampleRate, &mSampleRate);
105     CHECK(success);
106 
107     int32_t numChannels;
108     success = format->findInt32(kKeyChannelCount, &numChannels);
109     CHECK(success);
110 
111     if (mAudioSink.get() != NULL) {
112         status_t err = mAudioSink->open(
113                 mSampleRate, numChannels, AUDIO_FORMAT_PCM_16_BIT,
114                 DEFAULT_AUDIOSINK_BUFFERCOUNT,
115                 &AudioPlayerBase::AudioSinkCallback, this);
116         if (err != OK) {
117             if (mFirstBuffer != NULL) {
118                 mFirstBuffer->release();
119                 mFirstBuffer = NULL;
120             }
121 
122             if (!sourceAlreadyStarted) {
123                 mSource->stop();
124             }
125 
126             return err;
127         }
128 
129         mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
130         mFrameSize = mAudioSink->frameSize();
131 
132         mAudioSink->start();
133     } else {
134         mAudioTrack = new AudioTrack(
135                 AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT,
136                 (numChannels == 2)
137                     ? AUDIO_CHANNEL_OUT_STEREO
138                     : AUDIO_CHANNEL_OUT_MONO,
139                 0, 0, &AudioCallback, this, 0);
140 
141         if ((err = mAudioTrack->initCheck()) != OK) {
142             delete mAudioTrack;
143             mAudioTrack = NULL;
144 
145             if (mFirstBuffer != NULL) {
146                 mFirstBuffer->release();
147                 mFirstBuffer = NULL;
148             }
149 
150             if (!sourceAlreadyStarted) {
151                 mSource->stop();
152             }
153 
154             return err;
155         }
156 
157         mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
158         mFrameSize = mAudioTrack->frameSize();
159 
160         mAudioTrack->start();
161     }
162 
163     mStarted = true;
164 
165     return OK;
166 }
167 
pause(bool playPendingSamples)168 void AudioPlayerBase::pause(bool playPendingSamples) {
169     CHECK(mStarted);
170 
171     if (playPendingSamples) {
172         if (mAudioSink.get() != NULL) {
173             mAudioSink->stop();
174         } else {
175             mAudioTrack->stop();
176         }
177     } else {
178         if (mAudioSink.get() != NULL) {
179             mAudioSink->pause();
180         } else {
181             mAudioTrack->pause();
182         }
183     }
184 }
185 
resume()186 void AudioPlayerBase::resume() {
187     CHECK(mStarted);
188 
189     if (mAudioSink.get() != NULL) {
190         mAudioSink->start();
191     } else {
192         mAudioTrack->start();
193     }
194 }
195 
reset()196 void AudioPlayerBase::reset() {
197     CHECK(mStarted);
198 
199     if (mAudioSink.get() != NULL) {
200         mAudioSink->stop();
201         mAudioSink->close();
202     } else {
203         mAudioTrack->stop();
204 
205         delete mAudioTrack;
206         mAudioTrack = NULL;
207     }
208 
209     // Make sure to release any buffer we hold onto so that the
210     // source is able to stop().
211 
212     if (mFirstBuffer != NULL) {
213         mFirstBuffer->release();
214         mFirstBuffer = NULL;
215     }
216 
217     if (mInputBuffer != NULL) {
218         LOGV("AudioPlayerBase releasing input buffer.");
219 
220         mInputBuffer->release();
221         mInputBuffer = NULL;
222     }
223 
224     mSource->stop();
225 
226     // The following hack is necessary to ensure that the OMX
227     // component is completely released by the time we may try
228     // to instantiate it again.
229     wp<MediaSource> tmp = mSource;
230     mSource.clear();
231     while (tmp.promote() != NULL) {
232         usleep(1000);
233     }
234     IPCThreadState::self()->flushCommands();
235 
236     mNumFramesPlayed = 0;
237     mPositionTimeMediaUs = -1;
238     mPositionTimeRealUs = -1;
239     mSeeking = false;
240     mReachedEOS = false;
241     mFinalStatus = OK;
242     mStarted = false;
243 }
244 
245 // static
AudioCallback(int event,void * user,void * info)246 void AudioPlayerBase::AudioCallback(int event, void *user, void *info) {
247     static_cast<AudioPlayerBase *>(user)->AudioCallback(event, info);
248 }
249 
isSeeking()250 bool AudioPlayerBase::isSeeking() {
251     Mutex::Autolock autoLock(mLock);
252     return mSeeking;
253 }
254 
reachedEOS(status_t * finalStatus)255 bool AudioPlayerBase::reachedEOS(status_t *finalStatus) {
256     *finalStatus = OK;
257 
258     Mutex::Autolock autoLock(mLock);
259     *finalStatus = mFinalStatus;
260     return mReachedEOS;
261 }
262 
263 // static
AudioSinkCallback(MediaPlayerBase::AudioSink * audioSink,void * buffer,size_t size,void * cookie)264 size_t AudioPlayerBase::AudioSinkCallback(
265         MediaPlayerBase::AudioSink *audioSink,
266         void *buffer, size_t size, void *cookie) {
267     AudioPlayerBase *me = (AudioPlayerBase *)cookie;
268 
269     return me->fillBuffer(buffer, size);
270 }
271 
AudioCallback(int event,void * info)272 void AudioPlayerBase::AudioCallback(int event, void *info) {
273     if (event != AudioTrack::EVENT_MORE_DATA) {
274         return;
275     }
276 
277     AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
278     size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
279 
280     buffer->size = numBytesWritten;
281 }
282 
getNumFramesPendingPlayout() const283 uint32_t AudioPlayerBase::getNumFramesPendingPlayout() const {
284     uint32_t numFramesPlayedOut;
285     status_t err;
286 
287     if (mAudioSink != NULL) {
288         err = mAudioSink->getPosition(&numFramesPlayedOut);
289     } else {
290         err = mAudioTrack->getPosition(&numFramesPlayedOut);
291     }
292 
293     if (err != OK || mNumFramesPlayed < numFramesPlayedOut) {
294         return 0;
295     }
296 
297     // mNumFramesPlayed is the number of frames submitted
298     // to the audio sink for playback, but not all of them
299     // may have played out by now.
300     return mNumFramesPlayed - numFramesPlayedOut;
301 }
302 
fillBuffer(void * data,size_t size)303 size_t AudioPlayerBase::fillBuffer(void *data, size_t size) {
304     if (mNumFramesPlayed == 0) {
305         LOGV("AudioCallback");
306     }
307 
308     if (mReachedEOS) {
309         return 0;
310     }
311 
312     bool postSeekComplete = false;
313     bool postEOS = false;
314     int64_t postEOSDelayUs = 0;
315 
316     size_t size_done = 0;
317     size_t size_remaining = size;
318     while (size_remaining > 0) {
319         MediaSource::ReadOptions options;
320 
321         {
322             Mutex::Autolock autoLock(mLock);
323 
324             if (mSeeking) {
325                 if (mIsFirstBuffer) {
326                     if (mFirstBuffer != NULL) {
327                         mFirstBuffer->release();
328                         mFirstBuffer = NULL;
329                     }
330                     mIsFirstBuffer = false;
331                 }
332 
333                 options.setSeekTo(mSeekTimeUs);
334 
335                 if (mInputBuffer != NULL) {
336                     mInputBuffer->release();
337                     mInputBuffer = NULL;
338                 }
339 
340                 mSeeking = false;
341                 if (mObserver) {
342                     postSeekComplete = true;
343                 }
344             }
345         }
346 
347         if (mInputBuffer == NULL) {
348             status_t err;
349 
350             if (mIsFirstBuffer) {
351                 mInputBuffer = mFirstBuffer;
352                 mFirstBuffer = NULL;
353                 err = mFirstBufferResult;
354 
355                 mIsFirstBuffer = false;
356             } else {
357                 err = mSource->read(&mInputBuffer, &options);
358             }
359 
360             CHECK((err == OK && mInputBuffer != NULL)
361                    || (err != OK && mInputBuffer == NULL));
362 
363             Mutex::Autolock autoLock(mLock);
364 
365             if (err != OK) {
366                 if (mObserver && !mReachedEOS) {
367                     // We don't want to post EOS right away but only
368                     // after all frames have actually been played out.
369 
370                     // These are the number of frames submitted to the
371                     // AudioTrack that you haven't heard yet.
372                     uint32_t numFramesPendingPlayout =
373                         getNumFramesPendingPlayout();
374 
375                     // These are the number of frames we're going to
376                     // submit to the AudioTrack by returning from this
377                     // callback.
378                     uint32_t numAdditionalFrames = size_done / mFrameSize;
379 
380                     numFramesPendingPlayout += numAdditionalFrames;
381 
382                     int64_t timeToCompletionUs =
383                         (1000000ll * numFramesPendingPlayout) / mSampleRate;
384 
385                     LOGV("total number of frames played: %lld (%lld us)",
386                             (mNumFramesPlayed + numAdditionalFrames),
387                             1000000ll * (mNumFramesPlayed + numAdditionalFrames)
388                                 / mSampleRate);
389 
390                     LOGV("%d frames left to play, %lld us (%.2f secs)",
391                          numFramesPendingPlayout,
392                          timeToCompletionUs, timeToCompletionUs / 1E6);
393 
394                     postEOS = true;
395                     postEOSDelayUs = timeToCompletionUs + mLatencyUs;
396                 }
397 
398                 mReachedEOS = true;
399                 mFinalStatus = err;
400                 break;
401             }
402 
403             CHECK(mInputBuffer->meta_data()->findInt64(
404                         kKeyTime, &mPositionTimeMediaUs));
405 
406             mPositionTimeRealUs =
407                 ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
408                     / mSampleRate;
409 
410             LOGV("buffer->size() = %d, "
411                  "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
412                  mInputBuffer->range_length(),
413                  mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
414         }
415 
416         if (mInputBuffer->range_length() == 0) {
417             mInputBuffer->release();
418             mInputBuffer = NULL;
419 
420             continue;
421         }
422 
423         size_t copy = size_remaining;
424         if (copy > mInputBuffer->range_length()) {
425             copy = mInputBuffer->range_length();
426         }
427 
428         memcpy((char *)data + size_done,
429                (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
430                copy);
431 
432         mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
433                                 mInputBuffer->range_length() - copy);
434 
435         size_done += copy;
436         size_remaining -= copy;
437     }
438 
439     {
440         Mutex::Autolock autoLock(mLock);
441         mNumFramesPlayed += size_done / mFrameSize;
442     }
443 
444     if (postEOS) {
445         mObserver->postAudioEOS(postEOSDelayUs);
446     }
447 
448     if (postSeekComplete) {
449         mObserver->postAudioSeekComplete();
450     }
451 
452     return size_done;
453 }
454 
getRealTimeUs()455 int64_t AudioPlayerBase::getRealTimeUs() {
456     Mutex::Autolock autoLock(mLock);
457     return getRealTimeUsLocked();
458 }
459 
getRealTimeUsLocked() const460 int64_t AudioPlayerBase::getRealTimeUsLocked() const {
461     return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
462 }
463 
getMediaTimeUs()464 int64_t AudioPlayerBase::getMediaTimeUs() {
465     Mutex::Autolock autoLock(mLock);
466 
467     if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
468         if (mSeeking) {
469             return mSeekTimeUs;
470         }
471 
472         return 0;
473     }
474 
475     int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs;
476     if (realTimeOffset < 0) {
477         realTimeOffset = 0;
478     }
479 
480     return mPositionTimeMediaUs + realTimeOffset;
481 }
482 
getMediaTimeMapping(int64_t * realtime_us,int64_t * mediatime_us)483 bool AudioPlayerBase::getMediaTimeMapping(
484         int64_t *realtime_us, int64_t *mediatime_us) {
485     Mutex::Autolock autoLock(mLock);
486 
487     *realtime_us = mPositionTimeRealUs;
488     *mediatime_us = mPositionTimeMediaUs;
489 
490     return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
491 }
492 
seekTo(int64_t time_us)493 status_t AudioPlayerBase::seekTo(int64_t time_us) {
494     Mutex::Autolock autoLock(mLock);
495 
496     mSeeking = true;
497     mPositionTimeRealUs = mPositionTimeMediaUs = -1;
498     mReachedEOS = false;
499     mSeekTimeUs = time_us;
500 
501     if (mAudioSink != NULL) {
502         mAudioSink->flush();
503     } else {
504         mAudioTrack->flush();
505     }
506 
507     return OK;
508 }
509 
510 }
511