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 USE_LOG SLAndroidLogLevel_Verbose 18 19#include "android_SfPlayer.h" 20 21#include <stdio.h> 22#include "SLES/OpenSLES.h" 23#include "SLES/OpenSLES_Android.h" 24#include "sllog.h" 25#include <stdlib.h> 26 27#ifdef _DEBUG_AUDIO_TESTS 28// defines used for automated audio quality tests 29#define MONITOR_AUDIO_TARGET "/sdcard/playbackqual.raw" 30#define MONITOR_AUDIO_PLAY_PROP "system.media.sles-decode-dump" 31#include <cutils/properties.h> // for property_get 32#endif 33namespace android { 34 35SfPlayer::SfPlayer(AudioPlayback_Parameters *app) 36 : mAudioTrack(NULL), 37 mFlags(0), 38 mBitrate(-1), 39 mNumChannels(1), 40 mSampleRateHz(0), 41 mTimeDelta(-1), 42 mDurationUsec(-1), 43 mCacheStatus(kStatusEmpty), 44 mSeekTimeMsec(0), 45 mLastDecodedPositionUs(-1), 46 mCacheFill(0), 47 mLastNotifiedCacheFill(0), 48 mCacheFillNotifThreshold(100), 49 mDataLocatorType(kDataLocatorNone), 50 mNotifyClient(NULL), 51 mNotifyUser(NULL), 52 mDecodeBuffer(NULL) { 53 54 mRenderLooper = new android::ALooper(); 55 56 mPlaybackParams.sessionId = app->sessionId; 57 mPlaybackParams.streamType = app->streamType; 58 mPlaybackParams.trackcb = app->trackcb; 59 mPlaybackParams.trackcbUser = app->trackcbUser; 60#ifdef _DEBUG_AUDIO_TESTS 61 mMonitorAudioFp = NULL; // automated tests 62#endif 63} 64 65 66SfPlayer::~SfPlayer() { 67 SL_LOGV("SfPlayer::~SfPlayer()"); 68 69 mRenderLooper->stop(); 70 mRenderLooper->unregisterHandler(this->id()); 71 mRenderLooper.clear(); 72 73 if (mAudioTrack != NULL) { 74 mAudioTrack->stop(); 75 delete mAudioTrack; 76 mAudioTrack = NULL; 77 } 78 79 if (mAudioSource != NULL) { 80 { 81 // don't even think about stopping the media source without releasing the decode buffer 82 Mutex::Autolock _l(mDecodeBufferLock); 83 if (NULL != mDecodeBuffer) { 84 mDecodeBuffer->release(); 85 mDecodeBuffer = NULL; 86 } 87 } 88 mAudioSource->stop(); 89 } 90 91 resetDataLocator(); 92} 93 94void SfPlayer::armLooper() { 95 mRenderLooper->registerHandler(this); 96 mRenderLooper->start(false /*runOnCallingThread*/, false /*canCallJava*/, 97 ANDROID_PRIORITY_AUDIO); 98} 99 100 101void SfPlayer::setNotifListener(const notif_client_t cbf, void* notifUser) { 102 mNotifyClient = cbf; 103 mNotifyUser = notifUser; 104} 105 106 107void SfPlayer::notifyPrepared(status_t prepareRes) { 108 sp<AMessage> msg = new AMessage(kWhatNotif, id()); 109 msg->setInt32(EVENT_PREPARED, (int32_t)prepareRes); 110 notify(msg, true /*async*/); 111} 112 113 114void SfPlayer::notifyStatus() { 115 sp<AMessage> msg = new AMessage(kWhatNotif, id()); 116 msg->setInt32(EVENT_PREFETCHSTATUSCHANGE, (int32_t)mCacheStatus); 117 notify(msg, true /*async*/); 118} 119 120 121void SfPlayer::notifyCacheFill() { 122 sp<AMessage> msg = new AMessage(kWhatNotif, id()); 123 mLastNotifiedCacheFill = mCacheFill; 124 msg->setInt32(EVENT_PREFETCHFILLLEVELUPDATE, (int32_t)mLastNotifiedCacheFill); 125 notify(msg, true /*async*/); 126} 127 128 129void SfPlayer::notify(const sp<AMessage> &msg, bool async) { 130 if (async) { 131 msg->post(); 132 } else { 133 onNotify(msg); 134 } 135} 136 137 138void SfPlayer::setDataSource(const char *uri) { 139 resetDataLocator(); 140 141 size_t len = strlen((const char *) uri); 142 char* newUri = (char*) malloc(len + 1); 143 if (NULL == newUri) { 144 // mem issue 145 SL_LOGE("SfPlayer::setDataSource: not enough memory to allocator URI string"); 146 return; 147 } 148 memcpy(newUri, uri, len + 1); 149 mDataLocator.uri = newUri; 150 151 mDataLocatorType = kDataLocatorUri; 152} 153 154void SfPlayer::setDataSource(const int fd, const int64_t offset, const int64_t length) { 155 resetDataLocator(); 156 157 mDataLocator.fdi.fd = fd; 158 159 struct stat sb; 160 int ret = fstat(fd, &sb); 161 if (ret != 0) { 162 // sockets are not supported 163 SL_LOGE("SfPlayer::setDataSource: fstat(%d) failed: %d, %s", fd, ret, strerror(errno)); 164 return; 165 } 166 167 if (offset >= sb.st_size) { 168 SL_LOGE("SfPlayer::setDataSource: invalid offset"); 169 return; 170 } 171 mDataLocator.fdi.offset = offset; 172 173 if (SFPLAYER_FD_FIND_FILE_SIZE == length) { 174 mDataLocator.fdi.length = sb.st_size; 175 } else if (offset + length > sb.st_size) { 176 mDataLocator.fdi.length = sb.st_size - offset; 177 } else { 178 mDataLocator.fdi.length = length; 179 } 180 181 mDataLocatorType = kDataLocatorFd; 182} 183 184void SfPlayer::prepare() { 185 //SL_LOGV("SfPlayer::prepare()"); 186 sp<AMessage> msg = new AMessage(kWhatPrepare, id()); 187 msg->post(); 188} 189 190 191void SfPlayer::onPrepare(const sp<AMessage> &msg) { 192 SL_LOGV("SfPlayer::onPrepare"); 193 sp<DataSource> dataSource; 194 195 switch (mDataLocatorType) { 196 197 case kDataLocatorNone: 198 SL_LOGE("SfPlayer::onPrepare: no data locator set"); 199 notifyPrepared(MEDIA_ERROR_BASE); 200 break; 201 202 case kDataLocatorUri: 203 if (!strncasecmp(mDataLocator.uri, "http://", 7)) { 204 sp<NuHTTPDataSource> http = new NuHTTPDataSource; 205 if (http->connect(mDataLocator.uri) == OK) { 206 dataSource = 207 new NuCachedSource2( 208 new ThrottledSource( 209 http, 50 * 1024 /* bytes/sec */)); 210 } 211 } else { 212 dataSource = DataSource::CreateFromURI(mDataLocator.uri); 213 } 214 break; 215 216 case kDataLocatorFd: { 217 dataSource = new FileSource( 218 mDataLocator.fdi.fd, mDataLocator.fdi.offset, mDataLocator.fdi.length); 219 status_t err = dataSource->initCheck(); 220 if (err != OK) { 221 notifyPrepared(err); 222 return; 223 } 224 } 225 break; 226 227 default: 228 TRESPASS(); 229 } 230 231 if (dataSource == NULL) { 232 SL_LOGE("SfPlayer::onPrepare: Could not create data source."); 233 notifyPrepared(ERROR_UNSUPPORTED); 234 return; 235 } 236 237 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 238 if (extractor == NULL) { 239 SL_LOGE("SfPlayer::onPrepare: Could not instantiate extractor."); 240 notifyPrepared(ERROR_UNSUPPORTED); 241 return; 242 } 243 244 ssize_t audioTrackIndex = -1; 245 bool isRawAudio = false; 246 for (size_t i = 0; i < extractor->countTracks(); ++i) { 247 sp<MetaData> meta = extractor->getTrackMetaData(i); 248 249 const char *mime; 250 CHECK(meta->findCString(kKeyMIMEType, &mime)); 251 252 if (!strncasecmp("audio/", mime, 6)) { 253 audioTrackIndex = i; 254 255 if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_RAW, mime)) { 256 isRawAudio = true; 257 } 258 break; 259 } 260 } 261 262 if (audioTrackIndex < 0) { 263 SL_LOGE("SfPlayer::onPrepare: Could not find a supported audio track."); 264 notifyPrepared(ERROR_UNSUPPORTED); 265 return; 266 } 267 268 sp<MediaSource> source = extractor->getTrack(audioTrackIndex); 269 sp<MetaData> meta = source->getFormat(); 270 271 off_t size; 272 int64_t durationUs; 273 if (dataSource->getSize(&size) == OK 274 && meta->findInt64(kKeyDuration, &durationUs)) { 275 mBitrate = size * 8000000ll / durationUs; // in bits/sec 276 mDurationUsec = durationUs; 277 } else { 278 mBitrate = -1; 279 mDurationUsec = -1; 280 } 281 282 if (!isRawAudio) { 283 OMXClient client; 284 CHECK_EQ(client.connect(), (status_t)OK); 285 286 source = OMXCodec::Create( 287 client.interface(), meta, false /* createEncoder */, 288 source); 289 290 if (source == NULL) { 291 SL_LOGE("SfPlayer::onPrepare: Could not instantiate decoder."); 292 notifyPrepared(ERROR_UNSUPPORTED); 293 return; 294 } 295 296 meta = source->getFormat(); 297 } 298 299 if (source->start() != OK) { 300 SL_LOGE("SfPlayer::onPrepare: Failed to start source/decoder."); 301 notifyPrepared(MEDIA_ERROR_BASE); 302 return; 303 } 304 305 mDataSource = dataSource; 306 mAudioSource = source; 307 308 CHECK(meta->findInt32(kKeyChannelCount, &mNumChannels)); 309 CHECK(meta->findInt32(kKeySampleRate, &mSampleRateHz)); 310 311 if (!wantPrefetch()) { 312 SL_LOGV("SfPlayer::onPrepare: no need to prefetch"); 313 // doesn't need prefetching, notify good to go 314 mCacheStatus = kStatusHigh; 315 mCacheFill = 1000; 316 notifyStatus(); 317 notifyCacheFill(); 318 } 319 320 // at this point we have enough information about the source to create its associated AudioTrack 321 assert(NULL == mAudioTrack); 322 mAudioTrack = new android::AudioTrack( 323 mPlaybackParams.streamType, // streamType 324 mSampleRateHz, // sampleRate 325 android::AudioSystem::PCM_16_BIT, // format 326 mNumChannels == 1 ? //channel mask 327 android::AudioSystem::CHANNEL_OUT_MONO : 328 android::AudioSystem::CHANNEL_OUT_STEREO, 329 0, // frameCount (here min) 330 0, // flags 331 mPlaybackParams.trackcb, // callback 332 mPlaybackParams.trackcbUser, // user 333 0, // notificationFrame 334 mPlaybackParams.sessionId 335 ); 336 337 //SL_LOGV("SfPlayer::onPrepare: end"); 338 notifyPrepared(SFPLAYER_SUCCESS); 339 340} 341 342 343bool SfPlayer::wantPrefetch() { 344 return (mDataSource->flags() & DataSource::kWantsPrefetching); 345} 346 347 348void SfPlayer::startPrefetch_async() { 349 SL_LOGV("SfPlayer::startPrefetch_async()"); 350 if (wantPrefetch()) { 351 //SL_LOGV("SfPlayer::startPrefetch_async(): sending check cache msg"); 352 353 mFlags |= kFlagPreparing; 354 mFlags |= kFlagBuffering; 355 356 (new AMessage(kWhatCheckCache, id()))->post(); 357 } 358} 359 360 361void SfPlayer::play() { 362 SL_LOGV("SfPlayer::play"); 363 364 (new AMessage(kWhatPlay, id()))->post(); 365 (new AMessage(kWhatDecode, id()))->post(); 366} 367 368 369void SfPlayer::stop() { 370 SL_LOGV("SfPlayer::stop"); 371 372 if (NULL != mAudioTrack) { 373 mAudioTrack->stop(); 374 } 375 376 (new AMessage(kWhatPause, id()))->post(); 377 378 // after a stop, playback should resume from the start. 379 seek(0); 380} 381 382void SfPlayer::pause() { 383 SL_LOGV("SfPlayer::pause"); 384 if (NULL == mAudioTrack) { 385 return; 386 } 387 (new AMessage(kWhatPause, id()))->post(); 388 mAudioTrack->pause(); 389} 390 391void SfPlayer::seek(int64_t timeMsec) { 392 SL_LOGV("SfPlayer::seek %lld", timeMsec); 393 sp<AMessage> msg = new AMessage(kWhatSeek, id()); 394 msg->setInt64("seek", timeMsec); 395 msg->post(); 396} 397 398 399void SfPlayer::loop(bool loop) { 400 sp<AMessage> msg = new AMessage(kWhatLoop, id()); 401 msg->setInt32("loop", (int32_t)loop); 402 msg->post(); 403} 404 405 406uint32_t SfPlayer::getPositionMsec() { 407 Mutex::Autolock _l(mSeekLock); 408 if (mFlags & kFlagSeeking) { 409 return (uint32_t) mSeekTimeMsec; 410 } else { 411 if (mLastDecodedPositionUs < 0) { 412 return 0; 413 } else { 414 return (uint32_t) (mLastDecodedPositionUs / 1000); 415 } 416 } 417} 418 419 420int64_t SfPlayer::getPositionUsec() { 421 Mutex::Autolock _l(mSeekLock); 422 if (mFlags & kFlagSeeking) { 423 return mSeekTimeMsec * 1000; 424 } else { 425 if (mLastDecodedPositionUs < 0) { 426 return 0; 427 } else { 428 return mLastDecodedPositionUs; 429 } 430 } 431} 432 433/** 434 * called from message loop 435 */ 436void SfPlayer::reachedEndOfStream() { 437 SL_LOGV("SfPlayer::reachedEndOfStream"); 438 if (mFlags & kFlagPlaying) { 439 // async notification of end of stream reached during playback 440 sp<AMessage> msg = new AMessage(kWhatNotif, id()); 441 msg->setInt32(EVENT_ENDOFSTREAM, 1); 442 notify(msg, true /*async*/); 443 } 444 if (mFlags & kFlagLooping) { 445 seek(0); 446 // kick-off decoding again 447 (new AMessage(kWhatDecode, id()))->post(); 448 } 449} 450 451/** 452 * called from message loop 453 */ 454void SfPlayer::updatePlaybackParamsFromSource() { 455 if (mAudioSource != 0) { 456 sp<MetaData> meta = mAudioSource->getFormat(); 457 458 SL_LOGV("old sample rate = %d", mSampleRateHz); 459 CHECK(meta->findInt32(kKeyChannelCount, &mNumChannels)); 460 CHECK(meta->findInt32(kKeySampleRate, &mSampleRateHz)); 461 SL_LOGV("new sample rate = %d", mSampleRateHz); 462 463 // the AudioTrack currently used by the AudioPlayer will be deleted by AudioPlayer itself 464 // SfPlayer never deletes the AudioTrack it creates and uses. 465 if (NULL != mAudioTrack) { 466 mAudioTrack->stop(); 467 delete mAudioTrack; 468 mAudioTrack = NULL; 469 } 470 mAudioTrack = new android::AudioTrack( 471 mPlaybackParams.streamType, // streamType 472 mSampleRateHz, // sampleRate 473 android::AudioSystem::PCM_16_BIT, // format 474 mNumChannels == 1 ? //channel mask 475 android::AudioSystem::CHANNEL_OUT_MONO : 476 android::AudioSystem::CHANNEL_OUT_STEREO, 477 0, // frameCount (here min) 478 0, // flags 479 mPlaybackParams.trackcb, // callback 480 mPlaybackParams.trackcbUser, // user 481 0, // notificationFrame 482 mPlaybackParams.sessionId 483 ); 484 if (mFlags & kFlagPlaying) { 485 mAudioTrack->start(); 486 } 487 488 // notify the AudioPlayer synchronously there's a new AudioTrack to use and configure 489 sp<AMessage> msg = new AMessage(kWhatNotif, id()); 490 msg->setInt32(EVENT_NEW_AUDIOTRACK, 0/*data field unused*/); 491 notify(msg, false /*async*/); 492 } 493} 494 495 496/** 497 * Message handlers 498 */ 499 500void SfPlayer::onPlay() { 501 SL_LOGV("SfPlayer::onPlay"); 502#ifdef _DEBUG_AUDIO_TESTS 503 // Automated tests: Open file for Intercepting pcm audio for quality validation 504 char value[PROPERTY_VALUE_MAX]; 505 if (property_get(MONITOR_AUDIO_PLAY_PROP, value, NULL) && 506 (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 507 mMonitorAudioFp = fopen(MONITOR_AUDIO_TARGET, "w"); 508 if (mMonitorAudioFp == NULL) { LOGE("error opening %s", MONITOR_AUDIO_TARGET); } 509 else { LOGE("recording to %s", MONITOR_AUDIO_TARGET); } 510 } 511#endif 512 mFlags |= kFlagPlaying; 513 514 if (NULL != mAudioTrack) { 515 mAudioTrack->start(); 516 } 517} 518 519 520void SfPlayer::onPause() { 521 SL_LOGV("SfPlayer::onPause"); 522 mFlags &= ~kFlagPlaying; 523#ifdef _DEBUG_AUDIO_TESTS 524 // Automated tests: close intercept file 525 if (mMonitorAudioFp != NULL) { 526 fclose(mMonitorAudioFp); 527 } 528 mMonitorAudioFp = NULL; 529#endif 530} 531 532 533void SfPlayer::onSeek(const sp<AMessage> &msg) { 534 SL_LOGV("SfPlayer::onSeek"); 535 int64_t timeMsec; 536 CHECK(msg->findInt64("seek", &timeMsec)); 537 538 Mutex::Autolock _l(mSeekLock); 539 mFlags |= kFlagSeeking; 540 mSeekTimeMsec = timeMsec; 541 mTimeDelta = -1; 542 mLastDecodedPositionUs = -1; 543} 544 545 546void SfPlayer::onLoop(const sp<AMessage> &msg) { 547 //SL_LOGV("SfPlayer::onLoop"); 548 int32_t loop; 549 CHECK(msg->findInt32("loop", &loop)); 550 551 if (loop) { 552 //SL_LOGV("SfPlayer::onLoop start looping"); 553 mFlags |= kFlagLooping; 554 } else { 555 //SL_LOGV("SfPlayer::onLoop stop looping"); 556 mFlags &= ~kFlagLooping; 557 } 558} 559 560 561void SfPlayer::onDecode() { 562 //SL_LOGV("SfPlayer::onDecode"); 563 bool eos; 564 if (mDataSource == 0) { 565 // application set play state to paused which failed, then set play state to playing 566 return; 567 } 568 if ((mDataSource->flags() & DataSource::kWantsPrefetching) 569 && (getCacheRemaining(&eos) == kStatusLow) 570 && !eos) { 571 SL_LOGV("buffering more."); 572 573 if (mFlags & kFlagPlaying) { 574 mAudioTrack->pause(); 575 } 576 mFlags |= kFlagBuffering; 577 (new AMessage(kWhatCheckCache, id()))->post(100000); 578 return; 579 } 580 581 if (!(mFlags & (kFlagPlaying | kFlagBuffering | kFlagPreparing))) { 582 // don't decode if we're not buffering, prefetching or playing 583 //SL_LOGV("don't decode: not buffering, prefetching or playing"); 584 return; 585 } 586 587 status_t err; 588 MediaSource::ReadOptions readOptions; 589 if (mFlags & kFlagSeeking) { 590 readOptions.setSeekTo(mSeekTimeMsec * 1000); 591 } 592 593 { 594 Mutex::Autolock _l(mDecodeBufferLock); 595 if (NULL != mDecodeBuffer) { 596 // the current decoded buffer hasn't been rendered, drop it 597 mDecodeBuffer->release(); 598 mDecodeBuffer = NULL; 599 } 600 err = mAudioSource->read(&mDecodeBuffer, &readOptions); 601 if (err == OK) { 602 CHECK(mDecodeBuffer->meta_data()->findInt64(kKeyTime, &mLastDecodedPositionUs)); 603 } 604 } 605 606 { 607 Mutex::Autolock _l(mSeekLock); 608 if (mFlags & kFlagSeeking) { 609 mFlags &= ~kFlagSeeking; 610 } 611 } 612 613 if (err != OK) { 614 bool continueDecoding = false; 615 switch(err) { 616 case ERROR_END_OF_STREAM: 617 // handle notification and looping at end of stream 618 if (0 < mDurationUsec) { 619 mLastDecodedPositionUs = mDurationUsec; 620 } 621 reachedEndOfStream(); 622 break; 623 case INFO_FORMAT_CHANGED: 624 SL_LOGI("MediaSource::read encountered INFO_FORMAT_CHANGED"); 625 // reconfigure output 626 updatePlaybackParamsFromSource(); 627 continueDecoding = true; 628 break; 629 case INFO_DISCONTINUITY: 630 SL_LOGI("MediaSource::read encountered INFO_DISCONTINUITY"); 631 continueDecoding = true; 632 break; 633 default: 634 SL_LOGE("MediaSource::read returned error %d", err); 635 break; 636 } 637 if (continueDecoding) { 638 if (NULL == mDecodeBuffer) { 639 (new AMessage(kWhatDecode, id()))->post(); 640 return; 641 } 642 } else { 643 return; 644 } 645 } 646 647 // render 648 649 sp<AMessage> msg = new AMessage(kWhatRender, id()); 650 651 if (mTimeDelta < 0) { 652 mTimeDelta = ALooper::GetNowUs() - mLastDecodedPositionUs; 653 } 654 655 int64_t delayUs = mLastDecodedPositionUs + mTimeDelta - ALooper::GetNowUs() 656 - RENDER_SAFETY_DELAY_US; // negative delays are ignored 657 658 659 if ((NULL != mAudioTrack) && (mAudioTrack->getSampleRate() > mSampleRateHz)) { 660 // we're speeding up playback, feed data faster 661 // FIXME not the right formula, delays need to be evaluated differently 662 delayUs = RENDER_SAFETY_DELAY_US; 663 //SL_LOGV("delayUs=%lld new", delayUs); 664 } 665 666 // FIXME clicks can be observed if solely relying on delayUs, this is a safe compromise 667 msg->post(delayUs > RENDER_SAFETY_DELAY_US ? RENDER_SAFETY_DELAY_US : delayUs); 668 //msg->post(delayUs); // negative delays are ignored 669 //SL_LOGV("timeUs=%lld, mTimeDelta=%lld, delayUs=%lld", 670 // mLastDecodedPositionUs, mTimeDelta, delayUs); 671} 672 673 674void SfPlayer::onRender(const sp<AMessage> &msg) { 675 //SL_LOGV("SfPlayer::onRender"); 676 677 Mutex::Autolock _l(mDecodeBufferLock); 678 679 if (NULL == mDecodeBuffer) { 680 // nothing to render, move along 681 //SL_LOGV("SfPlayer::onRender NULL buffer, exiting"); 682 return; 683 } 684 685 if (mFlags & kFlagPlaying) { 686 assert(NULL != mAudioTrack); 687 mAudioTrack->write( (const uint8_t *)mDecodeBuffer->data() + mDecodeBuffer->range_offset(), 688 mDecodeBuffer->range_length()); 689 (new AMessage(kWhatDecode, id()))->post(); 690#ifdef _DEBUG_AUDIO_TESTS 691 // Automated tests: Intercept PCM data and write to file for later validations 692 if (mMonitorAudioFp != NULL) { 693 fwrite((const uint8_t *)mDecodeBuffer->data() + mDecodeBuffer->range_offset(), 694 mDecodeBuffer->range_length(), 1, mMonitorAudioFp); 695 } 696#endif 697 } 698 mDecodeBuffer->release(); 699 mDecodeBuffer = NULL; 700 701} 702 703 704void SfPlayer::onCheckCache(const sp<AMessage> &msg) { 705 //SL_LOGV("SfPlayer::onCheckCache"); 706 bool eos; 707 CacheStatus status = getCacheRemaining(&eos); 708 709 if (eos || status == kStatusHigh 710 || ((mFlags & kFlagPreparing) && (status >= kStatusEnough))) { 711 if (mFlags & kFlagPlaying) { 712 assert(NULL != mAudioTrack); 713 mAudioTrack->start(); 714 } 715 mFlags &= ~kFlagBuffering; 716 717 SL_LOGV("SfPlayer::onCheckCache: buffering done."); 718 719 if (mFlags & kFlagPreparing) { 720 //SL_LOGV("SfPlayer::onCheckCache: preparation done."); 721 mFlags &= ~kFlagPreparing; 722 } 723 724 mTimeDelta = -1; 725 if (mFlags & kFlagPlaying) { 726 (new AMessage(kWhatDecode, id()))->post(); 727 } 728 return; 729 } 730 731 msg->post(100000); 732} 733 734void SfPlayer::onNotify(const sp<AMessage> &msg) { 735 if (NULL == mNotifyClient) { 736 return; 737 } 738 int32_t val; 739 if (msg->findInt32(EVENT_PREFETCHSTATUSCHANGE, &val)) { 740 SL_LOGV("\tSfPlayer notifying %s = %d", EVENT_PREFETCHSTATUSCHANGE, val); 741 mNotifyClient(kEventPrefetchStatusChange, val, mNotifyUser); 742 } 743 if (msg->findInt32(EVENT_PREFETCHFILLLEVELUPDATE, &val)) { 744 SL_LOGV("\tSfPlayer notifying %s = %d", EVENT_PREFETCHFILLLEVELUPDATE, val); 745 mNotifyClient(kEventPrefetchFillLevelUpdate, val, mNotifyUser); 746 } 747 if (msg->findInt32(EVENT_ENDOFSTREAM, &val)) { 748 SL_LOGV("\tSfPlayer notifying %s = %d", EVENT_ENDOFSTREAM, val); 749 mNotifyClient(kEventEndOfStream, val, mNotifyUser); 750 } 751 752 if (msg->findInt32(EVENT_PREPARED, &val)) { 753 SL_LOGV("\tSfPlayer notifying %s = %d", EVENT_PREPARED, val); 754 mNotifyClient(kEventPrepared, val, mNotifyUser); 755 } 756 757 if (msg->findInt32(EVENT_NEW_AUDIOTRACK, &val)) { 758 SL_LOGV("\tSfPlayer notifying %s", EVENT_NEW_AUDIOTRACK); 759 mNotifyClient(kEventNewAudioTrack, val, mNotifyUser); 760 } 761} 762 763SfPlayer::CacheStatus SfPlayer::getCacheRemaining(bool *eos) { 764 sp<NuCachedSource2> cachedSource = 765 static_cast<NuCachedSource2 *>(mDataSource.get()); 766 767 CacheStatus oldStatus = mCacheStatus; 768 769 size_t dataRemaining = cachedSource->approxDataRemaining(eos); 770 771 CHECK_GE(mBitrate, 0); 772 773 int64_t dataRemainingUs = dataRemaining * 8000000ll / mBitrate; 774 775 //SL_LOGV("SfPlayer::getCacheRemaining: approx %.2f secs remaining (eos=%d)", 776 // dataRemainingUs / 1E6, *eos); 777 778 if (*eos) { 779 // data is buffered up to the end of the stream, it can't get any better than this 780 mCacheStatus = kStatusHigh; 781 mCacheFill = 1000; 782 783 } else { 784 if (mDurationUsec > 0) { 785 // known duration: 786 787 // fill level is ratio of how much has been played + how much is 788 // cached, divided by total duration 789 uint32_t currentPositionUsec = getPositionUsec(); 790 mCacheFill = (int16_t) ((1000.0 791 * (double)(currentPositionUsec + dataRemainingUs) / mDurationUsec)); 792 //SL_LOGV("cacheFill = %d", mCacheFill); 793 794 // cache status is evaluated against duration thresholds 795 if (dataRemainingUs > DURATION_CACHED_HIGH_US) { 796 mCacheStatus = kStatusHigh; 797 //LOGV("high"); 798 } else if (dataRemainingUs > DURATION_CACHED_MED_US) { 799 //LOGV("enough"); 800 mCacheStatus = kStatusEnough; 801 } else if (dataRemainingUs < DURATION_CACHED_LOW_US) { 802 //LOGV("low"); 803 mCacheStatus = kStatusLow; 804 } else { 805 mCacheStatus = kStatusIntermediate; 806 } 807 808 } else { 809 // unknown duration: 810 811 // cache status is evaluated against cache amount thresholds 812 // (no duration so we don't have the bitrate either, could be derived from format?) 813 if (dataRemaining > SIZE_CACHED_HIGH_BYTES) { 814 mCacheStatus = kStatusHigh; 815 } else if (dataRemaining > SIZE_CACHED_MED_BYTES) { 816 mCacheStatus = kStatusEnough; 817 } else if (dataRemaining < SIZE_CACHED_LOW_BYTES) { 818 mCacheStatus = kStatusLow; 819 } else { 820 mCacheStatus = kStatusIntermediate; 821 } 822 } 823 824 } 825 826 if (oldStatus != mCacheStatus) { 827 notifyStatus(); 828 } 829 830 if (abs(mCacheFill - mLastNotifiedCacheFill) > mCacheFillNotifThreshold) { 831 notifyCacheFill(); 832 } 833 834 return mCacheStatus; 835} 836 837 838/* 839 * post-condition: mDataLocatorType == kDataLocatorNone 840 * 841 */ 842void SfPlayer::resetDataLocator() { 843 if (kDataLocatorUri == mDataLocatorType) { 844 if (NULL != mDataLocator.uri) { 845 free(mDataLocator.uri); 846 mDataLocator.uri = NULL; 847 } 848 } 849 mDataLocatorType = kDataLocatorNone; 850} 851 852 853void SfPlayer::onMessageReceived(const sp<AMessage> &msg) { 854 switch (msg->what()) { 855 case kWhatPrepare: 856 onPrepare(msg); 857 break; 858 859 case kWhatDecode: 860 onDecode(); 861 break; 862 863 case kWhatRender: 864 onRender(msg); 865 break; 866 867 case kWhatCheckCache: 868 onCheckCache(msg); 869 break; 870 871 case kWhatNotif: 872 onNotify(msg); 873 break; 874 875 case kWhatPlay: 876 onPlay(); 877 break; 878 879 case kWhatPause: 880 onPause(); 881 break; 882 883 case kWhatSeek: 884 onSeek(msg); 885 break; 886 887 case kWhatLoop: 888 onLoop(msg); 889 break; 890 891 default: 892 TRESPASS(); 893 } 894} 895 896} // namespace android 897