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 "NuPlayerDecoder"
     19 #include <utils/Log.h>
     20 
     21 #include "NuPlayerDecoder.h"
     22 
     23 #include "ESDS.h"
     24 
     25 #include <media/stagefright/foundation/ABuffer.h>
     26 #include <media/stagefright/foundation/ADebug.h>
     27 #include <media/stagefright/foundation/AMessage.h>
     28 #include <media/stagefright/ACodec.h>
     29 #include <media/stagefright/MediaDefs.h>
     30 #include <media/stagefright/MetaData.h>
     31 #include <media/stagefright/Utils.h>
     32 
     33 namespace android {
     34 
     35 NuPlayer::Decoder::Decoder(
     36         const sp<AMessage> &notify,
     37         const sp<NativeWindowWrapper> &nativeWindow)
     38     : mNotify(notify),
     39       mNativeWindow(nativeWindow) {
     40 }
     41 
     42 NuPlayer::Decoder::~Decoder() {
     43 }
     44 
     45 void NuPlayer::Decoder::configure(const sp<MetaData> &meta) {
     46     CHECK(mCodec == NULL);
     47 
     48     const char *mime;
     49     CHECK(meta->findCString(kKeyMIMEType, &mime));
     50 
     51     sp<AMessage> notifyMsg =
     52         new AMessage(kWhatCodecNotify, id());
     53 
     54     sp<AMessage> format = makeFormat(meta);
     55 
     56     if (mNativeWindow != NULL) {
     57         format->setObject("native-window", mNativeWindow);
     58     }
     59 
     60     // Current video decoders do not return from OMX_FillThisBuffer
     61     // quickly, violating the OpenMAX specs, until that is remedied
     62     // we need to invest in an extra looper to free the main event
     63     // queue.
     64     bool needDedicatedLooper = !strncasecmp(mime, "video/", 6);
     65 
     66     mCodec = new ACodec;
     67 
     68     if (needDedicatedLooper && mCodecLooper == NULL) {
     69         mCodecLooper = new ALooper;
     70         mCodecLooper->setName("NuPlayerDecoder");
     71         mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
     72     }
     73 
     74     (needDedicatedLooper ? mCodecLooper : looper())->registerHandler(mCodec);
     75 
     76     mCodec->setNotificationMessage(notifyMsg);
     77     mCodec->initiateSetup(format);
     78 }
     79 
     80 void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
     81     switch (msg->what()) {
     82         case kWhatCodecNotify:
     83         {
     84             int32_t what;
     85             CHECK(msg->findInt32("what", &what));
     86 
     87             if (what == ACodec::kWhatFillThisBuffer) {
     88                 onFillThisBuffer(msg);
     89             } else {
     90                 sp<AMessage> notify = mNotify->dup();
     91                 notify->setMessage("codec-request", msg);
     92                 notify->post();
     93             }
     94             break;
     95         }
     96 
     97         default:
     98             TRESPASS();
     99             break;
    100     }
    101 }
    102 
    103 sp<AMessage> NuPlayer::Decoder::makeFormat(const sp<MetaData> &meta) {
    104     CHECK(mCSD.isEmpty());
    105 
    106     sp<AMessage> msg;
    107     CHECK_EQ(convertMetaDataToMessage(meta, &msg), (status_t)OK);
    108 
    109     mCSDIndex = 0;
    110     for (size_t i = 0;; ++i) {
    111         sp<ABuffer> csd;
    112         if (!msg->findBuffer(StringPrintf("csd-%d", i).c_str(), &csd)) {
    113             break;
    114         }
    115 
    116         mCSD.push(csd);
    117     }
    118 
    119     return msg;
    120 }
    121 
    122 void NuPlayer::Decoder::onFillThisBuffer(const sp<AMessage> &msg) {
    123     sp<AMessage> reply;
    124     CHECK(msg->findMessage("reply", &reply));
    125 
    126 #if 0
    127     sp<ABuffer> outBuffer;
    128     CHECK(msg->findBuffer("buffer", &outBuffer));
    129 #else
    130     sp<ABuffer> outBuffer;
    131 #endif
    132 
    133     if (mCSDIndex < mCSD.size()) {
    134         outBuffer = mCSD.editItemAt(mCSDIndex++);
    135         outBuffer->meta()->setInt64("timeUs", 0);
    136 
    137         reply->setBuffer("buffer", outBuffer);
    138         reply->post();
    139         return;
    140     }
    141 
    142     sp<AMessage> notify = mNotify->dup();
    143     notify->setMessage("codec-request", msg);
    144     notify->post();
    145 }
    146 
    147 void NuPlayer::Decoder::signalFlush() {
    148     if (mCodec != NULL) {
    149         mCodec->signalFlush();
    150     }
    151 }
    152 
    153 void NuPlayer::Decoder::signalResume() {
    154     if (mCodec != NULL) {
    155         mCodec->signalResume();
    156     }
    157 }
    158 
    159 void NuPlayer::Decoder::initiateShutdown() {
    160     if (mCodec != NULL) {
    161         mCodec->initiateShutdown();
    162     }
    163 }
    164 
    165 }  // namespace android
    166 
    167