Home | History | Annotate | Download | only in nuplayer
      1 /*
      2  * Copyright (C) 2014 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 "NuPlayerDecoderPassThrough"
     19 #include <utils/Log.h>
     20 #include <inttypes.h>
     21 
     22 #include "NuPlayerDecoderPassThrough.h"
     23 
     24 #include <media/ICrypto.h>
     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/MediaDefs.h>
     29 #include <media/stagefright/MediaErrors.h>
     30 
     31 namespace android {
     32 
     33 static const size_t kMaxCachedBytes = 200000;
     34 // The buffers will contain a bit less than kAggregateBufferSizeBytes.
     35 // So we can start off with just enough buffers to keep the cache full.
     36 static const size_t kMaxPendingBuffers = 1 + (kMaxCachedBytes / NuPlayer::kAggregateBufferSizeBytes);
     37 
     38 NuPlayer::DecoderPassThrough::DecoderPassThrough(
     39         const sp<AMessage> &notify)
     40     : Decoder(notify),
     41       mNotify(notify),
     42       mBufferGeneration(0),
     43       mReachedEOS(true),
     44       mPendingBuffersToFill(0),
     45       mPendingBuffersToDrain(0),
     46       mCachedBytes(0),
     47       mComponentName("pass through decoder") {
     48     mDecoderLooper = new ALooper;
     49     mDecoderLooper->setName("NuPlayerDecoderPassThrough");
     50     mDecoderLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
     51 }
     52 
     53 NuPlayer::DecoderPassThrough::~DecoderPassThrough() {
     54 }
     55 
     56 void NuPlayer::DecoderPassThrough::configure(const sp<AMessage> &format) {
     57     sp<AMessage> msg = new AMessage(kWhatConfigure, id());
     58     msg->setMessage("format", format);
     59     msg->post();
     60 }
     61 
     62 void NuPlayer::DecoderPassThrough::init() {
     63     mDecoderLooper->registerHandler(this);
     64 }
     65 
     66 void NuPlayer::DecoderPassThrough::signalFlush() {
     67     (new AMessage(kWhatFlush, id()))->post();
     68 }
     69 
     70 void NuPlayer::DecoderPassThrough::signalResume() {
     71     (new AMessage(kWhatResume, id()))->post();
     72 }
     73 
     74 void NuPlayer::DecoderPassThrough::initiateShutdown() {
     75     (new AMessage(kWhatShutdown, id()))->post();
     76 }
     77 
     78 bool NuPlayer::DecoderPassThrough::supportsSeamlessFormatChange(
     79         const sp<AMessage> & /* targetFormat */) const {
     80     return true;
     81 }
     82 
     83 void NuPlayer::DecoderPassThrough::onConfigure(const sp<AMessage> &format) {
     84     ALOGV("[%s] onConfigure", mComponentName.c_str());
     85     mCachedBytes = 0;
     86     mPendingBuffersToFill = 0;
     87     mPendingBuffersToDrain = 0;
     88     mReachedEOS = false;
     89     ++mBufferGeneration;
     90 
     91     requestMaxBuffers();
     92 
     93     sp<AMessage> notify = mNotify->dup();
     94     notify->setInt32("what", kWhatOutputFormatChanged);
     95     notify->setMessage("format", format);
     96     notify->post();
     97 }
     98 
     99 bool NuPlayer::DecoderPassThrough::isStaleReply(const sp<AMessage> &msg) {
    100     int32_t generation;
    101     CHECK(msg->findInt32("generation", &generation));
    102     return generation != mBufferGeneration;
    103 }
    104 
    105 bool NuPlayer::DecoderPassThrough::requestABuffer() {
    106     if (mCachedBytes >= kMaxCachedBytes) {
    107         ALOGV("[%s] mCachedBytes = %zu",
    108                 mComponentName.c_str(), mCachedBytes);
    109         return false;
    110     }
    111     if (mReachedEOS) {
    112         ALOGV("[%s] reached EOS", mComponentName.c_str());
    113         return false;
    114     }
    115 
    116     sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, id());
    117     reply->setInt32("generation", mBufferGeneration);
    118 
    119     sp<AMessage> notify = mNotify->dup();
    120     notify->setInt32("what", kWhatFillThisBuffer);
    121     notify->setMessage("reply", reply);
    122     notify->post();
    123     mPendingBuffersToFill++;
    124     ALOGV("requestABuffer: #ToFill = %zu, #ToDrain = %zu", mPendingBuffersToFill,
    125             mPendingBuffersToDrain);
    126 
    127     return true;
    128 }
    129 
    130 void android::NuPlayer::DecoderPassThrough::onInputBufferFilled(
    131         const sp<AMessage> &msg) {
    132     --mPendingBuffersToFill;
    133     if (mReachedEOS) {
    134         return;
    135     }
    136 
    137     sp<ABuffer> buffer;
    138     msg->findBuffer("buffer", &buffer);
    139     if (buffer == NULL) {
    140         mReachedEOS = true;
    141 
    142         sp<AMessage> notify = mNotify->dup();
    143         notify->setInt32("what", kWhatEOS);
    144         notify->setInt32("err", ERROR_END_OF_STREAM);
    145         notify->post();
    146         return;
    147     }
    148 
    149     mCachedBytes += buffer->size();
    150 
    151     sp<AMessage> reply = new AMessage(kWhatBufferConsumed, id());
    152     reply->setInt32("generation", mBufferGeneration);
    153     reply->setInt32("size", buffer->size());
    154 
    155     sp<AMessage> notify = mNotify->dup();
    156     notify->setInt32("what", kWhatDrainThisBuffer);
    157     notify->setBuffer("buffer", buffer);
    158     notify->setMessage("reply", reply);
    159     notify->post();
    160     ++mPendingBuffersToDrain;
    161     ALOGV("onInputBufferFilled: #ToFill = %zu, #ToDrain = %zu, cachedBytes = %zu",
    162             mPendingBuffersToFill, mPendingBuffersToDrain, mCachedBytes);
    163 }
    164 
    165 void NuPlayer::DecoderPassThrough::onBufferConsumed(int32_t size) {
    166     --mPendingBuffersToDrain;
    167     mCachedBytes -= size;
    168     ALOGV("onBufferConsumed: #ToFill = %zu, #ToDrain = %zu, cachedBytes = %zu",
    169            mPendingBuffersToFill, mPendingBuffersToDrain, mCachedBytes);
    170     requestABuffer();
    171 }
    172 
    173 void NuPlayer::DecoderPassThrough::onFlush() {
    174     ++mBufferGeneration;
    175 
    176     sp<AMessage> notify = mNotify->dup();
    177     notify->setInt32("what", kWhatFlushCompleted);
    178     notify->post();
    179     mPendingBuffersToFill = 0;
    180     mPendingBuffersToDrain = 0;
    181     mCachedBytes = 0;
    182     mReachedEOS = false;
    183 }
    184 
    185 void NuPlayer::DecoderPassThrough::requestMaxBuffers() {
    186     for (size_t i = 0; i < kMaxPendingBuffers; i++) {
    187         if (!requestABuffer()) {
    188             break;
    189         }
    190     }
    191 }
    192 
    193 void NuPlayer::DecoderPassThrough::onShutdown() {
    194     ++mBufferGeneration;
    195 
    196     sp<AMessage> notify = mNotify->dup();
    197     notify->setInt32("what", kWhatShutdownCompleted);
    198     notify->post();
    199     mReachedEOS = true;
    200 }
    201 
    202 void NuPlayer::DecoderPassThrough::onMessageReceived(const sp<AMessage> &msg) {
    203     ALOGV("[%s] onMessage: %s", mComponentName.c_str(),
    204             msg->debugString().c_str());
    205 
    206     switch (msg->what()) {
    207         case kWhatConfigure:
    208         {
    209             sp<AMessage> format;
    210             CHECK(msg->findMessage("format", &format));
    211             onConfigure(format);
    212             break;
    213         }
    214 
    215         case kWhatRequestABuffer:
    216         {
    217             if (!isStaleReply(msg)) {
    218                 requestABuffer();
    219             }
    220 
    221             break;
    222         }
    223 
    224         case kWhatInputBufferFilled:
    225         {
    226             if (!isStaleReply(msg)) {
    227                 onInputBufferFilled(msg);
    228             }
    229             break;
    230         }
    231 
    232         case kWhatBufferConsumed:
    233         {
    234             if (!isStaleReply(msg)) {
    235                 int32_t size;
    236                 CHECK(msg->findInt32("size", &size));
    237                 onBufferConsumed(size);
    238             }
    239             break;
    240         }
    241 
    242         case kWhatFlush:
    243         {
    244             onFlush();
    245             break;
    246         }
    247 
    248         case kWhatResume:
    249         {
    250             requestMaxBuffers();
    251             break;
    252         }
    253 
    254         case kWhatShutdown:
    255         {
    256             onShutdown();
    257             break;
    258         }
    259 
    260         default:
    261             TRESPASS();
    262             break;
    263     }
    264 }
    265 
    266 }  // namespace android
    267