Home | History | Annotate | Download | only in libmediaplayerservice
      1 /*
      2 ** Copyright 2007, 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 "VorbisPlayer"
     19 #include "utils/Log.h"
     20 
     21 #include <stdio.h>
     22 #include <assert.h>
     23 #include <limits.h>
     24 #include <unistd.h>
     25 #include <fcntl.h>
     26 #include <sched.h>
     27 #include <sys/types.h>
     28 #include <sys/stat.h>
     29 
     30 
     31 #include "VorbisPlayer.h"
     32 
     33 #ifdef HAVE_GETTID
     34 static pid_t myTid() { return gettid(); }
     35 #else
     36 static pid_t myTid() { return getpid(); }
     37 #endif
     38 
     39 // ----------------------------------------------------------------------------
     40 
     41 namespace android {
     42 
     43 // ----------------------------------------------------------------------------
     44 
     45 // TODO: Determine appropriate return codes
     46 static status_t ERROR_NOT_OPEN = -1;
     47 static status_t ERROR_OPEN_FAILED = -2;
     48 static status_t ERROR_ALLOCATE_FAILED = -4;
     49 static status_t ERROR_NOT_SUPPORTED = -8;
     50 static status_t ERROR_NOT_READY = -16;
     51 static status_t STATE_INIT = 0;
     52 static status_t STATE_ERROR = 1;
     53 static status_t STATE_OPEN = 2;
     54 
     55 
     56 VorbisPlayer::VorbisPlayer() :
     57     mAudioBuffer(NULL), mPlayTime(-1), mDuration(-1), mState(STATE_ERROR),
     58     mStreamType(AudioSystem::MUSIC), mLoop(false), mAndroidLoop(false),
     59     mExit(false), mPaused(false), mRender(false), mRenderTid(-1)
     60 {
     61     LOGV("constructor\n");
     62     memset(&mVorbisFile, 0, sizeof mVorbisFile);
     63 }
     64 
     65 void VorbisPlayer::onFirstRef()
     66 {
     67     LOGV("onFirstRef");
     68     // create playback thread
     69     Mutex::Autolock l(mMutex);
     70     createThreadEtc(renderThread, this, "vorbis decoder", ANDROID_PRIORITY_AUDIO);
     71     mCondition.wait(mMutex);
     72     if (mRenderTid > 0) {
     73         LOGV("render thread(%d) started", mRenderTid);
     74         mState = STATE_INIT;
     75     }
     76 }
     77 
     78 status_t VorbisPlayer::initCheck()
     79 {
     80     if (mState != STATE_ERROR) return NO_ERROR;
     81     return ERROR_NOT_READY;
     82 }
     83 
     84 VorbisPlayer::~VorbisPlayer() {
     85     LOGV("VorbisPlayer destructor\n");
     86     release();
     87 }
     88 
     89 status_t VorbisPlayer::setDataSource(
     90         const char *uri, const KeyedVector<String8, String8> *headers) {
     91     return setdatasource(uri, -1, 0, 0x7ffffffffffffffLL); // intentionally less than LONG_MAX
     92 }
     93 
     94 status_t VorbisPlayer::setDataSource(int fd, int64_t offset, int64_t length)
     95 {
     96     return setdatasource(NULL, fd, offset, length);
     97 }
     98 
     99 size_t VorbisPlayer::vp_fread(void *buf, size_t size, size_t nmemb, void *me) {
    100     VorbisPlayer *self = (VorbisPlayer*) me;
    101 
    102     long curpos = vp_ftell(me);
    103     while (nmemb != 0 && (curpos + size * nmemb) > self->mLength) {
    104         nmemb--;
    105     }
    106     return fread(buf, size, nmemb, self->mFile);
    107 }
    108 
    109 int VorbisPlayer::vp_fseek(void *me, ogg_int64_t off, int whence) {
    110     VorbisPlayer *self = (VorbisPlayer*) me;
    111     if (whence == SEEK_SET)
    112         return fseek(self->mFile, off + self->mOffset, whence);
    113     else if (whence == SEEK_CUR)
    114         return fseek(self->mFile, off, whence);
    115     else if (whence == SEEK_END)
    116         return fseek(self->mFile, self->mOffset + self->mLength + off, SEEK_SET);
    117     return -1;
    118 }
    119 
    120 int VorbisPlayer::vp_fclose(void *me) {
    121     LOGV("vp_fclose");
    122     VorbisPlayer *self = (VorbisPlayer*) me;
    123     int ret = fclose (self->mFile);
    124     self->mFile = NULL;
    125     return ret;
    126 }
    127 
    128 long VorbisPlayer::vp_ftell(void *me) {
    129     VorbisPlayer *self = (VorbisPlayer*) me;
    130     return ftell(self->mFile) - self->mOffset;
    131 }
    132 
    133 status_t VorbisPlayer::setdatasource(const char *path, int fd, int64_t offset, int64_t length)
    134 {
    135     LOGV("setDataSource url=%s, fd=%d\n", path, fd);
    136 
    137     // file still open?
    138     Mutex::Autolock l(mMutex);
    139     if (mState == STATE_OPEN) {
    140         reset_nosync();
    141     }
    142 
    143     // open file and set paused state
    144     if (path) {
    145         mFile = fopen(path, "r");
    146     } else {
    147         mFile = fdopen(dup(fd), "r");
    148     }
    149     if (mFile == NULL) {
    150         return ERROR_OPEN_FAILED;
    151     }
    152 
    153     struct stat sb;
    154     int ret;
    155     if (path) {
    156         ret = stat(path, &sb);
    157     } else {
    158         ret = fstat(fd, &sb);
    159     }
    160     if (ret != 0) {
    161         mState = STATE_ERROR;
    162         fclose(mFile);
    163         return ERROR_OPEN_FAILED;
    164     }
    165     if (sb.st_size > (length + offset)) {
    166         mLength = length;
    167     } else {
    168         mLength = sb.st_size - offset;
    169     }
    170 
    171     ov_callbacks callbacks = {
    172         (size_t (*)(void *, size_t, size_t, void *))  vp_fread,
    173         (int (*)(void *, ogg_int64_t, int))           vp_fseek,
    174         (int (*)(void *))                             vp_fclose,
    175         (long (*)(void *))                            vp_ftell
    176     };
    177 
    178     mOffset = offset;
    179     fseek(mFile, offset, SEEK_SET);
    180 
    181     int result = ov_open_callbacks(this, &mVorbisFile, NULL, 0, callbacks);
    182     if (result < 0) {
    183         LOGE("ov_open() failed: [%d]\n", (int)result);
    184         mState = STATE_ERROR;
    185         fclose(mFile);
    186         return ERROR_OPEN_FAILED;
    187     }
    188 
    189     // look for the android loop tag  (for ringtones)
    190     char **ptr = ov_comment(&mVorbisFile,-1)->user_comments;
    191     while(*ptr) {
    192         // does the comment start with ANDROID_LOOP_TAG
    193         if(strncmp(*ptr, ANDROID_LOOP_TAG, strlen(ANDROID_LOOP_TAG)) == 0) {
    194             // read the value of the tag
    195             char *val = *ptr + strlen(ANDROID_LOOP_TAG) + 1;
    196             mAndroidLoop = (strncmp(val, "true", 4) == 0);
    197         }
    198         // we keep parsing even after finding one occurence of ANDROID_LOOP_TAG,
    199         // as we could find another one  (the tag might have been appended more than once).
    200         ++ptr;
    201     }
    202     LOGV_IF(mAndroidLoop, "looped sound");
    203 
    204     mState = STATE_OPEN;
    205     return NO_ERROR;
    206 }
    207 
    208 status_t VorbisPlayer::prepare()
    209 {
    210     LOGV("prepare\n");
    211     if (mState != STATE_OPEN ) {
    212         return ERROR_NOT_OPEN;
    213     }
    214     return NO_ERROR;
    215 }
    216 
    217 status_t VorbisPlayer::prepareAsync() {
    218     LOGV("prepareAsync\n");
    219     // can't hold the lock here because of the callback
    220     // it's safe because we don't change state
    221     if (mState != STATE_OPEN ) {
    222         sendEvent(MEDIA_ERROR);
    223         return NO_ERROR;
    224     }
    225     sendEvent(MEDIA_PREPARED);
    226     return NO_ERROR;
    227 }
    228 
    229 status_t VorbisPlayer::start()
    230 {
    231     LOGV("start\n");
    232     Mutex::Autolock l(mMutex);
    233     if (mState != STATE_OPEN) {
    234         return ERROR_NOT_OPEN;
    235     }
    236 
    237     mPaused = false;
    238     mRender = true;
    239 
    240     // wake up render thread
    241     LOGV("  wakeup render thread\n");
    242     mCondition.signal();
    243     return NO_ERROR;
    244 }
    245 
    246 status_t VorbisPlayer::stop()
    247 {
    248     LOGV("stop\n");
    249     Mutex::Autolock l(mMutex);
    250     if (mState != STATE_OPEN) {
    251         return ERROR_NOT_OPEN;
    252     }
    253     mPaused = true;
    254     mRender = false;
    255     return NO_ERROR;
    256 }
    257 
    258 status_t VorbisPlayer::seekTo(int position)
    259 {
    260     LOGV("seekTo %d\n", position);
    261     Mutex::Autolock l(mMutex);
    262     if (mState != STATE_OPEN) {
    263         return ERROR_NOT_OPEN;
    264     }
    265 
    266     int result = ov_time_seek(&mVorbisFile, position);
    267     if (result != 0) {
    268         LOGE("ov_time_seek() returned %d\n", result);
    269         return result;
    270     }
    271     sendEvent(MEDIA_SEEK_COMPLETE);
    272     return NO_ERROR;
    273 }
    274 
    275 status_t VorbisPlayer::pause()
    276 {
    277     LOGV("pause\n");
    278     Mutex::Autolock l(mMutex);
    279     if (mState != STATE_OPEN) {
    280         return ERROR_NOT_OPEN;
    281     }
    282     mPaused = true;
    283     return NO_ERROR;
    284 }
    285 
    286 bool VorbisPlayer::isPlaying()
    287 {
    288     LOGV("isPlaying\n");
    289     if (mState == STATE_OPEN) {
    290         return mRender;
    291     }
    292     return false;
    293 }
    294 
    295 status_t VorbisPlayer::getCurrentPosition(int* position)
    296 {
    297     LOGV("getCurrentPosition\n");
    298     Mutex::Autolock l(mMutex);
    299     if (mState != STATE_OPEN) {
    300         LOGE("getCurrentPosition(): file not open");
    301         return ERROR_NOT_OPEN;
    302     }
    303     *position = ov_time_tell(&mVorbisFile);
    304     if (*position < 0) {
    305         LOGE("getCurrentPosition(): ov_time_tell returned %d", *position);
    306         return *position;
    307     }
    308     return NO_ERROR;
    309 }
    310 
    311 status_t VorbisPlayer::getDuration(int* duration)
    312 {
    313     LOGV("getDuration\n");
    314     Mutex::Autolock l(mMutex);
    315     if (mState != STATE_OPEN) {
    316         return ERROR_NOT_OPEN;
    317     }
    318 
    319     int ret = ov_time_total(&mVorbisFile, -1);
    320     if (ret == OV_EINVAL) {
    321         return -1;
    322     }
    323 
    324     *duration = ret;
    325     return NO_ERROR;
    326 }
    327 
    328 status_t VorbisPlayer::release()
    329 {
    330     LOGV("release\n");
    331     Mutex::Autolock l(mMutex);
    332     reset_nosync();
    333 
    334     // TODO: timeout when thread won't exit
    335     // wait for render thread to exit
    336     if (mRenderTid > 0) {
    337         mExit = true;
    338         mCondition.signal();
    339         mCondition.wait(mMutex);
    340     }
    341     return NO_ERROR;
    342 }
    343 
    344 status_t VorbisPlayer::reset()
    345 {
    346     LOGV("reset\n");
    347     Mutex::Autolock l(mMutex);
    348     return reset_nosync();
    349 }
    350 
    351 // always call with lock held
    352 status_t VorbisPlayer::reset_nosync()
    353 {
    354     // close file
    355     if (mFile != NULL) {
    356         ov_clear(&mVorbisFile); // this also closes the FILE
    357         if (mFile != NULL) {
    358             LOGV("OOPS! Vorbis didn't close the file");
    359             fclose(mFile);
    360             mFile = NULL;
    361         }
    362     }
    363     mState = STATE_ERROR;
    364 
    365     mPlayTime = -1;
    366     mDuration = -1;
    367     mLoop = false;
    368     mAndroidLoop = false;
    369     mPaused = false;
    370     mRender = false;
    371     return NO_ERROR;
    372 }
    373 
    374 status_t VorbisPlayer::setLooping(int loop)
    375 {
    376     LOGV("setLooping\n");
    377     Mutex::Autolock l(mMutex);
    378     mLoop = (loop != 0);
    379     return NO_ERROR;
    380 }
    381 
    382 status_t VorbisPlayer::createOutputTrack() {
    383     // open audio track
    384     vorbis_info *vi = ov_info(&mVorbisFile, -1);
    385 
    386     LOGV("Create AudioTrack object: rate=%ld, channels=%d\n",
    387             vi->rate, vi->channels);
    388     if (mAudioSink->open(vi->rate, vi->channels, AudioSystem::PCM_16_BIT, DEFAULT_AUDIOSINK_BUFFERCOUNT) != NO_ERROR) {
    389         LOGE("mAudioSink open failed");
    390         return ERROR_OPEN_FAILED;
    391     }
    392     return NO_ERROR;
    393 }
    394 
    395 int VorbisPlayer::renderThread(void* p) {
    396     return ((VorbisPlayer*)p)->render();
    397 }
    398 
    399 #define AUDIOBUFFER_SIZE 4096
    400 
    401 int VorbisPlayer::render() {
    402     int result = -1;
    403     int temp;
    404     int current_section = 0;
    405     bool audioStarted = false;
    406 
    407     LOGV("render\n");
    408 
    409     // allocate render buffer
    410     mAudioBuffer = new char[AUDIOBUFFER_SIZE];
    411     if (!mAudioBuffer) {
    412         LOGE("mAudioBuffer allocate failed\n");
    413         goto threadExit;
    414     }
    415 
    416     // let main thread know we're ready
    417     {
    418         Mutex::Autolock l(mMutex);
    419         mRenderTid = myTid();
    420         mCondition.signal();
    421     }
    422 
    423     while (1) {
    424         long numread = 0;
    425         {
    426             Mutex::Autolock l(mMutex);
    427 
    428             // pausing?
    429             if (mPaused) {
    430                 if (mAudioSink->ready()) mAudioSink->pause();
    431                 mRender = false;
    432                 audioStarted = false;
    433             }
    434 
    435             // nothing to render, wait for client thread to wake us up
    436             if (!mExit && !mRender) {
    437                 LOGV("render - signal wait\n");
    438                 mCondition.wait(mMutex);
    439                 LOGV("render - signal rx'd\n");
    440             }
    441             if (mExit) break;
    442 
    443             // We could end up here if start() is called, and before we get a
    444             // chance to run, the app calls stop() or reset(). Re-check render
    445             // flag so we don't try to render in stop or reset state.
    446             if (!mRender) continue;
    447 
    448             // render vorbis data into the input buffer
    449             numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, &current_section);
    450             if (numread == 0) {
    451                 // end of file, do we need to loop?
    452                 // ...
    453                 if (mLoop || mAndroidLoop) {
    454                     ov_time_seek(&mVorbisFile, 0);
    455                     current_section = 0;
    456                     numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, &current_section);
    457                 } else {
    458                     mAudioSink->stop();
    459                     audioStarted = false;
    460                     mRender = false;
    461                     mPaused = true;
    462                     int endpos = ov_time_tell(&mVorbisFile);
    463 
    464                     LOGV("send MEDIA_PLAYBACK_COMPLETE");
    465                     sendEvent(MEDIA_PLAYBACK_COMPLETE);
    466 
    467                     // wait until we're started again
    468                     LOGV("playback complete - wait for signal");
    469                     mCondition.wait(mMutex);
    470                     LOGV("playback complete - signal rx'd");
    471                     if (mExit) break;
    472 
    473                     // if we're still at the end, restart from the beginning
    474                     if (mState == STATE_OPEN) {
    475                         int curpos = ov_time_tell(&mVorbisFile);
    476                         if (curpos == endpos) {
    477                             ov_time_seek(&mVorbisFile, 0);
    478                         }
    479                         current_section = 0;
    480                         numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, &current_section);
    481                     }
    482                 }
    483             }
    484         }
    485 
    486         // codec returns negative number on error
    487         if (numread < 0) {
    488             LOGE("Error in Vorbis decoder");
    489             sendEvent(MEDIA_ERROR);
    490             break;
    491         }
    492 
    493         // create audio output track if necessary
    494         if (!mAudioSink->ready()) {
    495             LOGV("render - create output track\n");
    496             if (createOutputTrack() != NO_ERROR)
    497                 break;
    498         }
    499 
    500         // Write data to the audio hardware
    501         if ((temp = mAudioSink->write(mAudioBuffer, numread)) < 0) {
    502             LOGE("Error in writing:%d",temp);
    503             result = temp;
    504             break;
    505         }
    506 
    507         // start audio output if necessary
    508         if (!audioStarted && !mPaused && !mExit) {
    509             LOGV("render - starting audio\n");
    510             mAudioSink->start();
    511             audioStarted = true;
    512         }
    513     }
    514 
    515 threadExit:
    516     mAudioSink.clear();
    517     if (mAudioBuffer) {
    518         delete [] mAudioBuffer;
    519         mAudioBuffer = NULL;
    520     }
    521 
    522     // tell main thread goodbye
    523     Mutex::Autolock l(mMutex);
    524     mRenderTid = -1;
    525     mCondition.signal();
    526     return result;
    527 }
    528 
    529 } // end namespace android
    530