Home | History | Annotate | Download | only in stagefright
      1 /*
      2  * Copyright (C) 2012 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 "SimplePlayer"
     19 #include <utils/Log.h>
     20 
     21 #include "SimplePlayer.h"
     22 
     23 #include <gui/SurfaceTextureClient.h>
     24 #include <media/AudioTrack.h>
     25 #include <media/ICrypto.h>
     26 #include <media/stagefright/foundation/ABuffer.h>
     27 #include <media/stagefright/foundation/ADebug.h>
     28 #include <media/stagefright/foundation/AMessage.h>
     29 #include <media/stagefright/MediaCodec.h>
     30 #include <media/stagefright/MediaErrors.h>
     31 #include <media/stagefright/NativeWindowWrapper.h>
     32 #include <media/stagefright/NuMediaExtractor.h>
     33 
     34 namespace android {
     35 
     36 SimplePlayer::SimplePlayer()
     37     : mState(UNINITIALIZED),
     38       mDoMoreStuffGeneration(0),
     39       mStartTimeRealUs(-1ll) {
     40 }
     41 
     42 SimplePlayer::~SimplePlayer() {
     43 }
     44 
     45 // static
     46 status_t PostAndAwaitResponse(
     47         const sp<AMessage> &msg, sp<AMessage> *response) {
     48     status_t err = msg->postAndAwaitResponse(response);
     49 
     50     if (err != OK) {
     51         return err;
     52     }
     53 
     54     if (!(*response)->findInt32("err", &err)) {
     55         err = OK;
     56     }
     57 
     58     return err;
     59 }
     60 status_t SimplePlayer::setDataSource(const char *path) {
     61     sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
     62     msg->setString("path", path);
     63     sp<AMessage> response;
     64     return PostAndAwaitResponse(msg, &response);
     65 }
     66 
     67 status_t SimplePlayer::setSurface(const sp<ISurfaceTexture> &surfaceTexture) {
     68     sp<AMessage> msg = new AMessage(kWhatSetSurface, id());
     69 
     70     sp<SurfaceTextureClient> surfaceTextureClient;
     71     if (surfaceTexture != NULL) {
     72         surfaceTextureClient = new SurfaceTextureClient(surfaceTexture);
     73     }
     74 
     75     msg->setObject(
     76             "native-window", new NativeWindowWrapper(surfaceTextureClient));
     77 
     78     sp<AMessage> response;
     79     return PostAndAwaitResponse(msg, &response);
     80 }
     81 
     82 status_t SimplePlayer::prepare() {
     83     sp<AMessage> msg = new AMessage(kWhatPrepare, id());
     84     sp<AMessage> response;
     85     return PostAndAwaitResponse(msg, &response);
     86 }
     87 
     88 status_t SimplePlayer::start() {
     89     sp<AMessage> msg = new AMessage(kWhatStart, id());
     90     sp<AMessage> response;
     91     return PostAndAwaitResponse(msg, &response);
     92 }
     93 
     94 status_t SimplePlayer::stop() {
     95     sp<AMessage> msg = new AMessage(kWhatStop, id());
     96     sp<AMessage> response;
     97     return PostAndAwaitResponse(msg, &response);
     98 }
     99 
    100 status_t SimplePlayer::reset() {
    101     sp<AMessage> msg = new AMessage(kWhatReset, id());
    102     sp<AMessage> response;
    103     return PostAndAwaitResponse(msg, &response);
    104 }
    105 
    106 void SimplePlayer::onMessageReceived(const sp<AMessage> &msg) {
    107     switch (msg->what()) {
    108         case kWhatSetDataSource:
    109         {
    110             status_t err;
    111             if (mState != UNINITIALIZED) {
    112                 err = INVALID_OPERATION;
    113             } else {
    114                 CHECK(msg->findString("path", &mPath));
    115                 mState = UNPREPARED;
    116             }
    117 
    118             uint32_t replyID;
    119             CHECK(msg->senderAwaitsResponse(&replyID));
    120 
    121             sp<AMessage> response = new AMessage;
    122             response->setInt32("err", err);
    123             response->postReply(replyID);
    124             break;
    125         }
    126 
    127         case kWhatSetSurface:
    128         {
    129             status_t err;
    130             if (mState != UNPREPARED) {
    131                 err = INVALID_OPERATION;
    132             } else {
    133                 sp<RefBase> obj;
    134                 CHECK(msg->findObject("native-window", &obj));
    135 
    136                 mNativeWindow = static_cast<NativeWindowWrapper *>(obj.get());
    137 
    138                 err = OK;
    139             }
    140 
    141             uint32_t replyID;
    142             CHECK(msg->senderAwaitsResponse(&replyID));
    143 
    144             sp<AMessage> response = new AMessage;
    145             response->setInt32("err", err);
    146             response->postReply(replyID);
    147             break;
    148         }
    149 
    150         case kWhatPrepare:
    151         {
    152             status_t err;
    153             if (mState != UNPREPARED) {
    154                 err = INVALID_OPERATION;
    155             } else {
    156                 err = onPrepare();
    157 
    158                 if (err == OK) {
    159                     mState = STOPPED;
    160                 }
    161             }
    162 
    163             uint32_t replyID;
    164             CHECK(msg->senderAwaitsResponse(&replyID));
    165 
    166             sp<AMessage> response = new AMessage;
    167             response->setInt32("err", err);
    168             response->postReply(replyID);
    169             break;
    170         }
    171 
    172         case kWhatStart:
    173         {
    174             status_t err = OK;
    175 
    176             if (mState == UNPREPARED) {
    177                 err = onPrepare();
    178 
    179                 if (err == OK) {
    180                     mState = STOPPED;
    181                 }
    182             }
    183 
    184             if (err == OK) {
    185                 if (mState != STOPPED) {
    186                     err = INVALID_OPERATION;
    187                 } else {
    188                     err = onStart();
    189 
    190                     if (err == OK) {
    191                         mState = STARTED;
    192                     }
    193                 }
    194             }
    195 
    196             uint32_t replyID;
    197             CHECK(msg->senderAwaitsResponse(&replyID));
    198 
    199             sp<AMessage> response = new AMessage;
    200             response->setInt32("err", err);
    201             response->postReply(replyID);
    202             break;
    203         }
    204 
    205         case kWhatStop:
    206         {
    207             status_t err;
    208 
    209             if (mState != STARTED) {
    210                 err = INVALID_OPERATION;
    211             } else {
    212                 err = onStop();
    213 
    214                 if (err == OK) {
    215                     mState = STOPPED;
    216                 }
    217             }
    218 
    219             uint32_t replyID;
    220             CHECK(msg->senderAwaitsResponse(&replyID));
    221 
    222             sp<AMessage> response = new AMessage;
    223             response->setInt32("err", err);
    224             response->postReply(replyID);
    225             break;
    226         }
    227 
    228         case kWhatReset:
    229         {
    230             status_t err = OK;
    231 
    232             if (mState == STARTED) {
    233                 CHECK_EQ(onStop(), (status_t)OK);
    234                 mState = STOPPED;
    235             }
    236 
    237             if (mState == STOPPED) {
    238                 err = onReset();
    239                 mState = UNINITIALIZED;
    240             }
    241 
    242             uint32_t replyID;
    243             CHECK(msg->senderAwaitsResponse(&replyID));
    244 
    245             sp<AMessage> response = new AMessage;
    246             response->setInt32("err", err);
    247             response->postReply(replyID);
    248             break;
    249         }
    250 
    251         case kWhatDoMoreStuff:
    252         {
    253             int32_t generation;
    254             CHECK(msg->findInt32("generation", &generation));
    255 
    256             if (generation != mDoMoreStuffGeneration) {
    257                 break;
    258             }
    259 
    260             status_t err = onDoMoreStuff();
    261 
    262             if (err == OK) {
    263                 msg->post(10000ll);
    264             }
    265             break;
    266         }
    267 
    268         default:
    269             TRESPASS();
    270     }
    271 }
    272 
    273 status_t SimplePlayer::onPrepare() {
    274     CHECK_EQ(mState, UNPREPARED);
    275 
    276     mExtractor = new NuMediaExtractor;
    277 
    278     status_t err = mExtractor->setDataSource(mPath.c_str());
    279 
    280     if (err != OK) {
    281         mExtractor.clear();
    282         return err;
    283     }
    284 
    285     if (mCodecLooper == NULL) {
    286         mCodecLooper = new ALooper;
    287         mCodecLooper->start();
    288     }
    289 
    290     bool haveAudio = false;
    291     bool haveVideo = false;
    292     for (size_t i = 0; i < mExtractor->countTracks(); ++i) {
    293         sp<AMessage> format;
    294         status_t err = mExtractor->getTrackFormat(i, &format);
    295         CHECK_EQ(err, (status_t)OK);
    296 
    297         AString mime;
    298         CHECK(format->findString("mime", &mime));
    299 
    300         if (!haveAudio && !strncasecmp(mime.c_str(), "audio/", 6)) {
    301             haveAudio = true;
    302         } else if (!haveVideo && !strncasecmp(mime.c_str(), "video/", 6)) {
    303             haveVideo = true;
    304         } else {
    305             continue;
    306         }
    307 
    308         err = mExtractor->selectTrack(i);
    309         CHECK_EQ(err, (status_t)OK);
    310 
    311         CodecState *state =
    312             &mStateByTrackIndex.editValueAt(
    313                     mStateByTrackIndex.add(i, CodecState()));
    314 
    315         state->mNumFramesWritten = 0;
    316         state->mCodec = MediaCodec::CreateByType(
    317                 mCodecLooper, mime.c_str(), false /* encoder */);
    318 
    319         CHECK(state->mCodec != NULL);
    320 
    321         err = state->mCodec->configure(
    322                 format,
    323                 mNativeWindow->getSurfaceTextureClient(),
    324                 NULL /* crypto */,
    325                 0 /* flags */);
    326 
    327         CHECK_EQ(err, (status_t)OK);
    328 
    329         size_t j = 0;
    330         sp<ABuffer> buffer;
    331         while (format->findBuffer(StringPrintf("csd-%d", j).c_str(), &buffer)) {
    332             state->mCSD.push_back(buffer);
    333 
    334             ++j;
    335         }
    336     }
    337 
    338     for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) {
    339         CodecState *state = &mStateByTrackIndex.editValueAt(i);
    340 
    341         status_t err = state->mCodec->start();
    342         CHECK_EQ(err, (status_t)OK);
    343 
    344         err = state->mCodec->getInputBuffers(&state->mBuffers[0]);
    345         CHECK_EQ(err, (status_t)OK);
    346 
    347         err = state->mCodec->getOutputBuffers(&state->mBuffers[1]);
    348         CHECK_EQ(err, (status_t)OK);
    349 
    350         for (size_t j = 0; j < state->mCSD.size(); ++j) {
    351             const sp<ABuffer> &srcBuffer = state->mCSD.itemAt(j);
    352 
    353             size_t index;
    354             err = state->mCodec->dequeueInputBuffer(&index, -1ll);
    355             CHECK_EQ(err, (status_t)OK);
    356 
    357             const sp<ABuffer> &dstBuffer = state->mBuffers[0].itemAt(index);
    358 
    359             CHECK_LE(srcBuffer->size(), dstBuffer->capacity());
    360             dstBuffer->setRange(0, srcBuffer->size());
    361             memcpy(dstBuffer->data(), srcBuffer->data(), srcBuffer->size());
    362 
    363             err = state->mCodec->queueInputBuffer(
    364                     index,
    365                     0,
    366                     dstBuffer->size(),
    367                     0ll,
    368                     MediaCodec::BUFFER_FLAG_CODECCONFIG);
    369             CHECK_EQ(err, (status_t)OK);
    370         }
    371     }
    372 
    373     return OK;
    374 }
    375 
    376 status_t SimplePlayer::onStart() {
    377     CHECK_EQ(mState, STOPPED);
    378 
    379     mStartTimeRealUs = -1ll;
    380 
    381     sp<AMessage> msg = new AMessage(kWhatDoMoreStuff, id());
    382     msg->setInt32("generation", ++mDoMoreStuffGeneration);
    383     msg->post();
    384 
    385     return OK;
    386 }
    387 
    388 status_t SimplePlayer::onStop() {
    389     CHECK_EQ(mState, STARTED);
    390 
    391     ++mDoMoreStuffGeneration;
    392 
    393     return OK;
    394 }
    395 
    396 status_t SimplePlayer::onReset() {
    397     CHECK_EQ(mState, STOPPED);
    398 
    399     for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) {
    400         CodecState *state = &mStateByTrackIndex.editValueAt(i);
    401 
    402         CHECK_EQ(state->mCodec->release(), (status_t)OK);
    403     }
    404 
    405     mStartTimeRealUs = -1ll;
    406 
    407     mStateByTrackIndex.clear();
    408     mCodecLooper.clear();
    409     mExtractor.clear();
    410     mNativeWindow.clear();
    411     mPath.clear();
    412 
    413     return OK;
    414 }
    415 
    416 status_t SimplePlayer::onDoMoreStuff() {
    417     ALOGV("onDoMoreStuff");
    418     for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) {
    419         CodecState *state = &mStateByTrackIndex.editValueAt(i);
    420 
    421         status_t err;
    422         do {
    423             size_t index;
    424             err = state->mCodec->dequeueInputBuffer(&index);
    425 
    426             if (err == OK) {
    427                 ALOGV("dequeued input buffer on track %d",
    428                       mStateByTrackIndex.keyAt(i));
    429 
    430                 state->mAvailInputBufferIndices.push_back(index);
    431             } else {
    432                 ALOGV("dequeueInputBuffer on track %d returned %d",
    433                       mStateByTrackIndex.keyAt(i), err);
    434             }
    435         } while (err == OK);
    436 
    437         do {
    438             BufferInfo info;
    439             err = state->mCodec->dequeueOutputBuffer(
    440                     &info.mIndex,
    441                     &info.mOffset,
    442                     &info.mSize,
    443                     &info.mPresentationTimeUs,
    444                     &info.mFlags);
    445 
    446             if (err == OK) {
    447                 ALOGV("dequeued output buffer on track %d",
    448                       mStateByTrackIndex.keyAt(i));
    449 
    450                 state->mAvailOutputBufferInfos.push_back(info);
    451             } else if (err == INFO_FORMAT_CHANGED) {
    452                 err = onOutputFormatChanged(mStateByTrackIndex.keyAt(i), state);
    453                 CHECK_EQ(err, (status_t)OK);
    454             } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) {
    455                 err = state->mCodec->getOutputBuffers(&state->mBuffers[1]);
    456                 CHECK_EQ(err, (status_t)OK);
    457             } else {
    458                 ALOGV("dequeueOutputBuffer on track %d returned %d",
    459                       mStateByTrackIndex.keyAt(i), err);
    460             }
    461         } while (err == OK
    462                 || err == INFO_FORMAT_CHANGED
    463                 || err == INFO_OUTPUT_BUFFERS_CHANGED);
    464     }
    465 
    466     for (;;) {
    467         size_t trackIndex;
    468         status_t err = mExtractor->getSampleTrackIndex(&trackIndex);
    469 
    470         if (err != OK) {
    471             ALOGI("encountered input EOS.");
    472             break;
    473         } else {
    474             CodecState *state = &mStateByTrackIndex.editValueFor(trackIndex);
    475 
    476             if (state->mAvailInputBufferIndices.empty()) {
    477                 break;
    478             }
    479 
    480             size_t index = *state->mAvailInputBufferIndices.begin();
    481             state->mAvailInputBufferIndices.erase(
    482                     state->mAvailInputBufferIndices.begin());
    483 
    484             const sp<ABuffer> &dstBuffer =
    485                 state->mBuffers[0].itemAt(index);
    486 
    487             err = mExtractor->readSampleData(dstBuffer);
    488             CHECK_EQ(err, (status_t)OK);
    489 
    490             int64_t timeUs;
    491             CHECK_EQ(mExtractor->getSampleTime(&timeUs), (status_t)OK);
    492 
    493             err = state->mCodec->queueInputBuffer(
    494                     index,
    495                     dstBuffer->offset(),
    496                     dstBuffer->size(),
    497                     timeUs,
    498                     0);
    499             CHECK_EQ(err, (status_t)OK);
    500 
    501             ALOGV("enqueued input data on track %d", trackIndex);
    502 
    503             err = mExtractor->advance();
    504             CHECK_EQ(err, (status_t)OK);
    505         }
    506     }
    507 
    508     int64_t nowUs = ALooper::GetNowUs();
    509 
    510     if (mStartTimeRealUs < 0ll) {
    511         mStartTimeRealUs = nowUs + 1000000ll;
    512     }
    513 
    514     for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) {
    515         CodecState *state = &mStateByTrackIndex.editValueAt(i);
    516 
    517         while (!state->mAvailOutputBufferInfos.empty()) {
    518             BufferInfo *info = &*state->mAvailOutputBufferInfos.begin();
    519 
    520             int64_t whenRealUs = info->mPresentationTimeUs + mStartTimeRealUs;
    521             int64_t lateByUs = nowUs - whenRealUs;
    522 
    523             if (lateByUs > -10000ll) {
    524                 bool release = true;
    525 
    526                 if (lateByUs > 30000ll) {
    527                     ALOGI("track %d buffer late by %lld us, dropping.",
    528                           mStateByTrackIndex.keyAt(i), lateByUs);
    529                     state->mCodec->releaseOutputBuffer(info->mIndex);
    530                 } else {
    531                     if (state->mAudioTrack != NULL) {
    532                         const sp<ABuffer> &srcBuffer =
    533                             state->mBuffers[1].itemAt(info->mIndex);
    534 
    535                         renderAudio(state, info, srcBuffer);
    536 
    537                         if (info->mSize > 0) {
    538                             release = false;
    539                         }
    540                     }
    541 
    542                     if (release) {
    543                         state->mCodec->renderOutputBufferAndRelease(
    544                                 info->mIndex);
    545                     }
    546                 }
    547 
    548                 if (release) {
    549                     state->mAvailOutputBufferInfos.erase(
    550                             state->mAvailOutputBufferInfos.begin());
    551 
    552                     info = NULL;
    553                 } else {
    554                     break;
    555                 }
    556             } else {
    557                 ALOGV("track %d buffer early by %lld us.",
    558                       mStateByTrackIndex.keyAt(i), -lateByUs);
    559                 break;
    560             }
    561         }
    562     }
    563 
    564     return OK;
    565 }
    566 
    567 status_t SimplePlayer::onOutputFormatChanged(
    568         size_t trackIndex, CodecState *state) {
    569     sp<AMessage> format;
    570     status_t err = state->mCodec->getOutputFormat(&format);
    571 
    572     if (err != OK) {
    573         return err;
    574     }
    575 
    576     AString mime;
    577     CHECK(format->findString("mime", &mime));
    578 
    579     if (!strncasecmp(mime.c_str(), "audio/", 6)) {
    580         int32_t channelCount;
    581         int32_t sampleRate;
    582         CHECK(format->findInt32("channel-count", &channelCount));
    583         CHECK(format->findInt32("sample-rate", &sampleRate));
    584 
    585         state->mAudioTrack = new AudioTrack(
    586                 AUDIO_STREAM_MUSIC,
    587                 sampleRate,
    588                 AUDIO_FORMAT_PCM_16_BIT,
    589                 audio_channel_out_mask_from_count(channelCount),
    590                 0);
    591 
    592         state->mNumFramesWritten = 0;
    593     }
    594 
    595     return OK;
    596 }
    597 
    598 void SimplePlayer::renderAudio(
    599         CodecState *state, BufferInfo *info, const sp<ABuffer> &buffer) {
    600     CHECK(state->mAudioTrack != NULL);
    601 
    602     if (state->mAudioTrack->stopped()) {
    603         state->mAudioTrack->start();
    604     }
    605 
    606     uint32_t numFramesPlayed;
    607     CHECK_EQ(state->mAudioTrack->getPosition(&numFramesPlayed), (status_t)OK);
    608 
    609     uint32_t numFramesAvailableToWrite =
    610         state->mAudioTrack->frameCount()
    611             - (state->mNumFramesWritten - numFramesPlayed);
    612 
    613     size_t numBytesAvailableToWrite =
    614         numFramesAvailableToWrite * state->mAudioTrack->frameSize();
    615 
    616     size_t copy = info->mSize;
    617     if (copy > numBytesAvailableToWrite) {
    618         copy = numBytesAvailableToWrite;
    619     }
    620 
    621     if (copy == 0) {
    622         return;
    623     }
    624 
    625     int64_t startTimeUs = ALooper::GetNowUs();
    626 
    627     ssize_t nbytes = state->mAudioTrack->write(
    628             buffer->base() + info->mOffset, copy);
    629 
    630     CHECK_EQ(nbytes, (ssize_t)copy);
    631 
    632     int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
    633 
    634     uint32_t numFramesWritten = nbytes / state->mAudioTrack->frameSize();
    635 
    636     if (delayUs > 2000ll) {
    637         ALOGW("AudioTrack::write took %lld us, numFramesAvailableToWrite=%u, "
    638               "numFramesWritten=%u",
    639               delayUs, numFramesAvailableToWrite, numFramesWritten);
    640     }
    641 
    642     info->mOffset += nbytes;
    643     info->mSize -= nbytes;
    644 
    645     state->mNumFramesWritten += numFramesWritten;
    646 }
    647 
    648 }  // namespace android
    649