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 "AwesomePlayer"
     19 #include <utils/Log.h>
     20 
     21 #include <dlfcn.h>
     22 
     23 #include "include/ARTSPController.h"
     24 #include "include/AwesomePlayer.h"
     25 #include "include/LiveSource.h"
     26 #include "include/SoftwareRenderer.h"
     27 #include "include/NuCachedSource2.h"
     28 #include "include/ThrottledSource.h"
     29 #include "include/MPEG2TSExtractor.h"
     30 
     31 #include "ARTPSession.h"
     32 #include "APacketSource.h"
     33 #include "ASessionDescription.h"
     34 #include "UDPPusher.h"
     35 
     36 #include <binder/IPCThreadState.h>
     37 #include <media/stagefright/AudioPlayer.h>
     38 #include <media/stagefright/DataSource.h>
     39 #include <media/stagefright/FileSource.h>
     40 #include <media/stagefright/MediaBuffer.h>
     41 #include <media/stagefright/MediaDefs.h>
     42 #include <media/stagefright/MediaExtractor.h>
     43 #include <media/stagefright/MediaDebug.h>
     44 #include <media/stagefright/MediaSource.h>
     45 #include <media/stagefright/MetaData.h>
     46 #include <media/stagefright/OMXCodec.h>
     47 
     48 #include <surfaceflinger/ISurface.h>
     49 
     50 #include <media/stagefright/foundation/ALooper.h>
     51 
     52 namespace android {
     53 
     54 static int64_t kLowWaterMarkUs = 2000000ll;  // 2secs
     55 static int64_t kHighWaterMarkUs = 10000000ll;  // 10secs
     56 
     57 struct AwesomeEvent : public TimedEventQueue::Event {
     58     AwesomeEvent(
     59             AwesomePlayer *player,
     60             void (AwesomePlayer::*method)())
     61         : mPlayer(player),
     62           mMethod(method) {
     63     }
     64 
     65 protected:
     66     virtual ~AwesomeEvent() {}
     67 
     68     virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
     69         (mPlayer->*mMethod)();
     70     }
     71 
     72 private:
     73     AwesomePlayer *mPlayer;
     74     void (AwesomePlayer::*mMethod)();
     75 
     76     AwesomeEvent(const AwesomeEvent &);
     77     AwesomeEvent &operator=(const AwesomeEvent &);
     78 };
     79 
     80 struct AwesomeRemoteRenderer : public AwesomeRenderer {
     81     AwesomeRemoteRenderer(const sp<IOMXRenderer> &target)
     82         : mTarget(target) {
     83     }
     84 
     85     virtual void render(MediaBuffer *buffer) {
     86         void *id;
     87         if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) {
     88             mTarget->render((IOMX::buffer_id)id);
     89         }
     90     }
     91 
     92 private:
     93     sp<IOMXRenderer> mTarget;
     94 
     95     AwesomeRemoteRenderer(const AwesomeRemoteRenderer &);
     96     AwesomeRemoteRenderer &operator=(const AwesomeRemoteRenderer &);
     97 };
     98 
     99 struct AwesomeLocalRenderer : public AwesomeRenderer {
    100     AwesomeLocalRenderer(
    101             bool previewOnly,
    102             const char *componentName,
    103             OMX_COLOR_FORMATTYPE colorFormat,
    104             const sp<ISurface> &surface,
    105             size_t displayWidth, size_t displayHeight,
    106             size_t decodedWidth, size_t decodedHeight,
    107             int32_t rotationDegrees)
    108         : mTarget(NULL),
    109           mLibHandle(NULL) {
    110             init(previewOnly, componentName,
    111                  colorFormat, surface, displayWidth,
    112                  displayHeight, decodedWidth, decodedHeight,
    113                  rotationDegrees);
    114     }
    115 
    116     virtual void render(MediaBuffer *buffer) {
    117         render((const uint8_t *)buffer->data() + buffer->range_offset(),
    118                buffer->range_length());
    119     }
    120 
    121     void render(const void *data, size_t size) {
    122         mTarget->render(data, size, NULL);
    123     }
    124 
    125 protected:
    126     virtual ~AwesomeLocalRenderer() {
    127         delete mTarget;
    128         mTarget = NULL;
    129 
    130         if (mLibHandle) {
    131             dlclose(mLibHandle);
    132             mLibHandle = NULL;
    133         }
    134     }
    135 
    136 private:
    137     VideoRenderer *mTarget;
    138     void *mLibHandle;
    139 
    140     void init(
    141             bool previewOnly,
    142             const char *componentName,
    143             OMX_COLOR_FORMATTYPE colorFormat,
    144             const sp<ISurface> &surface,
    145             size_t displayWidth, size_t displayHeight,
    146             size_t decodedWidth, size_t decodedHeight,
    147             int32_t rotationDegrees);
    148 
    149     AwesomeLocalRenderer(const AwesomeLocalRenderer &);
    150     AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
    151 };
    152 
    153 void AwesomeLocalRenderer::init(
    154         bool previewOnly,
    155         const char *componentName,
    156         OMX_COLOR_FORMATTYPE colorFormat,
    157         const sp<ISurface> &surface,
    158         size_t displayWidth, size_t displayHeight,
    159         size_t decodedWidth, size_t decodedHeight,
    160         int32_t rotationDegrees) {
    161     if (!previewOnly) {
    162         // We will stick to the vanilla software-color-converting renderer
    163         // for "previewOnly" mode, to avoid unneccessarily switching overlays
    164         // more often than necessary.
    165 
    166         mLibHandle = dlopen("libstagefrighthw.so", RTLD_NOW);
    167 
    168         if (mLibHandle) {
    169             typedef VideoRenderer *(*CreateRendererWithRotationFunc)(
    170                     const sp<ISurface> &surface,
    171                     const char *componentName,
    172                     OMX_COLOR_FORMATTYPE colorFormat,
    173                     size_t displayWidth, size_t displayHeight,
    174                     size_t decodedWidth, size_t decodedHeight,
    175                     int32_t rotationDegrees);
    176 
    177             typedef VideoRenderer *(*CreateRendererFunc)(
    178                     const sp<ISurface> &surface,
    179                     const char *componentName,
    180                     OMX_COLOR_FORMATTYPE colorFormat,
    181                     size_t displayWidth, size_t displayHeight,
    182                     size_t decodedWidth, size_t decodedHeight);
    183 
    184             CreateRendererWithRotationFunc funcWithRotation =
    185                 (CreateRendererWithRotationFunc)dlsym(
    186                         mLibHandle,
    187                         "_Z26createRendererWithRotationRKN7android2spINS_8"
    188                         "ISurfaceEEEPKc20OMX_COLOR_FORMATTYPEjjjji");
    189 
    190             if (funcWithRotation) {
    191                 mTarget =
    192                     (*funcWithRotation)(
    193                             surface, componentName, colorFormat,
    194                             displayWidth, displayHeight,
    195                             decodedWidth, decodedHeight,
    196                             rotationDegrees);
    197             } else {
    198                 if (rotationDegrees != 0) {
    199                     LOGW("renderer does not support rotation.");
    200                 }
    201 
    202                 CreateRendererFunc func =
    203                     (CreateRendererFunc)dlsym(
    204                             mLibHandle,
    205                             "_Z14createRendererRKN7android2spINS_8ISurfaceEEEPKc20"
    206                             "OMX_COLOR_FORMATTYPEjjjj");
    207 
    208                 if (func) {
    209                     mTarget =
    210                         (*func)(surface, componentName, colorFormat,
    211                             displayWidth, displayHeight,
    212                             decodedWidth, decodedHeight);
    213                 }
    214             }
    215         }
    216     }
    217 
    218     if (mTarget == NULL) {
    219         mTarget = new SoftwareRenderer(
    220                 colorFormat, surface, displayWidth, displayHeight,
    221                 decodedWidth, decodedHeight, rotationDegrees);
    222     }
    223 }
    224 
    225 AwesomePlayer::AwesomePlayer()
    226     : mQueueStarted(false),
    227       mTimeSource(NULL),
    228       mVideoRendererIsPreview(false),
    229       mAudioPlayer(NULL),
    230       mFlags(0),
    231       mExtractorFlags(0),
    232       mLastVideoBuffer(NULL),
    233       mVideoBuffer(NULL),
    234       mSuspensionState(NULL) {
    235     CHECK_EQ(mClient.connect(), OK);
    236 
    237     DataSource::RegisterDefaultSniffers();
    238 
    239     mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
    240     mVideoEventPending = false;
    241     mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
    242     mStreamDoneEventPending = false;
    243     mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
    244     mBufferingEventPending = false;
    245 
    246     mCheckAudioStatusEvent = new AwesomeEvent(
    247             this, &AwesomePlayer::onCheckAudioStatus);
    248 
    249     mAudioStatusEventPending = false;
    250 
    251     reset();
    252 }
    253 
    254 AwesomePlayer::~AwesomePlayer() {
    255     if (mQueueStarted) {
    256         mQueue.stop();
    257     }
    258 
    259     reset();
    260 
    261     mClient.disconnect();
    262 }
    263 
    264 void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
    265     mQueue.cancelEvent(mVideoEvent->eventID());
    266     mVideoEventPending = false;
    267     mQueue.cancelEvent(mStreamDoneEvent->eventID());
    268     mStreamDoneEventPending = false;
    269     mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
    270     mAudioStatusEventPending = false;
    271 
    272     if (!keepBufferingGoing) {
    273         mQueue.cancelEvent(mBufferingEvent->eventID());
    274         mBufferingEventPending = false;
    275     }
    276 }
    277 
    278 void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
    279     Mutex::Autolock autoLock(mLock);
    280     mListener = listener;
    281 }
    282 
    283 status_t AwesomePlayer::setDataSource(
    284         const char *uri, const KeyedVector<String8, String8> *headers) {
    285     Mutex::Autolock autoLock(mLock);
    286     return setDataSource_l(uri, headers);
    287 }
    288 
    289 status_t AwesomePlayer::setDataSource_l(
    290         const char *uri, const KeyedVector<String8, String8> *headers) {
    291     reset_l();
    292 
    293     mUri = uri;
    294 
    295     if (headers) {
    296         mUriHeaders = *headers;
    297     }
    298 
    299     // The actual work will be done during preparation in the call to
    300     // ::finishSetDataSource_l to avoid blocking the calling thread in
    301     // setDataSource for any significant time.
    302 
    303     return OK;
    304 }
    305 
    306 status_t AwesomePlayer::setDataSource(
    307         int fd, int64_t offset, int64_t length) {
    308     Mutex::Autolock autoLock(mLock);
    309 
    310     reset_l();
    311 
    312     sp<DataSource> dataSource = new FileSource(fd, offset, length);
    313 
    314     status_t err = dataSource->initCheck();
    315 
    316     if (err != OK) {
    317         return err;
    318     }
    319 
    320     mFileSource = dataSource;
    321 
    322     return setDataSource_l(dataSource);
    323 }
    324 
    325 status_t AwesomePlayer::setDataSource_l(
    326         const sp<DataSource> &dataSource) {
    327     sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
    328 
    329     if (extractor == NULL) {
    330         return UNKNOWN_ERROR;
    331     }
    332 
    333     return setDataSource_l(extractor);
    334 }
    335 
    336 status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
    337     // Attempt to approximate overall stream bitrate by summing all
    338     // tracks' individual bitrates, if not all of them advertise bitrate,
    339     // we have to fail.
    340 
    341     int64_t totalBitRate = 0;
    342 
    343     for (size_t i = 0; i < extractor->countTracks(); ++i) {
    344         sp<MetaData> meta = extractor->getTrackMetaData(i);
    345 
    346         int32_t bitrate;
    347         if (!meta->findInt32(kKeyBitRate, &bitrate)) {
    348             totalBitRate = -1;
    349             break;
    350         }
    351 
    352         totalBitRate += bitrate;
    353     }
    354 
    355     mBitrate = totalBitRate;
    356 
    357     LOGV("mBitrate = %lld bits/sec", mBitrate);
    358 
    359     bool haveAudio = false;
    360     bool haveVideo = false;
    361     for (size_t i = 0; i < extractor->countTracks(); ++i) {
    362         sp<MetaData> meta = extractor->getTrackMetaData(i);
    363 
    364         const char *mime;
    365         CHECK(meta->findCString(kKeyMIMEType, &mime));
    366 
    367         if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
    368             setVideoSource(extractor->getTrack(i));
    369             haveVideo = true;
    370         } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
    371             setAudioSource(extractor->getTrack(i));
    372             haveAudio = true;
    373 
    374             if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
    375                 // Only do this for vorbis audio, none of the other audio
    376                 // formats even support this ringtone specific hack and
    377                 // retrieving the metadata on some extractors may turn out
    378                 // to be very expensive.
    379                 sp<MetaData> fileMeta = extractor->getMetaData();
    380                 int32_t loop;
    381                 if (fileMeta != NULL
    382                         && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
    383                     mFlags |= AUTO_LOOPING;
    384                 }
    385             }
    386         }
    387 
    388         if (haveAudio && haveVideo) {
    389             break;
    390         }
    391     }
    392 
    393     if (!haveAudio && !haveVideo) {
    394         return UNKNOWN_ERROR;
    395     }
    396 
    397     mExtractorFlags = extractor->flags();
    398 
    399     return OK;
    400 }
    401 
    402 void AwesomePlayer::reset() {
    403     Mutex::Autolock autoLock(mLock);
    404     reset_l();
    405 }
    406 
    407 void AwesomePlayer::reset_l() {
    408     if (mFlags & PREPARING) {
    409         mFlags |= PREPARE_CANCELLED;
    410         if (mConnectingDataSource != NULL) {
    411             LOGI("interrupting the connection process");
    412             mConnectingDataSource->disconnect();
    413         }
    414     }
    415 
    416     while (mFlags & PREPARING) {
    417         mPreparedCondition.wait(mLock);
    418     }
    419 
    420     cancelPlayerEvents();
    421 
    422     mCachedSource.clear();
    423     mAudioTrack.clear();
    424     mVideoTrack.clear();
    425 
    426     // Shutdown audio first, so that the respone to the reset request
    427     // appears to happen instantaneously as far as the user is concerned
    428     // If we did this later, audio would continue playing while we
    429     // shutdown the video-related resources and the player appear to
    430     // not be as responsive to a reset request.
    431     if (mAudioPlayer == NULL && mAudioSource != NULL) {
    432         // If we had an audio player, it would have effectively
    433         // taken possession of the audio source and stopped it when
    434         // _it_ is stopped. Otherwise this is still our responsibility.
    435         mAudioSource->stop();
    436     }
    437     mAudioSource.clear();
    438 
    439     mTimeSource = NULL;
    440 
    441     delete mAudioPlayer;
    442     mAudioPlayer = NULL;
    443 
    444     mVideoRenderer.clear();
    445 
    446     if (mLastVideoBuffer) {
    447         mLastVideoBuffer->release();
    448         mLastVideoBuffer = NULL;
    449     }
    450 
    451     if (mVideoBuffer) {
    452         mVideoBuffer->release();
    453         mVideoBuffer = NULL;
    454     }
    455 
    456     if (mRTSPController != NULL) {
    457         mRTSPController->disconnect();
    458         mRTSPController.clear();
    459     }
    460 
    461     mRTPPusher.clear();
    462     mRTCPPusher.clear();
    463     mRTPSession.clear();
    464 
    465     if (mVideoSource != NULL) {
    466         mVideoSource->stop();
    467 
    468         // The following hack is necessary to ensure that the OMX
    469         // component is completely released by the time we may try
    470         // to instantiate it again.
    471         wp<MediaSource> tmp = mVideoSource;
    472         mVideoSource.clear();
    473         while (tmp.promote() != NULL) {
    474             usleep(1000);
    475         }
    476         IPCThreadState::self()->flushCommands();
    477     }
    478 
    479     mDurationUs = -1;
    480     mFlags = 0;
    481     mExtractorFlags = 0;
    482     mVideoWidth = mVideoHeight = -1;
    483     mTimeSourceDeltaUs = 0;
    484     mVideoTimeUs = 0;
    485 
    486     mSeeking = false;
    487     mSeekNotificationSent = false;
    488     mSeekTimeUs = 0;
    489 
    490     mUri.setTo("");
    491     mUriHeaders.clear();
    492 
    493     mFileSource.clear();
    494 
    495     delete mSuspensionState;
    496     mSuspensionState = NULL;
    497 
    498     mBitrate = -1;
    499 }
    500 
    501 void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
    502     if (mListener != NULL) {
    503         sp<MediaPlayerBase> listener = mListener.promote();
    504 
    505         if (listener != NULL) {
    506             listener->sendEvent(msg, ext1, ext2);
    507         }
    508     }
    509 }
    510 
    511 bool AwesomePlayer::getBitrate(int64_t *bitrate) {
    512     off_t size;
    513     if (mDurationUs >= 0 && mCachedSource != NULL
    514             && mCachedSource->getSize(&size) == OK) {
    515         *bitrate = size * 8000000ll / mDurationUs;  // in bits/sec
    516         return true;
    517     }
    518 
    519     if (mBitrate >= 0) {
    520         *bitrate = mBitrate;
    521         return true;
    522     }
    523 
    524     *bitrate = 0;
    525 
    526     return false;
    527 }
    528 
    529 // Returns true iff cached duration is available/applicable.
    530 bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
    531     int64_t bitrate;
    532 
    533     if (mRTSPController != NULL) {
    534         *durationUs = mRTSPController->getQueueDurationUs(eos);
    535         return true;
    536     } else if (mCachedSource != NULL && getBitrate(&bitrate)) {
    537         size_t cachedDataRemaining = mCachedSource->approxDataRemaining(eos);
    538         *durationUs = cachedDataRemaining * 8000000ll / bitrate;
    539         return true;
    540     }
    541 
    542     return false;
    543 }
    544 
    545 void AwesomePlayer::onBufferingUpdate() {
    546     Mutex::Autolock autoLock(mLock);
    547     if (!mBufferingEventPending) {
    548         return;
    549     }
    550     mBufferingEventPending = false;
    551 
    552     if (mCachedSource != NULL) {
    553         bool eos;
    554         size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&eos);
    555 
    556         if (eos) {
    557             notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
    558             if (mFlags & PREPARING) {
    559                 LOGV("cache has reached EOS, prepare is done.");
    560                 finishAsyncPrepare_l();
    561             }
    562         } else {
    563             int64_t bitrate;
    564             if (getBitrate(&bitrate)) {
    565                 size_t cachedSize = mCachedSource->cachedSize();
    566                 int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
    567 
    568                 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
    569                 if (percentage > 100) {
    570                     percentage = 100;
    571                 }
    572 
    573                 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
    574             } else {
    575                 // We don't know the bitrate of the stream, use absolute size
    576                 // limits to maintain the cache.
    577 
    578                 const size_t kLowWaterMarkBytes = 40000;
    579                 const size_t kHighWaterMarkBytes = 200000;
    580 
    581                 if ((mFlags & PLAYING) && !eos
    582                         && (cachedDataRemaining < kLowWaterMarkBytes)) {
    583                     LOGI("cache is running low (< %d) , pausing.",
    584                          kLowWaterMarkBytes);
    585                     mFlags |= CACHE_UNDERRUN;
    586                     pause_l();
    587                     notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
    588                 } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
    589                     if (mFlags & CACHE_UNDERRUN) {
    590                         LOGI("cache has filled up (> %d), resuming.",
    591                              kHighWaterMarkBytes);
    592                         mFlags &= ~CACHE_UNDERRUN;
    593                         play_l();
    594                         notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
    595                     } else if (mFlags & PREPARING) {
    596                         LOGV("cache has filled up (> %d), prepare is done",
    597                              kHighWaterMarkBytes);
    598                         finishAsyncPrepare_l();
    599                     }
    600                 }
    601             }
    602         }
    603     }
    604 
    605     int64_t cachedDurationUs;
    606     bool eos;
    607     if (getCachedDuration_l(&cachedDurationUs, &eos)) {
    608         if ((mFlags & PLAYING) && !eos
    609                 && (cachedDurationUs < kLowWaterMarkUs)) {
    610             LOGI("cache is running low (%.2f secs) , pausing.",
    611                  cachedDurationUs / 1E6);
    612             mFlags |= CACHE_UNDERRUN;
    613             pause_l();
    614             notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
    615         } else if (eos || cachedDurationUs > kHighWaterMarkUs) {
    616             if (mFlags & CACHE_UNDERRUN) {
    617                 LOGI("cache has filled up (%.2f secs), resuming.",
    618                      cachedDurationUs / 1E6);
    619                 mFlags &= ~CACHE_UNDERRUN;
    620                 play_l();
    621                 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
    622             } else if (mFlags & PREPARING) {
    623                 LOGV("cache has filled up (%.2f secs), prepare is done",
    624                      cachedDurationUs / 1E6);
    625                 finishAsyncPrepare_l();
    626             }
    627         }
    628     }
    629 
    630     postBufferingEvent_l();
    631 }
    632 
    633 void AwesomePlayer::partial_reset_l() {
    634     // Only reset the video renderer and shut down the video decoder.
    635     // Then instantiate a new video decoder and resume video playback.
    636 
    637     mVideoRenderer.clear();
    638 
    639     if (mLastVideoBuffer) {
    640         mLastVideoBuffer->release();
    641         mLastVideoBuffer = NULL;
    642     }
    643 
    644     if (mVideoBuffer) {
    645         mVideoBuffer->release();
    646         mVideoBuffer = NULL;
    647     }
    648 
    649     {
    650         mVideoSource->stop();
    651 
    652         // The following hack is necessary to ensure that the OMX
    653         // component is completely released by the time we may try
    654         // to instantiate it again.
    655         wp<MediaSource> tmp = mVideoSource;
    656         mVideoSource.clear();
    657         while (tmp.promote() != NULL) {
    658             usleep(1000);
    659         }
    660         IPCThreadState::self()->flushCommands();
    661     }
    662 
    663     CHECK_EQ(OK, initVideoDecoder(OMXCodec::kIgnoreCodecSpecificData));
    664 }
    665 
    666 void AwesomePlayer::onStreamDone() {
    667     // Posted whenever any stream finishes playing.
    668 
    669     Mutex::Autolock autoLock(mLock);
    670     if (!mStreamDoneEventPending) {
    671         return;
    672     }
    673     mStreamDoneEventPending = false;
    674 
    675     if (mStreamDoneStatus == INFO_DISCONTINUITY) {
    676         // This special status is returned because an http live stream's
    677         // video stream switched to a different bandwidth at this point
    678         // and future data may have been encoded using different parameters.
    679         // This requires us to shutdown the video decoder and reinstantiate
    680         // a fresh one.
    681 
    682         LOGV("INFO_DISCONTINUITY");
    683 
    684         CHECK(mVideoSource != NULL);
    685 
    686         partial_reset_l();
    687         postVideoEvent_l();
    688         return;
    689     } else if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
    690         LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
    691 
    692         notifyListener_l(
    693                 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
    694 
    695         pause_l(true /* at eos */);
    696 
    697         mFlags |= AT_EOS;
    698         return;
    699     }
    700 
    701     const bool allDone =
    702         (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
    703             && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
    704 
    705     if (!allDone) {
    706         return;
    707     }
    708 
    709     if (mFlags & (LOOPING | AUTO_LOOPING)) {
    710         seekTo_l(0);
    711 
    712         if (mVideoSource != NULL) {
    713             postVideoEvent_l();
    714         }
    715     } else {
    716         LOGV("MEDIA_PLAYBACK_COMPLETE");
    717         notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
    718 
    719         pause_l(true /* at eos */);
    720 
    721         mFlags |= AT_EOS;
    722     }
    723 }
    724 
    725 status_t AwesomePlayer::play() {
    726     Mutex::Autolock autoLock(mLock);
    727 
    728     mFlags &= ~CACHE_UNDERRUN;
    729 
    730     return play_l();
    731 }
    732 
    733 status_t AwesomePlayer::play_l() {
    734     if (mFlags & PLAYING) {
    735         return OK;
    736     }
    737 
    738     if (!(mFlags & PREPARED)) {
    739         status_t err = prepare_l();
    740 
    741         if (err != OK) {
    742             return err;
    743         }
    744     }
    745 
    746     mFlags |= PLAYING;
    747     mFlags |= FIRST_FRAME;
    748 
    749     bool deferredAudioSeek = false;
    750 
    751     if (mAudioSource != NULL) {
    752         if (mAudioPlayer == NULL) {
    753             if (mAudioSink != NULL) {
    754                 mAudioPlayer = new AudioPlayer(mAudioSink, this);
    755                 mAudioPlayer->setSource(mAudioSource);
    756 
    757                 // We've already started the MediaSource in order to enable
    758                 // the prefetcher to read its data.
    759                 status_t err = mAudioPlayer->start(
    760                         true /* sourceAlreadyStarted */);
    761 
    762                 if (err != OK) {
    763                     delete mAudioPlayer;
    764                     mAudioPlayer = NULL;
    765 
    766                     mFlags &= ~(PLAYING | FIRST_FRAME);
    767 
    768                     return err;
    769                 }
    770 
    771                 mTimeSource = mAudioPlayer;
    772 
    773                 deferredAudioSeek = true;
    774 
    775                 mWatchForAudioSeekComplete = false;
    776                 mWatchForAudioEOS = true;
    777             }
    778         } else {
    779             mAudioPlayer->resume();
    780         }
    781     }
    782 
    783     if (mTimeSource == NULL && mAudioPlayer == NULL) {
    784         mTimeSource = &mSystemTimeSource;
    785     }
    786 
    787     if (mVideoSource != NULL) {
    788         // Kick off video playback
    789         postVideoEvent_l();
    790     }
    791 
    792     if (deferredAudioSeek) {
    793         // If there was a seek request while we were paused
    794         // and we're just starting up again, honor the request now.
    795         seekAudioIfNecessary_l();
    796     }
    797 
    798     if (mFlags & AT_EOS) {
    799         // Legacy behaviour, if a stream finishes playing and then
    800         // is started again, we play from the start...
    801         seekTo_l(0);
    802     }
    803 
    804     return OK;
    805 }
    806 
    807 void AwesomePlayer::initRenderer_l() {
    808     if (mISurface != NULL) {
    809         sp<MetaData> meta = mVideoSource->getFormat();
    810 
    811         int32_t format;
    812         const char *component;
    813         int32_t decodedWidth, decodedHeight;
    814         CHECK(meta->findInt32(kKeyColorFormat, &format));
    815         CHECK(meta->findCString(kKeyDecoderComponent, &component));
    816         CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
    817         CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
    818 
    819         int32_t rotationDegrees;
    820         if (!mVideoTrack->getFormat()->findInt32(
    821                     kKeyRotation, &rotationDegrees)) {
    822             rotationDegrees = 0;
    823         }
    824 
    825         mVideoRenderer.clear();
    826 
    827         // Must ensure that mVideoRenderer's destructor is actually executed
    828         // before creating a new one.
    829         IPCThreadState::self()->flushCommands();
    830 
    831         if (!strncmp("OMX.", component, 4)) {
    832             // Our OMX codecs allocate buffers on the media_server side
    833             // therefore they require a remote IOMXRenderer that knows how
    834             // to display them.
    835             mVideoRenderer = new AwesomeRemoteRenderer(
    836                 mClient.interface()->createRenderer(
    837                         mISurface, component,
    838                         (OMX_COLOR_FORMATTYPE)format,
    839                         decodedWidth, decodedHeight,
    840                         mVideoWidth, mVideoHeight,
    841                         rotationDegrees));
    842         } else {
    843             // Other decoders are instantiated locally and as a consequence
    844             // allocate their buffers in local address space.
    845             mVideoRenderer = new AwesomeLocalRenderer(
    846                 false,  // previewOnly
    847                 component,
    848                 (OMX_COLOR_FORMATTYPE)format,
    849                 mISurface,
    850                 mVideoWidth, mVideoHeight,
    851                 decodedWidth, decodedHeight, rotationDegrees);
    852         }
    853     }
    854 }
    855 
    856 status_t AwesomePlayer::pause() {
    857     Mutex::Autolock autoLock(mLock);
    858 
    859     mFlags &= ~CACHE_UNDERRUN;
    860 
    861     return pause_l();
    862 }
    863 
    864 status_t AwesomePlayer::pause_l(bool at_eos) {
    865     if (!(mFlags & PLAYING)) {
    866         return OK;
    867     }
    868 
    869     cancelPlayerEvents(true /* keepBufferingGoing */);
    870 
    871     if (mAudioPlayer != NULL) {
    872         if (at_eos) {
    873             // If we played the audio stream to completion we
    874             // want to make sure that all samples remaining in the audio
    875             // track's queue are played out.
    876             mAudioPlayer->pause(true /* playPendingSamples */);
    877         } else {
    878             mAudioPlayer->pause();
    879         }
    880     }
    881 
    882     mFlags &= ~PLAYING;
    883 
    884     return OK;
    885 }
    886 
    887 bool AwesomePlayer::isPlaying() const {
    888     return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
    889 }
    890 
    891 void AwesomePlayer::setISurface(const sp<ISurface> &isurface) {
    892     Mutex::Autolock autoLock(mLock);
    893 
    894     mISurface = isurface;
    895 }
    896 
    897 void AwesomePlayer::setAudioSink(
    898         const sp<MediaPlayerBase::AudioSink> &audioSink) {
    899     Mutex::Autolock autoLock(mLock);
    900 
    901     mAudioSink = audioSink;
    902 }
    903 
    904 status_t AwesomePlayer::setLooping(bool shouldLoop) {
    905     Mutex::Autolock autoLock(mLock);
    906 
    907     mFlags = mFlags & ~LOOPING;
    908 
    909     if (shouldLoop) {
    910         mFlags |= LOOPING;
    911     }
    912 
    913     return OK;
    914 }
    915 
    916 status_t AwesomePlayer::getDuration(int64_t *durationUs) {
    917     Mutex::Autolock autoLock(mMiscStateLock);
    918 
    919     if (mDurationUs < 0) {
    920         return UNKNOWN_ERROR;
    921     }
    922 
    923     *durationUs = mDurationUs;
    924 
    925     return OK;
    926 }
    927 
    928 status_t AwesomePlayer::getPosition(int64_t *positionUs) {
    929     if (mRTSPController != NULL) {
    930         *positionUs = mRTSPController->getNormalPlayTimeUs();
    931     }
    932     else if (mSeeking) {
    933         *positionUs = mSeekTimeUs;
    934     } else if (mVideoSource != NULL) {
    935         Mutex::Autolock autoLock(mMiscStateLock);
    936         *positionUs = mVideoTimeUs;
    937     } else if (mAudioPlayer != NULL) {
    938         *positionUs = mAudioPlayer->getMediaTimeUs();
    939     } else {
    940         *positionUs = 0;
    941     }
    942 
    943     return OK;
    944 }
    945 
    946 status_t AwesomePlayer::seekTo(int64_t timeUs) {
    947     if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
    948         Mutex::Autolock autoLock(mLock);
    949         return seekTo_l(timeUs);
    950     }
    951 
    952     return OK;
    953 }
    954 
    955 // static
    956 void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) {
    957     static_cast<AwesomePlayer *>(cookie)->onRTSPSeekDone();
    958 }
    959 
    960 void AwesomePlayer::onRTSPSeekDone() {
    961     notifyListener_l(MEDIA_SEEK_COMPLETE);
    962     mSeekNotificationSent = true;
    963 }
    964 
    965 status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
    966     if (mRTSPController != NULL) {
    967         mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this);
    968         return OK;
    969     }
    970 
    971     if (mFlags & CACHE_UNDERRUN) {
    972         mFlags &= ~CACHE_UNDERRUN;
    973         play_l();
    974     }
    975 
    976     mSeeking = true;
    977     mSeekNotificationSent = false;
    978     mSeekTimeUs = timeUs;
    979     mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
    980 
    981     seekAudioIfNecessary_l();
    982 
    983     if (!(mFlags & PLAYING)) {
    984         LOGV("seeking while paused, sending SEEK_COMPLETE notification"
    985              " immediately.");
    986 
    987         notifyListener_l(MEDIA_SEEK_COMPLETE);
    988         mSeekNotificationSent = true;
    989     }
    990 
    991     return OK;
    992 }
    993 
    994 void AwesomePlayer::seekAudioIfNecessary_l() {
    995     if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
    996         mAudioPlayer->seekTo(mSeekTimeUs);
    997 
    998         mWatchForAudioSeekComplete = true;
    999         mWatchForAudioEOS = true;
   1000         mSeekNotificationSent = false;
   1001     }
   1002 }
   1003 
   1004 status_t AwesomePlayer::getVideoDimensions(
   1005         int32_t *width, int32_t *height) const {
   1006     Mutex::Autolock autoLock(mLock);
   1007 
   1008     if (mVideoWidth < 0 || mVideoHeight < 0) {
   1009         return UNKNOWN_ERROR;
   1010     }
   1011 
   1012     *width = mVideoWidth;
   1013     *height = mVideoHeight;
   1014 
   1015     return OK;
   1016 }
   1017 
   1018 void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
   1019     CHECK(source != NULL);
   1020 
   1021     mAudioTrack = source;
   1022 }
   1023 
   1024 status_t AwesomePlayer::initAudioDecoder() {
   1025     sp<MetaData> meta = mAudioTrack->getFormat();
   1026 
   1027     const char *mime;
   1028     CHECK(meta->findCString(kKeyMIMEType, &mime));
   1029 
   1030     if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
   1031         mAudioSource = mAudioTrack;
   1032     } else {
   1033         mAudioSource = OMXCodec::Create(
   1034                 mClient.interface(), mAudioTrack->getFormat(),
   1035                 false, // createEncoder
   1036                 mAudioTrack);
   1037     }
   1038 
   1039     if (mAudioSource != NULL) {
   1040         int64_t durationUs;
   1041         if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
   1042             Mutex::Autolock autoLock(mMiscStateLock);
   1043             if (mDurationUs < 0 || durationUs > mDurationUs) {
   1044                 mDurationUs = durationUs;
   1045             }
   1046         }
   1047 
   1048         status_t err = mAudioSource->start();
   1049 
   1050         if (err != OK) {
   1051             mAudioSource.clear();
   1052             return err;
   1053         }
   1054     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
   1055         // For legacy reasons we're simply going to ignore the absence
   1056         // of an audio decoder for QCELP instead of aborting playback
   1057         // altogether.
   1058         return OK;
   1059     }
   1060 
   1061     return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
   1062 }
   1063 
   1064 void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
   1065     CHECK(source != NULL);
   1066 
   1067     mVideoTrack = source;
   1068 }
   1069 
   1070 status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
   1071     mVideoSource = OMXCodec::Create(
   1072             mClient.interface(), mVideoTrack->getFormat(),
   1073             false, // createEncoder
   1074             mVideoTrack,
   1075             NULL, flags);
   1076 
   1077     if (mVideoSource != NULL) {
   1078         int64_t durationUs;
   1079         if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
   1080             Mutex::Autolock autoLock(mMiscStateLock);
   1081             if (mDurationUs < 0 || durationUs > mDurationUs) {
   1082                 mDurationUs = durationUs;
   1083             }
   1084         }
   1085 
   1086         CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
   1087         CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
   1088 
   1089         status_t err = mVideoSource->start();
   1090 
   1091         if (err != OK) {
   1092             mVideoSource.clear();
   1093             return err;
   1094         }
   1095     }
   1096 
   1097     return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
   1098 }
   1099 
   1100 void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
   1101     if (!mSeeking) {
   1102         return;
   1103     }
   1104 
   1105     if (mAudioPlayer != NULL) {
   1106         LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
   1107 
   1108         // If we don't have a video time, seek audio to the originally
   1109         // requested seek time instead.
   1110 
   1111         mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
   1112         mAudioPlayer->resume();
   1113         mWatchForAudioSeekComplete = true;
   1114         mWatchForAudioEOS = true;
   1115     } else if (!mSeekNotificationSent) {
   1116         // If we're playing video only, report seek complete now,
   1117         // otherwise audio player will notify us later.
   1118         notifyListener_l(MEDIA_SEEK_COMPLETE);
   1119     }
   1120 
   1121     mFlags |= FIRST_FRAME;
   1122     mSeeking = false;
   1123     mSeekNotificationSent = false;
   1124 }
   1125 
   1126 void AwesomePlayer::onVideoEvent() {
   1127     Mutex::Autolock autoLock(mLock);
   1128     if (!mVideoEventPending) {
   1129         // The event has been cancelled in reset_l() but had already
   1130         // been scheduled for execution at that time.
   1131         return;
   1132     }
   1133     mVideoEventPending = false;
   1134 
   1135     if (mSeeking) {
   1136         if (mLastVideoBuffer) {
   1137             mLastVideoBuffer->release();
   1138             mLastVideoBuffer = NULL;
   1139         }
   1140 
   1141         if (mVideoBuffer) {
   1142             mVideoBuffer->release();
   1143             mVideoBuffer = NULL;
   1144         }
   1145 
   1146         if (mCachedSource != NULL && mAudioSource != NULL) {
   1147             // We're going to seek the video source first, followed by
   1148             // the audio source.
   1149             // In order to avoid jumps in the DataSource offset caused by
   1150             // the audio codec prefetching data from the old locations
   1151             // while the video codec is already reading data from the new
   1152             // locations, we'll "pause" the audio source, causing it to
   1153             // stop reading input data until a subsequent seek.
   1154 
   1155             if (mAudioPlayer != NULL) {
   1156                 mAudioPlayer->pause();
   1157             }
   1158             mAudioSource->pause();
   1159         }
   1160     }
   1161 
   1162     if (!mVideoBuffer) {
   1163         MediaSource::ReadOptions options;
   1164         if (mSeeking) {
   1165             LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
   1166 
   1167             options.setSeekTo(
   1168                     mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
   1169         }
   1170         for (;;) {
   1171             status_t err = mVideoSource->read(&mVideoBuffer, &options);
   1172             options.clearSeekTo();
   1173 
   1174             if (err != OK) {
   1175                 CHECK_EQ(mVideoBuffer, NULL);
   1176 
   1177                 if (err == INFO_FORMAT_CHANGED) {
   1178                     LOGV("VideoSource signalled format change.");
   1179 
   1180                     if (mVideoRenderer != NULL) {
   1181                         mVideoRendererIsPreview = false;
   1182                         initRenderer_l();
   1183                     }
   1184                     continue;
   1185                 }
   1186 
   1187                 // So video playback is complete, but we may still have
   1188                 // a seek request pending that needs to be applied
   1189                 // to the audio track.
   1190                 if (mSeeking) {
   1191                     LOGV("video stream ended while seeking!");
   1192                 }
   1193                 finishSeekIfNecessary(-1);
   1194 
   1195                 mFlags |= VIDEO_AT_EOS;
   1196                 postStreamDoneEvent_l(err);
   1197                 return;
   1198             }
   1199 
   1200             if (mVideoBuffer->range_length() == 0) {
   1201                 // Some decoders, notably the PV AVC software decoder
   1202                 // return spurious empty buffers that we just want to ignore.
   1203 
   1204                 mVideoBuffer->release();
   1205                 mVideoBuffer = NULL;
   1206                 continue;
   1207             }
   1208 
   1209             break;
   1210         }
   1211     }
   1212 
   1213     int64_t timeUs;
   1214     CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
   1215 
   1216     {
   1217         Mutex::Autolock autoLock(mMiscStateLock);
   1218         mVideoTimeUs = timeUs;
   1219     }
   1220 
   1221     finishSeekIfNecessary(timeUs);
   1222 
   1223     TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
   1224 
   1225     if (mFlags & FIRST_FRAME) {
   1226         mFlags &= ~FIRST_FRAME;
   1227 
   1228         mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
   1229     }
   1230 
   1231     int64_t realTimeUs, mediaTimeUs;
   1232     if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
   1233         && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
   1234         mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
   1235     }
   1236 
   1237     int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
   1238 
   1239     int64_t latenessUs = nowUs - timeUs;
   1240 
   1241     if (mRTPSession != NULL) {
   1242         // We'll completely ignore timestamps for gtalk videochat
   1243         // and we'll play incoming video as fast as we get it.
   1244         latenessUs = 0;
   1245     }
   1246 
   1247     if (latenessUs > 40000) {
   1248         // We're more than 40ms late.
   1249         LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
   1250 
   1251         mVideoBuffer->release();
   1252         mVideoBuffer = NULL;
   1253 
   1254         postVideoEvent_l();
   1255         return;
   1256     }
   1257 
   1258     if (latenessUs < -10000) {
   1259         // We're more than 10ms early.
   1260 
   1261         postVideoEvent_l(10000);
   1262         return;
   1263     }
   1264 
   1265     if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
   1266         mVideoRendererIsPreview = false;
   1267 
   1268         initRenderer_l();
   1269     }
   1270 
   1271     if (mVideoRenderer != NULL) {
   1272         mVideoRenderer->render(mVideoBuffer);
   1273     }
   1274 
   1275     if (mLastVideoBuffer) {
   1276         mLastVideoBuffer->release();
   1277         mLastVideoBuffer = NULL;
   1278     }
   1279     mLastVideoBuffer = mVideoBuffer;
   1280     mVideoBuffer = NULL;
   1281 
   1282     postVideoEvent_l();
   1283 }
   1284 
   1285 void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
   1286     if (mVideoEventPending) {
   1287         return;
   1288     }
   1289 
   1290     mVideoEventPending = true;
   1291     mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
   1292 }
   1293 
   1294 void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
   1295     if (mStreamDoneEventPending) {
   1296         return;
   1297     }
   1298     mStreamDoneEventPending = true;
   1299 
   1300     mStreamDoneStatus = status;
   1301     mQueue.postEvent(mStreamDoneEvent);
   1302 }
   1303 
   1304 void AwesomePlayer::postBufferingEvent_l() {
   1305     if (mBufferingEventPending) {
   1306         return;
   1307     }
   1308     mBufferingEventPending = true;
   1309     mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
   1310 }
   1311 
   1312 void AwesomePlayer::postCheckAudioStatusEvent_l() {
   1313     if (mAudioStatusEventPending) {
   1314         return;
   1315     }
   1316     mAudioStatusEventPending = true;
   1317     mQueue.postEvent(mCheckAudioStatusEvent);
   1318 }
   1319 
   1320 void AwesomePlayer::onCheckAudioStatus() {
   1321     Mutex::Autolock autoLock(mLock);
   1322     if (!mAudioStatusEventPending) {
   1323         // Event was dispatched and while we were blocking on the mutex,
   1324         // has already been cancelled.
   1325         return;
   1326     }
   1327 
   1328     mAudioStatusEventPending = false;
   1329 
   1330     if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
   1331         mWatchForAudioSeekComplete = false;
   1332 
   1333         if (!mSeekNotificationSent) {
   1334             notifyListener_l(MEDIA_SEEK_COMPLETE);
   1335             mSeekNotificationSent = true;
   1336         }
   1337 
   1338         mSeeking = false;
   1339     }
   1340 
   1341     status_t finalStatus;
   1342     if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
   1343         mWatchForAudioEOS = false;
   1344         mFlags |= AUDIO_AT_EOS;
   1345         mFlags |= FIRST_FRAME;
   1346         postStreamDoneEvent_l(finalStatus);
   1347     }
   1348 }
   1349 
   1350 status_t AwesomePlayer::prepare() {
   1351     Mutex::Autolock autoLock(mLock);
   1352     return prepare_l();
   1353 }
   1354 
   1355 status_t AwesomePlayer::prepare_l() {
   1356     if (mFlags & PREPARED) {
   1357         return OK;
   1358     }
   1359 
   1360     if (mFlags & PREPARING) {
   1361         return UNKNOWN_ERROR;
   1362     }
   1363 
   1364     mIsAsyncPrepare = false;
   1365     status_t err = prepareAsync_l();
   1366 
   1367     if (err != OK) {
   1368         return err;
   1369     }
   1370 
   1371     while (mFlags & PREPARING) {
   1372         mPreparedCondition.wait(mLock);
   1373     }
   1374 
   1375     return mPrepareResult;
   1376 }
   1377 
   1378 status_t AwesomePlayer::prepareAsync() {
   1379     Mutex::Autolock autoLock(mLock);
   1380 
   1381     if (mFlags & PREPARING) {
   1382         return UNKNOWN_ERROR;  // async prepare already pending
   1383     }
   1384 
   1385     mIsAsyncPrepare = true;
   1386     return prepareAsync_l();
   1387 }
   1388 
   1389 status_t AwesomePlayer::prepareAsync_l() {
   1390     if (mFlags & PREPARING) {
   1391         return UNKNOWN_ERROR;  // async prepare already pending
   1392     }
   1393 
   1394     if (!mQueueStarted) {
   1395         mQueue.start();
   1396         mQueueStarted = true;
   1397     }
   1398 
   1399     mFlags |= PREPARING;
   1400     mAsyncPrepareEvent = new AwesomeEvent(
   1401             this, &AwesomePlayer::onPrepareAsyncEvent);
   1402 
   1403     mQueue.postEvent(mAsyncPrepareEvent);
   1404 
   1405     return OK;
   1406 }
   1407 
   1408 status_t AwesomePlayer::finishSetDataSource_l() {
   1409     sp<DataSource> dataSource;
   1410 
   1411     if (!strncasecmp("http://", mUri.string(), 7)) {
   1412         mConnectingDataSource = new NuHTTPDataSource;
   1413 
   1414         mLock.unlock();
   1415         status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
   1416         mLock.lock();
   1417 
   1418         if (err != OK) {
   1419             mConnectingDataSource.clear();
   1420 
   1421             LOGI("mConnectingDataSource->connect() returned %d", err);
   1422             return err;
   1423         }
   1424 
   1425 #if 0
   1426         mCachedSource = new NuCachedSource2(
   1427                 new ThrottledSource(
   1428                     mConnectingDataSource, 50 * 1024 /* bytes/sec */));
   1429 #else
   1430         mCachedSource = new NuCachedSource2(mConnectingDataSource);
   1431 #endif
   1432         mConnectingDataSource.clear();
   1433 
   1434         dataSource = mCachedSource;
   1435     } else if (!strncasecmp(mUri.string(), "httplive://", 11)) {
   1436         String8 uri("http://");
   1437         uri.append(mUri.string() + 11);
   1438 
   1439         sp<LiveSource> liveSource = new LiveSource(uri.string());
   1440 
   1441         mCachedSource = new NuCachedSource2(liveSource);
   1442         dataSource = mCachedSource;
   1443 
   1444         sp<MediaExtractor> extractor =
   1445             MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
   1446 
   1447         static_cast<MPEG2TSExtractor *>(extractor.get())
   1448             ->setLiveSource(liveSource);
   1449 
   1450         return setDataSource_l(extractor);
   1451     } else if (!strncmp("rtsp://gtalk/", mUri.string(), 13)) {
   1452         if (mLooper == NULL) {
   1453             mLooper = new ALooper;
   1454             mLooper->setName("gtalk rtp");
   1455             mLooper->start(
   1456                     false /* runOnCallingThread */,
   1457                     false /* canCallJava */,
   1458                     PRIORITY_HIGHEST);
   1459         }
   1460 
   1461         const char *startOfCodecString = &mUri.string()[13];
   1462         const char *startOfSlash1 = strchr(startOfCodecString, '/');
   1463         if (startOfSlash1 == NULL) {
   1464             return BAD_VALUE;
   1465         }
   1466         const char *startOfWidthString = &startOfSlash1[1];
   1467         const char *startOfSlash2 = strchr(startOfWidthString, '/');
   1468         if (startOfSlash2 == NULL) {
   1469             return BAD_VALUE;
   1470         }
   1471         const char *startOfHeightString = &startOfSlash2[1];
   1472 
   1473         String8 codecString(startOfCodecString, startOfSlash1 - startOfCodecString);
   1474         String8 widthString(startOfWidthString, startOfSlash2 - startOfWidthString);
   1475         String8 heightString(startOfHeightString);
   1476 
   1477 #if 0
   1478         mRTPPusher = new UDPPusher("/data/misc/rtpout.bin", 5434);
   1479         mLooper->registerHandler(mRTPPusher);
   1480 
   1481         mRTCPPusher = new UDPPusher("/data/misc/rtcpout.bin", 5435);
   1482         mLooper->registerHandler(mRTCPPusher);
   1483 #endif
   1484 
   1485         mRTPSession = new ARTPSession;
   1486         mLooper->registerHandler(mRTPSession);
   1487 
   1488 #if 0
   1489         // My AMR SDP
   1490         static const char *raw =
   1491             "v=0\r\n"
   1492             "o=- 64 233572944 IN IP4 127.0.0.0\r\n"
   1493             "s=QuickTime\r\n"
   1494             "t=0 0\r\n"
   1495             "a=range:npt=0-315\r\n"
   1496             "a=isma-compliance:2,2.0,2\r\n"
   1497             "m=audio 5434 RTP/AVP 97\r\n"
   1498             "c=IN IP4 127.0.0.1\r\n"
   1499             "b=AS:30\r\n"
   1500             "a=rtpmap:97 AMR/8000/1\r\n"
   1501             "a=fmtp:97 octet-align\r\n";
   1502 #elif 1
   1503         String8 sdp;
   1504         sdp.appendFormat(
   1505             "v=0\r\n"
   1506             "o=- 64 233572944 IN IP4 127.0.0.0\r\n"
   1507             "s=QuickTime\r\n"
   1508             "t=0 0\r\n"
   1509             "a=range:npt=0-315\r\n"
   1510             "a=isma-compliance:2,2.0,2\r\n"
   1511             "m=video 5434 RTP/AVP 97\r\n"
   1512             "c=IN IP4 127.0.0.1\r\n"
   1513             "b=AS:30\r\n"
   1514             "a=rtpmap:97 %s/90000\r\n"
   1515             "a=cliprect:0,0,%s,%s\r\n"
   1516             "a=framesize:97 %s-%s\r\n",
   1517 
   1518             codecString.string(),
   1519             heightString.string(), widthString.string(),
   1520             widthString.string(), heightString.string()
   1521             );
   1522         const char *raw = sdp.string();
   1523 
   1524 #endif
   1525 
   1526         sp<ASessionDescription> desc = new ASessionDescription;
   1527         CHECK(desc->setTo(raw, strlen(raw)));
   1528 
   1529         CHECK_EQ(mRTPSession->setup(desc), (status_t)OK);
   1530 
   1531         if (mRTPPusher != NULL) {
   1532             mRTPPusher->start();
   1533         }
   1534 
   1535         if (mRTCPPusher != NULL) {
   1536             mRTCPPusher->start();
   1537         }
   1538 
   1539         CHECK_EQ(mRTPSession->countTracks(), 1u);
   1540         sp<MediaSource> source = mRTPSession->trackAt(0);
   1541 
   1542 #if 0
   1543         bool eos;
   1544         while (((APacketSource *)source.get())
   1545                 ->getQueuedDuration(&eos) < 5000000ll && !eos) {
   1546             usleep(100000ll);
   1547         }
   1548 #endif
   1549 
   1550         const char *mime;
   1551         CHECK(source->getFormat()->findCString(kKeyMIMEType, &mime));
   1552 
   1553         if (!strncasecmp("video/", mime, 6)) {
   1554             setVideoSource(source);
   1555         } else {
   1556             CHECK(!strncasecmp("audio/", mime, 6));
   1557             setAudioSource(source);
   1558         }
   1559 
   1560         mExtractorFlags = MediaExtractor::CAN_PAUSE;
   1561 
   1562         return OK;
   1563     } else if (!strncasecmp("rtsp://", mUri.string(), 7)) {
   1564         if (mLooper == NULL) {
   1565             mLooper = new ALooper;
   1566             mLooper->setName("rtsp");
   1567             mLooper->start();
   1568         }
   1569         mRTSPController = new ARTSPController(mLooper);
   1570         status_t err = mRTSPController->connect(mUri.string());
   1571 
   1572         LOGI("ARTSPController::connect returned %d", err);
   1573 
   1574         if (err != OK) {
   1575             mRTSPController.clear();
   1576             return err;
   1577         }
   1578 
   1579         sp<MediaExtractor> extractor = mRTSPController.get();
   1580         return setDataSource_l(extractor);
   1581     } else {
   1582         dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
   1583     }
   1584 
   1585     if (dataSource == NULL) {
   1586         return UNKNOWN_ERROR;
   1587     }
   1588 
   1589     sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
   1590 
   1591     if (extractor == NULL) {
   1592         return UNKNOWN_ERROR;
   1593     }
   1594 
   1595     return setDataSource_l(extractor);
   1596 }
   1597 
   1598 void AwesomePlayer::abortPrepare(status_t err) {
   1599     CHECK(err != OK);
   1600 
   1601     if (mIsAsyncPrepare) {
   1602         notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
   1603     }
   1604 
   1605     mPrepareResult = err;
   1606     mFlags &= ~(PREPARING|PREPARE_CANCELLED);
   1607     mAsyncPrepareEvent = NULL;
   1608     mPreparedCondition.broadcast();
   1609 }
   1610 
   1611 // static
   1612 bool AwesomePlayer::ContinuePreparation(void *cookie) {
   1613     AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
   1614 
   1615     return (me->mFlags & PREPARE_CANCELLED) == 0;
   1616 }
   1617 
   1618 void AwesomePlayer::onPrepareAsyncEvent() {
   1619     Mutex::Autolock autoLock(mLock);
   1620 
   1621     if (mFlags & PREPARE_CANCELLED) {
   1622         LOGI("prepare was cancelled before doing anything");
   1623         abortPrepare(UNKNOWN_ERROR);
   1624         return;
   1625     }
   1626 
   1627     if (mUri.size() > 0) {
   1628         status_t err = finishSetDataSource_l();
   1629 
   1630         if (err != OK) {
   1631             abortPrepare(err);
   1632             return;
   1633         }
   1634     }
   1635 
   1636     if (mVideoTrack != NULL && mVideoSource == NULL) {
   1637         status_t err = initVideoDecoder();
   1638 
   1639         if (err != OK) {
   1640             abortPrepare(err);
   1641             return;
   1642         }
   1643     }
   1644 
   1645     if (mAudioTrack != NULL && mAudioSource == NULL) {
   1646         status_t err = initAudioDecoder();
   1647 
   1648         if (err != OK) {
   1649             abortPrepare(err);
   1650             return;
   1651         }
   1652     }
   1653 
   1654     if (mCachedSource != NULL || mRTSPController != NULL) {
   1655         postBufferingEvent_l();
   1656     } else {
   1657         finishAsyncPrepare_l();
   1658     }
   1659 }
   1660 
   1661 void AwesomePlayer::finishAsyncPrepare_l() {
   1662     if (mIsAsyncPrepare) {
   1663         if (mVideoWidth < 0 || mVideoHeight < 0) {
   1664             notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
   1665         } else {
   1666             int32_t rotationDegrees;
   1667             if (!mVideoTrack->getFormat()->findInt32(
   1668                         kKeyRotation, &rotationDegrees)) {
   1669                 rotationDegrees = 0;
   1670             }
   1671 
   1672 #if 1
   1673             if (rotationDegrees == 90 || rotationDegrees == 270) {
   1674                 notifyListener_l(
   1675                         MEDIA_SET_VIDEO_SIZE, mVideoHeight, mVideoWidth);
   1676             } else
   1677 #endif
   1678             {
   1679                 notifyListener_l(
   1680                         MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
   1681             }
   1682         }
   1683 
   1684         notifyListener_l(MEDIA_PREPARED);
   1685     }
   1686 
   1687     mPrepareResult = OK;
   1688     mFlags &= ~(PREPARING|PREPARE_CANCELLED);
   1689     mFlags |= PREPARED;
   1690     mAsyncPrepareEvent = NULL;
   1691     mPreparedCondition.broadcast();
   1692 }
   1693 
   1694 status_t AwesomePlayer::suspend() {
   1695     LOGV("suspend");
   1696     Mutex::Autolock autoLock(mLock);
   1697 
   1698     if (mSuspensionState != NULL) {
   1699         if (mLastVideoBuffer == NULL) {
   1700             //go into here if video is suspended again
   1701             //after resuming without being played between
   1702             //them
   1703             SuspensionState *state = mSuspensionState;
   1704             mSuspensionState = NULL;
   1705             reset_l();
   1706             mSuspensionState = state;
   1707             return OK;
   1708         }
   1709 
   1710         delete mSuspensionState;
   1711         mSuspensionState = NULL;
   1712     }
   1713 
   1714     if (mFlags & PREPARING) {
   1715         mFlags |= PREPARE_CANCELLED;
   1716         if (mConnectingDataSource != NULL) {
   1717             LOGI("interrupting the connection process");
   1718             mConnectingDataSource->disconnect();
   1719         }
   1720     }
   1721 
   1722     while (mFlags & PREPARING) {
   1723         mPreparedCondition.wait(mLock);
   1724     }
   1725 
   1726     SuspensionState *state = new SuspensionState;
   1727     state->mUri = mUri;
   1728     state->mUriHeaders = mUriHeaders;
   1729     state->mFileSource = mFileSource;
   1730 
   1731     state->mFlags = mFlags & (PLAYING | AUTO_LOOPING | LOOPING | AT_EOS);
   1732     getPosition(&state->mPositionUs);
   1733 
   1734     if (mLastVideoBuffer) {
   1735         size_t size = mLastVideoBuffer->range_length();
   1736 
   1737         if (size) {
   1738             int32_t unreadable;
   1739             if (!mLastVideoBuffer->meta_data()->findInt32(
   1740                         kKeyIsUnreadable, &unreadable)
   1741                     || unreadable == 0) {
   1742                 state->mLastVideoFrameSize = size;
   1743                 state->mLastVideoFrame = malloc(size);
   1744                 memcpy(state->mLastVideoFrame,
   1745                        (const uint8_t *)mLastVideoBuffer->data()
   1746                             + mLastVideoBuffer->range_offset(),
   1747                        size);
   1748 
   1749                 state->mVideoWidth = mVideoWidth;
   1750                 state->mVideoHeight = mVideoHeight;
   1751 
   1752                 sp<MetaData> meta = mVideoSource->getFormat();
   1753                 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat));
   1754                 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth));
   1755                 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight));
   1756             } else {
   1757                 LOGV("Unable to save last video frame, we have no access to "
   1758                      "the decoded video data.");
   1759             }
   1760         }
   1761     }
   1762 
   1763     reset_l();
   1764 
   1765     mSuspensionState = state;
   1766 
   1767     return OK;
   1768 }
   1769 
   1770 status_t AwesomePlayer::resume() {
   1771     LOGV("resume");
   1772     Mutex::Autolock autoLock(mLock);
   1773 
   1774     if (mSuspensionState == NULL) {
   1775         return INVALID_OPERATION;
   1776     }
   1777 
   1778     SuspensionState *state = mSuspensionState;
   1779     mSuspensionState = NULL;
   1780 
   1781     status_t err;
   1782     if (state->mFileSource != NULL) {
   1783         err = setDataSource_l(state->mFileSource);
   1784 
   1785         if (err == OK) {
   1786             mFileSource = state->mFileSource;
   1787         }
   1788     } else {
   1789         err = setDataSource_l(state->mUri, &state->mUriHeaders);
   1790     }
   1791 
   1792     if (err != OK) {
   1793         delete state;
   1794         state = NULL;
   1795 
   1796         return err;
   1797     }
   1798 
   1799     seekTo_l(state->mPositionUs);
   1800 
   1801     mFlags = state->mFlags & (AUTO_LOOPING | LOOPING | AT_EOS);
   1802 
   1803     if (state->mLastVideoFrame && mISurface != NULL) {
   1804         mVideoRenderer =
   1805             new AwesomeLocalRenderer(
   1806                     true,  // previewOnly
   1807                     "",
   1808                     (OMX_COLOR_FORMATTYPE)state->mColorFormat,
   1809                     mISurface,
   1810                     state->mVideoWidth,
   1811                     state->mVideoHeight,
   1812                     state->mDecodedWidth,
   1813                     state->mDecodedHeight,
   1814                     0);
   1815 
   1816         mVideoRendererIsPreview = true;
   1817 
   1818         ((AwesomeLocalRenderer *)mVideoRenderer.get())->render(
   1819                 state->mLastVideoFrame, state->mLastVideoFrameSize);
   1820     }
   1821 
   1822     if (state->mFlags & PLAYING) {
   1823         play_l();
   1824     }
   1825 
   1826     mSuspensionState = state;
   1827     state = NULL;
   1828 
   1829     return OK;
   1830 }
   1831 
   1832 uint32_t AwesomePlayer::flags() const {
   1833     return mExtractorFlags;
   1834 }
   1835 
   1836 void AwesomePlayer::postAudioEOS() {
   1837     postCheckAudioStatusEvent_l();
   1838 }
   1839 
   1840 void AwesomePlayer::postAudioSeekComplete() {
   1841     postCheckAudioStatusEvent_l();
   1842 }
   1843 
   1844 }  // namespace android
   1845 
   1846