Home | History | Annotate | Download | only in libstagefright
      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 <binder/IPCThreadState.h>
     22 #include <media/AudioTrack.h>
     23 #include <media/stagefright/AudioPlayer.h>
     24 #include <media/stagefright/MediaDebug.h>
     25 #include <media/stagefright/MediaDefs.h>
     26 #include <media/stagefright/MediaErrors.h>
     27 #include <media/stagefright/MediaSource.h>
     28 #include <media/stagefright/MetaData.h>
     29 
     30 #include "include/AwesomePlayer.h"
     31 
     32 namespace android {
     33 
     34 AudioPlayer::AudioPlayer(
     35         const sp<MediaPlayerBase::AudioSink> &audioSink,
     36         AwesomePlayer *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 
     56 AudioPlayer::~AudioPlayer() {
     57     if (mStarted) {
     58         reset();
     59     }
     60 }
     61 
     62 void AudioPlayer::setSource(const sp<MediaSource> &source) {
     63     CHECK_EQ(mSource, NULL);
     64     mSource = source;
     65 }
     66 
     67 status_t AudioPlayer::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, AudioSystem::PCM_16_BIT,
    114                 DEFAULT_AUDIOSINK_BUFFERCOUNT,
    115                 &AudioPlayer::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                 AudioSystem::MUSIC, mSampleRate, AudioSystem::PCM_16_BIT,
    136                 (numChannels == 2)
    137                     ? AudioSystem::CHANNEL_OUT_STEREO
    138                     : AudioSystem::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 
    168 void AudioPlayer::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 
    186 void AudioPlayer::resume() {
    187     CHECK(mStarted);
    188 
    189     if (mAudioSink.get() != NULL) {
    190         mAudioSink->start();
    191     } else {
    192         mAudioTrack->start();
    193     }
    194 }
    195 
    196 void AudioPlayer::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("AudioPlayer 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
    246 void AudioPlayer::AudioCallback(int event, void *user, void *info) {
    247     static_cast<AudioPlayer *>(user)->AudioCallback(event, info);
    248 }
    249 
    250 bool AudioPlayer::isSeeking() {
    251     Mutex::Autolock autoLock(mLock);
    252     return mSeeking;
    253 }
    254 
    255 bool AudioPlayer::reachedEOS(status_t *finalStatus) {
    256     *finalStatus = OK;
    257 
    258     Mutex::Autolock autoLock(mLock);
    259     *finalStatus = mFinalStatus;
    260     return mReachedEOS;
    261 }
    262 
    263 // static
    264 size_t AudioPlayer::AudioSinkCallback(
    265         MediaPlayerBase::AudioSink *audioSink,
    266         void *buffer, size_t size, void *cookie) {
    267     AudioPlayer *me = (AudioPlayer *)cookie;
    268 
    269     return me->fillBuffer(buffer, size);
    270 }
    271 
    272 void AudioPlayer::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 
    283 size_t AudioPlayer::fillBuffer(void *data, size_t size) {
    284     if (mNumFramesPlayed == 0) {
    285         LOGV("AudioCallback");
    286     }
    287 
    288     if (mReachedEOS) {
    289         return 0;
    290     }
    291 
    292     size_t size_done = 0;
    293     size_t size_remaining = size;
    294     while (size_remaining > 0) {
    295         MediaSource::ReadOptions options;
    296 
    297         {
    298             Mutex::Autolock autoLock(mLock);
    299 
    300             if (mSeeking) {
    301                 if (mIsFirstBuffer) {
    302                     if (mFirstBuffer != NULL) {
    303                         mFirstBuffer->release();
    304                         mFirstBuffer = NULL;
    305                     }
    306                     mIsFirstBuffer = false;
    307                 }
    308 
    309                 options.setSeekTo(mSeekTimeUs);
    310 
    311                 if (mInputBuffer != NULL) {
    312                     mInputBuffer->release();
    313                     mInputBuffer = NULL;
    314                 }
    315 
    316                 mSeeking = false;
    317                 if (mObserver) {
    318                     mObserver->postAudioSeekComplete();
    319                 }
    320             }
    321         }
    322 
    323         if (mInputBuffer == NULL) {
    324             status_t err;
    325 
    326             if (mIsFirstBuffer) {
    327                 mInputBuffer = mFirstBuffer;
    328                 mFirstBuffer = NULL;
    329                 err = mFirstBufferResult;
    330 
    331                 mIsFirstBuffer = false;
    332             } else {
    333                 err = mSource->read(&mInputBuffer, &options);
    334             }
    335 
    336             CHECK((err == OK && mInputBuffer != NULL)
    337                    || (err != OK && mInputBuffer == NULL));
    338 
    339             Mutex::Autolock autoLock(mLock);
    340 
    341             if (err != OK) {
    342                 if (mObserver && !mReachedEOS) {
    343                     mObserver->postAudioEOS();
    344                 }
    345 
    346                 mReachedEOS = true;
    347                 mFinalStatus = err;
    348                 break;
    349             }
    350 
    351             CHECK(mInputBuffer->meta_data()->findInt64(
    352                         kKeyTime, &mPositionTimeMediaUs));
    353 
    354             mPositionTimeRealUs =
    355                 ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
    356                     / mSampleRate;
    357 
    358             LOGV("buffer->size() = %d, "
    359                  "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
    360                  mInputBuffer->range_length(),
    361                  mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
    362         }
    363 
    364         if (mInputBuffer->range_length() == 0) {
    365             mInputBuffer->release();
    366             mInputBuffer = NULL;
    367 
    368             continue;
    369         }
    370 
    371         size_t copy = size_remaining;
    372         if (copy > mInputBuffer->range_length()) {
    373             copy = mInputBuffer->range_length();
    374         }
    375 
    376         memcpy((char *)data + size_done,
    377                (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
    378                copy);
    379 
    380         mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
    381                                 mInputBuffer->range_length() - copy);
    382 
    383         size_done += copy;
    384         size_remaining -= copy;
    385     }
    386 
    387     Mutex::Autolock autoLock(mLock);
    388     mNumFramesPlayed += size_done / mFrameSize;
    389 
    390     return size_done;
    391 }
    392 
    393 int64_t AudioPlayer::getRealTimeUs() {
    394     Mutex::Autolock autoLock(mLock);
    395     return getRealTimeUsLocked();
    396 }
    397 
    398 int64_t AudioPlayer::getRealTimeUsLocked() const {
    399     return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
    400 }
    401 
    402 int64_t AudioPlayer::getMediaTimeUs() {
    403     Mutex::Autolock autoLock(mLock);
    404 
    405     if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
    406         return 0;
    407     }
    408 
    409     int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs;
    410     if (realTimeOffset < 0) {
    411         realTimeOffset = 0;
    412     }
    413 
    414     return mPositionTimeMediaUs + realTimeOffset;
    415 }
    416 
    417 bool AudioPlayer::getMediaTimeMapping(
    418         int64_t *realtime_us, int64_t *mediatime_us) {
    419     Mutex::Autolock autoLock(mLock);
    420 
    421     *realtime_us = mPositionTimeRealUs;
    422     *mediatime_us = mPositionTimeMediaUs;
    423 
    424     return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
    425 }
    426 
    427 status_t AudioPlayer::seekTo(int64_t time_us) {
    428     Mutex::Autolock autoLock(mLock);
    429 
    430     mSeeking = true;
    431     mReachedEOS = false;
    432     mSeekTimeUs = time_us;
    433 
    434     if (mAudioSink != NULL) {
    435         mAudioSink->flush();
    436     } else {
    437         mAudioTrack->flush();
    438     }
    439 
    440     return OK;
    441 }
    442 
    443 }
    444