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             mPlayer->pause();
    259             break;
    260 
    261         default:
    262             return INVALID_OPERATION;
    263     }
    264 
    265     mState = STATE_PAUSED;
    266 
    267     return OK;
    268 }
    269 
    270 bool NuPlayerDriver::isPlaying() {
    271     return mState == STATE_RUNNING && !mAtEOS;
    272 }
    273 
    274 status_t NuPlayerDriver::seekTo(int msec) {
    275     Mutex::Autolock autoLock(mLock);
    276 
    277     int64_t seekTimeUs = msec * 1000ll;
    278 
    279     switch (mState) {
    280         case STATE_PREPARED:
    281         {
    282             mStartupSeekTimeUs = seekTimeUs;
    283             break;
    284         }
    285 
    286         case STATE_RUNNING:
    287         case STATE_PAUSED:
    288         {
    289             mAtEOS = false;
    290             mPlayer->seekToAsync(seekTimeUs);
    291             break;
    292         }
    293 
    294         default:
    295             return INVALID_OPERATION;
    296     }
    297 
    298     return OK;
    299 }
    300 
    301 status_t NuPlayerDriver::getCurrentPosition(int *msec) {
    302     Mutex::Autolock autoLock(mLock);
    303 
    304     if (mPositionUs < 0) {
    305         *msec = 0;
    306     } else {
    307         *msec = (mPositionUs + 500ll) / 1000;
    308     }
    309 
    310     return OK;
    311 }
    312 
    313 status_t NuPlayerDriver::getDuration(int *msec) {
    314     Mutex::Autolock autoLock(mLock);
    315 
    316     if (mDurationUs < 0) {
    317         return UNKNOWN_ERROR;
    318     }
    319 
    320     *msec = (mDurationUs + 500ll) / 1000;
    321 
    322     return OK;
    323 }
    324 
    325 status_t NuPlayerDriver::reset() {
    326     Mutex::Autolock autoLock(mLock);
    327 
    328     switch (mState) {
    329         case STATE_IDLE:
    330             return OK;
    331 
    332         case STATE_SET_DATASOURCE_PENDING:
    333         case STATE_RESET_IN_PROGRESS:
    334             return INVALID_OPERATION;
    335 
    336         case STATE_PREPARING:
    337         {
    338             CHECK(mIsAsyncPrepare);
    339 
    340             notifyListener(MEDIA_PREPARED);
    341             break;
    342         }
    343 
    344         default:
    345             break;
    346     }
    347 
    348     mState = STATE_RESET_IN_PROGRESS;
    349     mPlayer->resetAsync();
    350 
    351     while (mState == STATE_RESET_IN_PROGRESS) {
    352         mCondition.wait(mLock);
    353     }
    354 
    355     mDurationUs = -1;
    356     mPositionUs = -1;
    357     mStartupSeekTimeUs = -1;
    358 
    359     return OK;
    360 }
    361 
    362 status_t NuPlayerDriver::setLooping(int loop) {
    363     return INVALID_OPERATION;
    364 }
    365 
    366 player_type NuPlayerDriver::playerType() {
    367     return NU_PLAYER;
    368 }
    369 
    370 status_t NuPlayerDriver::invoke(const Parcel &request, Parcel *reply) {
    371     if (reply == NULL) {
    372         ALOGE("reply is a NULL pointer");
    373         return BAD_VALUE;
    374     }
    375 
    376     int32_t methodId;
    377     status_t ret = request.readInt32(&methodId);
    378     if (ret != OK) {
    379         ALOGE("Failed to retrieve the requested method to invoke");
    380         return ret;
    381     }
    382 
    383     switch (methodId) {
    384         case INVOKE_ID_SET_VIDEO_SCALING_MODE:
    385         {
    386             int mode = request.readInt32();
    387             return mPlayer->setVideoScalingMode(mode);
    388         }
    389 
    390         default:
    391         {
    392             return INVALID_OPERATION;
    393         }
    394     }
    395 }
    396 
    397 void NuPlayerDriver::setAudioSink(const sp<AudioSink> &audioSink) {
    398     mPlayer->setAudioSink(audioSink);
    399 }
    400 
    401 status_t NuPlayerDriver::setParameter(int key, const Parcel &request) {
    402     return INVALID_OPERATION;
    403 }
    404 
    405 status_t NuPlayerDriver::getParameter(int key, Parcel *reply) {
    406     return INVALID_OPERATION;
    407 }
    408 
    409 status_t NuPlayerDriver::getMetadata(
    410         const media::Metadata::Filter& ids, Parcel *records) {
    411     Mutex::Autolock autoLock(mLock);
    412 
    413     using media::Metadata;
    414 
    415     Metadata meta(records);
    416 
    417     meta.appendBool(
    418             Metadata::kPauseAvailable,
    419             mPlayerFlags & NuPlayer::Source::FLAG_CAN_PAUSE);
    420 
    421     meta.appendBool(
    422             Metadata::kSeekBackwardAvailable,
    423             mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_BACKWARD);
    424 
    425     meta.appendBool(
    426             Metadata::kSeekForwardAvailable,
    427             mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_FORWARD);
    428 
    429     meta.appendBool(
    430             Metadata::kSeekAvailable,
    431             mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK);
    432 
    433     return OK;
    434 }
    435 
    436 void NuPlayerDriver::notifyResetComplete() {
    437     Mutex::Autolock autoLock(mLock);
    438 
    439     CHECK_EQ(mState, STATE_RESET_IN_PROGRESS);
    440     mState = STATE_IDLE;
    441     mCondition.broadcast();
    442 }
    443 
    444 void NuPlayerDriver::notifySetSurfaceComplete() {
    445     Mutex::Autolock autoLock(mLock);
    446 
    447     CHECK(mSetSurfaceInProgress);
    448     mSetSurfaceInProgress = false;
    449 
    450     mCondition.broadcast();
    451 }
    452 
    453 void NuPlayerDriver::notifyDuration(int64_t durationUs) {
    454     Mutex::Autolock autoLock(mLock);
    455     mDurationUs = durationUs;
    456 }
    457 
    458 void NuPlayerDriver::notifyPosition(int64_t positionUs) {
    459     Mutex::Autolock autoLock(mLock);
    460     mPositionUs = positionUs;
    461 }
    462 
    463 void NuPlayerDriver::notifySeekComplete() {
    464     notifyListener(MEDIA_SEEK_COMPLETE);
    465 }
    466 
    467 void NuPlayerDriver::notifyFrameStats(
    468         int64_t numFramesTotal, int64_t numFramesDropped) {
    469     Mutex::Autolock autoLock(mLock);
    470     mNumFramesTotal = numFramesTotal;
    471     mNumFramesDropped = numFramesDropped;
    472 }
    473 
    474 status_t NuPlayerDriver::dump(int fd, const Vector<String16> &args) const {
    475     Mutex::Autolock autoLock(mLock);
    476 
    477     FILE *out = fdopen(dup(fd), "w");
    478 
    479     fprintf(out, " NuPlayer\n");
    480     fprintf(out, "  numFramesTotal(%lld), numFramesDropped(%lld), "
    481                  "percentageDropped(%.2f)\n",
    482                  mNumFramesTotal,
    483                  mNumFramesDropped,
    484                  mNumFramesTotal == 0
    485                     ? 0.0 : (double)mNumFramesDropped / mNumFramesTotal);
    486 
    487     fclose(out);
    488     out = NULL;
    489 
    490     return OK;
    491 }
    492 
    493 void NuPlayerDriver::notifyListener(int msg, int ext1, int ext2) {
    494     if (msg == MEDIA_PLAYBACK_COMPLETE || msg == MEDIA_ERROR) {
    495         mAtEOS = true;
    496     }
    497 
    498     sendEvent(msg, ext1, ext2);
    499 }
    500 
    501 void NuPlayerDriver::notifySetDataSourceCompleted(status_t err) {
    502     Mutex::Autolock autoLock(mLock);
    503 
    504     CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING);
    505 
    506     mAsyncResult = err;
    507     mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE;
    508     mCondition.broadcast();
    509 }
    510 
    511 void NuPlayerDriver::notifyPrepareCompleted(status_t err) {
    512     Mutex::Autolock autoLock(mLock);
    513 
    514     if (mState != STATE_PREPARING) {
    515         // We were preparing asynchronously when the client called
    516         // reset(), we sent a premature "prepared" notification and
    517         // then initiated the reset. This notification is stale.
    518         CHECK(mState == STATE_RESET_IN_PROGRESS || mState == STATE_IDLE);
    519         return;
    520     }
    521 
    522     CHECK_EQ(mState, STATE_PREPARING);
    523 
    524     mAsyncResult = err;
    525 
    526     if (err == OK) {
    527         if (mIsAsyncPrepare) {
    528             notifyListener(MEDIA_PREPARED);
    529         }
    530         mState = STATE_PREPARED;
    531     } else {
    532         if (mIsAsyncPrepare) {
    533             notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
    534         }
    535         mState = STATE_UNPREPARED;
    536     }
    537 
    538     mCondition.broadcast();
    539 }
    540 
    541 void NuPlayerDriver::notifyFlagsChanged(uint32_t flags) {
    542     Mutex::Autolock autoLock(mLock);
    543 
    544     mPlayerFlags = flags;
    545 }
    546 
    547 }  // namespace android
    548