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> ¬ify) 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