NuPlayerDecoderPassThrough.cpp revision c6cfd70f24a11b946859485ce398a189c301a4e2
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 "NuPlayerRenderer.h" 25#include "NuPlayerSource.h" 26 27#include <media/ICrypto.h> 28#include <media/stagefright/foundation/ABuffer.h> 29#include <media/stagefright/foundation/ADebug.h> 30#include <media/stagefright/foundation/AMessage.h> 31#include <media/stagefright/MediaDefs.h> 32#include <media/stagefright/MediaErrors.h> 33 34namespace android { 35 36static const size_t kMaxCachedBytes = 200000; 37// The buffers will contain a bit less than kAggregateBufferSizeBytes. 38// So we can start off with just enough buffers to keep the cache full. 39static const size_t kMaxPendingBuffers = 1 + (kMaxCachedBytes / NuPlayer::kAggregateBufferSizeBytes); 40 41NuPlayer::DecoderPassThrough::DecoderPassThrough( 42 const sp<AMessage> ¬ify, 43 const sp<Source> &source, 44 const sp<Renderer> &renderer) 45 : Decoder(notify, source), 46 mNotify(notify), 47 mSource(source), 48 mRenderer(renderer), 49 mSkipRenderingUntilMediaTimeUs(-1ll), 50 mBufferGeneration(0), 51 mReachedEOS(true), 52 mPendingBuffersToFill(0), 53 mPendingBuffersToDrain(0), 54 mCachedBytes(0), 55 mComponentName("pass through decoder") { 56 ALOGW_IF(renderer == NULL, "expect a non-NULL renderer"); 57 mDecoderLooper = new ALooper; 58 mDecoderLooper->setName("NuPlayerDecoderPassThrough"); 59 mDecoderLooper->start(false, false, ANDROID_PRIORITY_AUDIO); 60} 61 62NuPlayer::DecoderPassThrough::~DecoderPassThrough() { 63} 64 65void NuPlayer::DecoderPassThrough::configure(const sp<AMessage> &format) { 66 sp<AMessage> msg = new AMessage(kWhatConfigure, id()); 67 msg->setMessage("format", format); 68 msg->post(); 69} 70 71void NuPlayer::DecoderPassThrough::init() { 72 mDecoderLooper->registerHandler(this); 73} 74 75void NuPlayer::DecoderPassThrough::signalFlush() { 76 (new AMessage(kWhatFlush, id()))->post(); 77} 78 79void NuPlayer::DecoderPassThrough::signalResume() { 80 (new AMessage(kWhatResume, id()))->post(); 81} 82 83void NuPlayer::DecoderPassThrough::initiateShutdown() { 84 (new AMessage(kWhatShutdown, id()))->post(); 85} 86 87bool NuPlayer::DecoderPassThrough::supportsSeamlessFormatChange( 88 const sp<AMessage> & /* targetFormat */) const { 89 return true; 90} 91 92void NuPlayer::DecoderPassThrough::onConfigure(const sp<AMessage> &format) { 93 ALOGV("[%s] onConfigure", mComponentName.c_str()); 94 mCachedBytes = 0; 95 mPendingBuffersToFill = 0; 96 mPendingBuffersToDrain = 0; 97 mReachedEOS = false; 98 ++mBufferGeneration; 99 100 requestMaxBuffers(); 101 102 uint32_t flags; 103 int64_t durationUs; 104 if (mSource->getDuration(&durationUs) == OK && 105 durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) { 106 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER; 107 } else { 108 flags = AUDIO_OUTPUT_FLAG_NONE; 109 } 110 111 mRenderer->openAudioSink( 112 format, true /* offloadOnly */, false /* hasVideo */, flags); 113} 114 115bool NuPlayer::DecoderPassThrough::isStaleReply(const sp<AMessage> &msg) { 116 int32_t generation; 117 CHECK(msg->findInt32("generation", &generation)); 118 return generation != mBufferGeneration; 119} 120 121bool NuPlayer::DecoderPassThrough::requestABuffer() { 122 if (mCachedBytes >= kMaxCachedBytes) { 123 ALOGV("[%s] mCachedBytes = %zu", 124 mComponentName.c_str(), mCachedBytes); 125 return false; 126 } 127 if (mReachedEOS) { 128 ALOGV("[%s] reached EOS", mComponentName.c_str()); 129 return false; 130 } 131 132 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, id()); 133 reply->setInt32("generation", mBufferGeneration); 134 135 sp<AMessage> notify = mNotify->dup(); 136 notify->setInt32("what", kWhatFillThisBuffer); 137 notify->setMessage("reply", reply); 138 notify->post(); 139 mPendingBuffersToFill++; 140 ALOGV("requestABuffer: #ToFill = %zu, #ToDrain = %zu", mPendingBuffersToFill, 141 mPendingBuffersToDrain); 142 143 return true; 144} 145 146void android::NuPlayer::DecoderPassThrough::onInputBufferFilled( 147 const sp<AMessage> &msg) { 148 --mPendingBuffersToFill; 149 if (mReachedEOS) { 150 return; 151 } 152 153 sp<ABuffer> buffer; 154 msg->findBuffer("buffer", &buffer); 155 if (buffer == NULL) { 156 mReachedEOS = true; 157 if (mRenderer != NULL) { 158 mRenderer->queueEOS(true /* audio */, ERROR_END_OF_STREAM); 159 } 160 return; 161 } 162 163 sp<AMessage> extra; 164 if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) { 165 int64_t resumeAtMediaTimeUs; 166 if (extra->findInt64( 167 "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) { 168 ALOGI("[%s] suppressing rendering until %lld us", 169 mComponentName.c_str(), (long long)resumeAtMediaTimeUs); 170 mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs; 171 } 172 } 173 174 int32_t bufferSize = buffer->size(); 175 mCachedBytes += bufferSize; 176 177 if (mSkipRenderingUntilMediaTimeUs >= 0) { 178 int64_t timeUs = 0; 179 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 180 181 if (timeUs < mSkipRenderingUntilMediaTimeUs) { 182 ALOGV("[%s] dropping buffer at time %lld as requested.", 183 mComponentName.c_str(), (long long)timeUs); 184 185 onBufferConsumed(bufferSize); 186 return; 187 } 188 189 mSkipRenderingUntilMediaTimeUs = -1; 190 } 191 192 if (mRenderer == NULL) { 193 onBufferConsumed(bufferSize); 194 return; 195 } 196 197 sp<AMessage> reply = new AMessage(kWhatBufferConsumed, id()); 198 reply->setInt32("generation", mBufferGeneration); 199 reply->setInt32("size", bufferSize); 200 201 mRenderer->queueBuffer(true /* audio */, buffer, reply); 202 203 ++mPendingBuffersToDrain; 204 ALOGV("onInputBufferFilled: #ToFill = %zu, #ToDrain = %zu, cachedBytes = %zu", 205 mPendingBuffersToFill, mPendingBuffersToDrain, mCachedBytes); 206} 207 208void NuPlayer::DecoderPassThrough::onBufferConsumed(int32_t size) { 209 --mPendingBuffersToDrain; 210 mCachedBytes -= size; 211 ALOGV("onBufferConsumed: #ToFill = %zu, #ToDrain = %zu, cachedBytes = %zu", 212 mPendingBuffersToFill, mPendingBuffersToDrain, mCachedBytes); 213 requestABuffer(); 214} 215 216void NuPlayer::DecoderPassThrough::onFlush() { 217 ++mBufferGeneration; 218 mSkipRenderingUntilMediaTimeUs = -1; 219 220 if (mRenderer != NULL) { 221 mRenderer->flush(true /* audio */); 222 } 223 224 sp<AMessage> notify = mNotify->dup(); 225 notify->setInt32("what", kWhatFlushCompleted); 226 notify->post(); 227 mPendingBuffersToFill = 0; 228 mPendingBuffersToDrain = 0; 229 mCachedBytes = 0; 230 mReachedEOS = false; 231} 232 233void NuPlayer::DecoderPassThrough::requestMaxBuffers() { 234 for (size_t i = 0; i < kMaxPendingBuffers; i++) { 235 if (!requestABuffer()) { 236 break; 237 } 238 } 239} 240 241void NuPlayer::DecoderPassThrough::onShutdown() { 242 ++mBufferGeneration; 243 mSkipRenderingUntilMediaTimeUs = -1; 244 245 sp<AMessage> notify = mNotify->dup(); 246 notify->setInt32("what", kWhatShutdownCompleted); 247 notify->post(); 248 mReachedEOS = true; 249} 250 251void NuPlayer::DecoderPassThrough::onMessageReceived(const sp<AMessage> &msg) { 252 ALOGV("[%s] onMessage: %s", mComponentName.c_str(), 253 msg->debugString().c_str()); 254 255 switch (msg->what()) { 256 case kWhatConfigure: 257 { 258 sp<AMessage> format; 259 CHECK(msg->findMessage("format", &format)); 260 onConfigure(format); 261 break; 262 } 263 264 case kWhatRequestABuffer: 265 { 266 if (!isStaleReply(msg)) { 267 requestABuffer(); 268 } 269 270 break; 271 } 272 273 case kWhatInputBufferFilled: 274 { 275 if (!isStaleReply(msg)) { 276 onInputBufferFilled(msg); 277 } 278 break; 279 } 280 281 case kWhatBufferConsumed: 282 { 283 if (!isStaleReply(msg)) { 284 int32_t size; 285 CHECK(msg->findInt32("size", &size)); 286 onBufferConsumed(size); 287 } 288 break; 289 } 290 291 case kWhatFlush: 292 { 293 onFlush(); 294 break; 295 } 296 297 case kWhatResume: 298 { 299 requestMaxBuffers(); 300 break; 301 } 302 303 case kWhatShutdown: 304 { 305 onShutdown(); 306 break; 307 } 308 309 default: 310 TRESPASS(); 311 break; 312 } 313} 314 315} // namespace android 316