Home | History | Annotate | Download | only in nuplayer
      1 /*
      2  * Copyright (C) 2010 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 "NuPlayerDriver"
     19 #include <utils/Log.h>
     20 
     21 #include "NuPlayerDriver.h"
     22 
     23 #include "NuPlayer.h"
     24 #include "NuPlayerSource.h"
     25 
     26 #include <media/stagefright/foundation/ADebug.h>
     27 #include <media/stagefright/foundation/ALooper.h>
     28 #include <media/stagefright/MetaData.h>
     29 
     30 namespace android {
     31 
     32 NuPlayerDriver::NuPlayerDriver()
     33     : mState(STATE_IDLE),
     34       mIsAsyncPrepare(false),
     35       mAsyncResult(UNKNOWN_ERROR),
     36       mSetSurfaceInProgress(false),
     37       mDurationUs(-1),
     38       mPositionUs(-1),
     39       mNumFramesTotal(0),
     40       mNumFramesDropped(0),
     41       mLooper(new ALooper),
     42       mPlayerFlags(0),
     43       mAtEOS(false),
     44       mStartupSeekTimeUs(-1) {
     45     mLooper->setName("NuPlayerDriver Looper");
     46 
     47     mLooper->start(
     48             false, /* runOnCallingThread */
     49             true,  /* canCallJava */
     50             PRIORITY_AUDIO);
     51 
     52     mPlayer = new NuPlayer;
     53     mLooper->registerHandler(mPlayer);
     54 
     55     mPlayer->setDriver(this);
     56 }
     57 
     58 NuPlayerDriver::~NuPlayerDriver() {
     59     mLooper->stop();
     60 }
     61 
     62 status_t NuPlayerDriver::initCheck() {
     63     return OK;
     64 }
     65 
     66 status_t NuPlayerDriver::setUID(uid_t uid) {
     67     mPlayer->setUID(uid);
     68 
     69     return OK;
     70 }
     71 
     72 status_t NuPlayerDriver::setDataSource(
     73         const char *url, const KeyedVector<String8, String8> *headers) {
     74     Mutex::Autolock autoLock(mLock);
     75 
     76     if (mState != STATE_IDLE) {
     77         return INVALID_OPERATION;
     78     }
     79 
     80     mState = STATE_SET_DATASOURCE_PENDING;
     81 
     82     mPlayer->setDataSourceAsync(url, headers);
     83 
     84     while (mState == STATE_SET_DATASOURCE_PENDING) {
     85         mCondition.wait(mLock);
     86     }
     87 
     88     return mAsyncResult;
     89 }
     90 
     91 status_t NuPlayerDriver::setDataSource(int fd, int64_t offset, int64_t length) {
     92     Mutex::Autolock autoLock(mLock);
     93 
     94     if (mState != STATE_IDLE) {
     95         return INVALID_OPERATION;
     96     }
     97 
     98     mState = STATE_SET_DATASOURCE_PENDING;
     99 
    100     mPlayer->setDataSourceAsync(fd, offset, length);
    101 
    102     while (mState == STATE_SET_DATASOURCE_PENDING) {
    103         mCondition.wait(mLock);
    104     }
    105 
    106     return mAsyncResult;
    107 }
    108 
    109 status_t NuPlayerDriver::setDataSource(const sp<IStreamSource> &source) {
    110     Mutex::Autolock autoLock(mLock);
    111 
    112     if (mState != STATE_IDLE) {
    113         return INVALID_OPERATION;
    114     }
    115 
    116     mState = STATE_SET_DATASOURCE_PENDING;
    117 
    118     mPlayer->setDataSourceAsync(source);
    119 
    120     while (mState == STATE_SET_DATASOURCE_PENDING) {
    121         mCondition.wait(mLock);
    122     }
    123 
    124     return mAsyncResult;
    125 }
    126 
    127 status_t NuPlayerDriver::setVideoSurfaceTexture(
    128         const sp<IGraphicBufferProducer> &bufferProducer) {
    129     Mutex::Autolock autoLock(mLock);
    130 
    131     if (mSetSurfaceInProgress) {
    132         return INVALID_OPERATION;
    133     }
    134 
    135     switch (mState) {
    136         case STATE_SET_DATASOURCE_PENDING:
    137         case STATE_RESET_IN_PROGRESS:
    138             return INVALID_OPERATION;
    139 
    140         default:
    141             break;
    142     }
    143 
    144     mSetSurfaceInProgress = true;
    145 
    146     mPlayer->setVideoSurfaceTextureAsync(bufferProducer);
    147 
    148     while (mSetSurfaceInProgress) {
    149         mCondition.wait(mLock);
    150     }
    151 
    152     return OK;
    153 }
    154 
    155 status_t NuPlayerDriver::prepare() {
    156     Mutex::Autolock autoLock(mLock);
    157     return prepare_l();
    158 }
    159 
    160 status_t NuPlayerDriver::prepare_l() {
    161     switch (mState) {
    162         case STATE_UNPREPARED:
    163             mState = STATE_PREPARING;
    164 
    165             // Make sure we're not posting any notifications, success or
    166             // failure information is only communicated through our result
    167             // code.
    168             mIsAsyncPrepare = false;
    169             mPlayer->prepareAsync();
    170             while (mState == STATE_PREPARING) {
    171                 mCondition.wait(mLock);
    172             }
    173             return (mState == STATE_PREPARED) ? OK : UNKNOWN_ERROR;
    174         default:
    175             return INVALID_OPERATION;
    176     };
    177 }
    178 
    179 status_t NuPlayerDriver::prepareAsync() {
    180     Mutex::Autolock autoLock(mLock);
    181 
    182     switch (mState) {
    183         case STATE_UNPREPARED:
    184             mState = STATE_PREPARING;
    185             mIsAsyncPrepare = true;
    186             mPlayer->prepareAsync();
    187             return OK;
    188         default:
    189             return INVALID_OPERATION;
    190     };
    191 }
    192 
    193 status_t NuPlayerDriver::start() {
    194     Mutex::Autolock autoLock(mLock);
    195 
    196     switch (mState) {
    197         case STATE_UNPREPARED:
    198         {
    199             status_t err = prepare_l();
    200 
    201             if (err != OK) {
    202                 return err;
    203             }
    204 
    205             CHECK_EQ(mState, STATE_PREPARED);
    206 
    207             // fall through
    208         }
    209 
    210         case STATE_PREPARED:
    211         {
    212             mAtEOS = false;
    213             mPlayer->start();
    214 
    215             if (mStartupSeekTimeUs >= 0) {
    216                 if (mStartupSeekTimeUs == 0) {
    217                     notifySeekComplete();
    218                 } else {
    219                     mPlayer->seekToAsync(mStartupSeekTimeUs);
    220                 }
    221 
    222                 mStartupSeekTimeUs = -1;
    223             }
    224             break;
    225         }
    226 
    227         case STATE_RUNNING:
    228             break;
    229 
    230         case STATE_PAUSED:
    231         {
    232             mPlayer->resume();
    233             break;
    234         }
    235 
    236         default:
    237             return INVALID_OPERATION;
    238     }
    239 
    240     mState = STATE_RUNNING;
    241 
    242     return OK;
    243 }
    244 
    245 status_t NuPlayerDriver::stop() {
    246     return pause();
    247 }
    248 
    249 status_t NuPlayerDriver::pause() {
    250     Mutex::Autolock autoLock(mLock);
    251 
    252     switch (mState) {
    253         case STATE_PAUSED:
    254         case STATE_PREPARED:
    255             return OK;
    256 
    257         case STATE_RUNNING:
    258             notifyListener(MEDIA_PAUSED);
    259             mPlayer->pause();
    260             break;
    261 
    262         default:
    263             return INVALID_OPERATION;
    264     }
    265 
    266     mState = STATE_PAUSED;
    267 
    268     return OK;
    269 }
    270 
    271 bool NuPlayerDriver::isPlaying() {
    272     return mState == STATE_RUNNING && !mAtEOS;
    273 }
    274 
    275 status_t NuPlayerDriver::seekTo(int msec) {
    276     Mutex::Autolock autoLock(mLock);
    277 
    278     int64_t seekTimeUs = msec * 1000ll;
    279 
    280     switch (mState) {
    281         case STATE_PREPARED:
    282         {
    283             mStartupSeekTimeUs = seekTimeUs;
    284             break;
    285         }
    286 
    287         case STATE_RUNNING:
    288         case STATE_PAUSED:
    289         {
    290             mAtEOS = false;
    291             // seeks can take a while, so we essentially paused
    292             notifyListener(MEDIA_PAUSED);
    293             mPlayer->seekToAsync(seekTimeUs);
    294             break;
    295         }
    296 
    297         default:
    298             return INVALID_OPERATION;
    299     }
    300 
    301     return OK;
    302 }
    303 
    304 status_t NuPlayerDriver::getCurrentPosition(int *msec) {
    305     Mutex::Autolock autoLock(mLock);
    306 
    307     if (mPositionUs < 0) {
    308         *msec = 0;
    309     } else {
    310         *msec = (mPositionUs + 500ll) / 1000;
    311     }
    312 
    313     return OK;
    314 }
    315 
    316 status_t NuPlayerDriver::getDuration(int *msec) {
    317     Mutex::Autolock autoLock(mLock);
    318 
    319     if (mDurationUs < 0) {
    320         return UNKNOWN_ERROR;
    321     }
    322 
    323     *msec = (mDurationUs + 500ll) / 1000;
    324 
    325     return OK;
    326 }
    327 
    328 status_t NuPlayerDriver::reset() {
    329     Mutex::Autolock autoLock(mLock);
    330 
    331     switch (mState) {
    332         case STATE_IDLE:
    333             return OK;
    334 
    335         case STATE_SET_DATASOURCE_PENDING:
    336         case STATE_RESET_IN_PROGRESS:
    337             return INVALID_OPERATION;
    338 
    339         case STATE_PREPARING:
    340         {
    341             CHECK(mIsAsyncPrepare);
    342 
    343             notifyListener(MEDIA_PREPARED);
    344             break;
    345         }
    346 
    347         default:
    348             break;
    349     }
    350 
    351     notifyListener(MEDIA_STOPPED);
    352 
    353     mState = STATE_RESET_IN_PROGRESS;
    354     mPlayer->resetAsync();
    355 
    356     while (mState == STATE_RESET_IN_PROGRESS) {
    357         mCondition.wait(mLock);
    358     }
    359 
    360     mDurationUs = -1;
    361     mPositionUs = -1;
    362     mStartupSeekTimeUs = -1;
    363 
    364     return OK;
    365 }
    366 
    367 status_t NuPlayerDriver::setLooping(int loop) {
    368     return INVALID_OPERATION;
    369 }
    370 
    371 player_type NuPlayerDriver::playerType() {
    372     return NU_PLAYER;
    373 }
    374 
    375 status_t NuPlayerDriver::invoke(const Parcel &request, Parcel *reply) {
    376     if (reply == NULL) {
    377         ALOGE("reply is a NULL pointer");
    378         return BAD_VALUE;
    379     }
    380 
    381     int32_t methodId;
    382     status_t ret = request.readInt32(&methodId);
    383     if (ret != OK) {
    384         ALOGE("Failed to retrieve the requested method to invoke");
    385         return ret;
    386     }
    387 
    388     switch (methodId) {
    389         case INVOKE_ID_SET_VIDEO_SCALING_MODE:
    390         {
    391             int mode = request.readInt32();
    392             return mPlayer->setVideoScalingMode(mode);
    393         }
    394 
    395         case INVOKE_ID_GET_TRACK_INFO:
    396         {
    397             return mPlayer->getTrackInfo(reply);
    398         }
    399 
    400         case INVOKE_ID_SELECT_TRACK:
    401         {
    402             int trackIndex = request.readInt32();
    403             return mPlayer->selectTrack(trackIndex, true /* select */);
    404         }
    405 
    406         case INVOKE_ID_UNSELECT_TRACK:
    407         {
    408             int trackIndex = request.readInt32();
    409             return mPlayer->selectTrack(trackIndex, false /* select */);
    410         }
    411 
    412         default:
    413         {
    414             return INVALID_OPERATION;
    415         }
    416     }
    417 }
    418 
    419 void NuPlayerDriver::setAudioSink(const sp<AudioSink> &audioSink) {
    420     mPlayer->setAudioSink(audioSink);
    421 }
    422 
    423 status_t NuPlayerDriver::setParameter(int key, const Parcel &request) {
    424     return INVALID_OPERATION;
    425 }
    426 
    427 status_t NuPlayerDriver::getParameter(int key, Parcel *reply) {
    428     return INVALID_OPERATION;
    429 }
    430 
    431 status_t NuPlayerDriver::getMetadata(
    432         const media::Metadata::Filter& ids, Parcel *records) {
    433     Mutex::Autolock autoLock(mLock);
    434 
    435     using media::Metadata;
    436 
    437     Metadata meta(records);
    438 
    439     meta.appendBool(
    440             Metadata::kPauseAvailable,
    441             mPlayerFlags & NuPlayer::Source::FLAG_CAN_PAUSE);
    442 
    443     meta.appendBool(
    444             Metadata::kSeekBackwardAvailable,
    445             mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_BACKWARD);
    446 
    447     meta.appendBool(
    448             Metadata::kSeekForwardAvailable,
    449             mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_FORWARD);
    450 
    451     meta.appendBool(
    452             Metadata::kSeekAvailable,
    453             mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK);
    454 
    455     return OK;
    456 }
    457 
    458 void NuPlayerDriver::notifyResetComplete() {
    459     Mutex::Autolock autoLock(mLock);
    460 
    461     CHECK_EQ(mState, STATE_RESET_IN_PROGRESS);
    462     mState = STATE_IDLE;
    463     mCondition.broadcast();
    464 }
    465 
    466 void NuPlayerDriver::notifySetSurfaceComplete() {
    467     Mutex::Autolock autoLock(mLock);
    468 
    469     CHECK(mSetSurfaceInProgress);
    470     mSetSurfaceInProgress = false;
    471 
    472     mCondition.broadcast();
    473 }
    474 
    475 void NuPlayerDriver::notifyDuration(int64_t durationUs) {
    476     Mutex::Autolock autoLock(mLock);
    477     mDurationUs = durationUs;
    478 }
    479 
    480 void NuPlayerDriver::notifyPosition(int64_t positionUs) {
    481     Mutex::Autolock autoLock(mLock);
    482     mPositionUs = positionUs;
    483 }
    484 
    485 void NuPlayerDriver::notifySeekComplete() {
    486     notifyListener(MEDIA_SEEK_COMPLETE);
    487 }
    488 
    489 void NuPlayerDriver::notifyFrameStats(
    490         int64_t numFramesTotal, int64_t numFramesDropped) {
    491     Mutex::Autolock autoLock(mLock);
    492     mNumFramesTotal = numFramesTotal;
    493     mNumFramesDropped = numFramesDropped;
    494 }
    495 
    496 status_t NuPlayerDriver::dump(int fd, const Vector<String16> &args) const {
    497     Mutex::Autolock autoLock(mLock);
    498 
    499     FILE *out = fdopen(dup(fd), "w");
    500 
    501     fprintf(out, " NuPlayer\n");
    502     fprintf(out, "  numFramesTotal(%lld), numFramesDropped(%lld), "
    503                  "percentageDropped(%.2f)\n",
    504                  mNumFramesTotal,
    505                  mNumFramesDropped,
    506                  mNumFramesTotal == 0
    507                     ? 0.0 : (double)mNumFramesDropped / mNumFramesTotal);
    508 
    509     fclose(out);
    510     out = NULL;
    511 
    512     return OK;
    513 }
    514 
    515 void NuPlayerDriver::notifyListener(
    516         int msg, int ext1, int ext2, const Parcel *in) {
    517     if (msg == MEDIA_PLAYBACK_COMPLETE || msg == MEDIA_ERROR) {
    518         mAtEOS = true;
    519     }
    520 
    521     sendEvent(msg, ext1, ext2, in);
    522 }
    523 
    524 void NuPlayerDriver::notifySetDataSourceCompleted(status_t err) {
    525     Mutex::Autolock autoLock(mLock);
    526 
    527     CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING);
    528 
    529     mAsyncResult = err;
    530     mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE;
    531     mCondition.broadcast();
    532 }
    533 
    534 void NuPlayerDriver::notifyPrepareCompleted(status_t err) {
    535     Mutex::Autolock autoLock(mLock);
    536 
    537     if (mState != STATE_PREPARING) {
    538         // We were preparing asynchronously when the client called
    539         // reset(), we sent a premature "prepared" notification and
    540         // then initiated the reset. This notification is stale.
    541         CHECK(mState == STATE_RESET_IN_PROGRESS || mState == STATE_IDLE);
    542         return;
    543     }
    544 
    545     CHECK_EQ(mState, STATE_PREPARING);
    546 
    547     mAsyncResult = err;
    548 
    549     if (err == OK) {
    550         if (mIsAsyncPrepare) {
    551             notifyListener(MEDIA_PREPARED);
    552         }
    553         mState = STATE_PREPARED;
    554     } else {
    555         if (mIsAsyncPrepare) {
    556             notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
    557         }
    558         mState = STATE_UNPREPARED;
    559     }
    560 
    561     mCondition.broadcast();
    562 }
    563 
    564 void NuPlayerDriver::notifyFlagsChanged(uint32_t flags) {
    565     Mutex::Autolock autoLock(mLock);
    566 
    567     mPlayerFlags = flags;
    568 }
    569 
    570 }  // namespace android
    571