1 /* 2 * Copyright (C) 2011 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_TAG "LibAAH_RTP" 18 #include <utils/Log.h> 19 20 #define __STDC_FORMAT_MACROS 21 #include <inttypes.h> 22 #include <netdb.h> 23 #include <netinet/ip.h> 24 25 #include <common_time/cc_helper.h> 26 #include <media/IMediaPlayer.h> 27 #include <media/stagefright/foundation/ADebug.h> 28 #include <media/stagefright/foundation/AMessage.h> 29 #include <media/stagefright/FileSource.h> 30 #include <media/stagefright/MediaBuffer.h> 31 #include <media/stagefright/MediaDefs.h> 32 #include <media/stagefright/MetaData.h> 33 #include <utils/Timers.h> 34 35 #include "aah_tx_packet.h" 36 #include "aah_tx_player.h" 37 38 namespace android { 39 40 static int64_t kLowWaterMarkUs = 2000000ll; // 2secs 41 static int64_t kHighWaterMarkUs = 10000000ll; // 10secs 42 static const size_t kLowWaterMarkBytes = 40000; 43 static const size_t kHighWaterMarkBytes = 200000; 44 45 // When we start up, how much lead time should we put on the first access unit? 46 static const int64_t kAAHStartupLeadTimeUs = 300000LL; 47 48 // How much time do we attempt to lead the clock by in steady state? 49 static const int64_t kAAHBufferTimeUs = 1000000LL; 50 51 // how long do we keep data in our retransmit buffer after sending it. 52 const int64_t AAH_TXPlayer::kAAHRetryKeepAroundTimeNs = 53 kAAHBufferTimeUs * 1100; 54 55 sp<MediaPlayerBase> createAAH_TXPlayer() { 56 sp<MediaPlayerBase> ret = new AAH_TXPlayer(); 57 return ret; 58 } 59 60 template <typename T> static T clamp(T val, T min, T max) { 61 if (val < min) { 62 return min; 63 } else if (val > max) { 64 return max; 65 } else { 66 return val; 67 } 68 } 69 70 struct AAH_TXEvent : public TimedEventQueue::Event { 71 AAH_TXEvent(AAH_TXPlayer *player, 72 void (AAH_TXPlayer::*method)()) : mPlayer(player) 73 , mMethod(method) {} 74 75 protected: 76 virtual ~AAH_TXEvent() {} 77 78 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) { 79 (mPlayer->*mMethod)(); 80 } 81 82 private: 83 AAH_TXPlayer *mPlayer; 84 void (AAH_TXPlayer::*mMethod)(); 85 86 AAH_TXEvent(const AAH_TXEvent &); 87 AAH_TXEvent& operator=(const AAH_TXEvent &); 88 }; 89 90 AAH_TXPlayer::AAH_TXPlayer() 91 : mQueueStarted(false) 92 , mFlags(0) 93 , mExtractorFlags(0) { 94 DataSource::RegisterDefaultSniffers(); 95 96 mBufferingEvent = new AAH_TXEvent(this, &AAH_TXPlayer::onBufferingUpdate); 97 mBufferingEventPending = false; 98 99 mPumpAudioEvent = new AAH_TXEvent(this, &AAH_TXPlayer::onPumpAudio); 100 mPumpAudioEventPending = false; 101 102 mAudioCodecData = NULL; 103 104 reset_l(); 105 } 106 107 AAH_TXPlayer::~AAH_TXPlayer() { 108 if (mQueueStarted) { 109 mQueue.stop(); 110 } 111 112 reset_l(); 113 } 114 115 void AAH_TXPlayer::cancelPlayerEvents(bool keepBufferingGoing) { 116 if (!keepBufferingGoing) { 117 mQueue.cancelEvent(mBufferingEvent->eventID()); 118 mBufferingEventPending = false; 119 120 mQueue.cancelEvent(mPumpAudioEvent->eventID()); 121 mPumpAudioEventPending = false; 122 } 123 } 124 125 status_t AAH_TXPlayer::initCheck() { 126 // Check for the presense of the common time service by attempting to query 127 // for CommonTime's frequency. If we get an error back, we cannot talk to 128 // the service at all and should abort now. 129 status_t res; 130 uint64_t freq; 131 res = mCCHelper.getCommonFreq(&freq); 132 if (OK != res) { 133 ALOGE("Failed to connect to common time service! (res %d)", res); 134 return res; 135 } 136 137 return OK; 138 } 139 140 status_t AAH_TXPlayer::setDataSource( 141 const char *url, 142 const KeyedVector<String8, String8> *headers) { 143 Mutex::Autolock autoLock(mLock); 144 return setDataSource_l(url, headers); 145 } 146 147 status_t AAH_TXPlayer::setDataSource_l( 148 const char *url, 149 const KeyedVector<String8, String8> *headers) { 150 reset_l(); 151 152 mUri.setTo(url); 153 154 if (headers) { 155 mUriHeaders = *headers; 156 157 ssize_t index = mUriHeaders.indexOfKey(String8("x-hide-urls-from-log")); 158 if (index >= 0) { 159 // Browser is in "incognito" mode, suppress logging URLs. 160 161 // This isn't something that should be passed to the server. 162 mUriHeaders.removeItemsAt(index); 163 164 mFlags |= INCOGNITO; 165 } 166 } 167 168 // The URL may optionally contain a "#" character followed by a Skyjam 169 // cookie. Ideally the cookie header should just be passed in the headers 170 // argument, but the Java API for supplying headers is apparently not yet 171 // exposed in the SDK used by application developers. 172 const char kSkyjamCookieDelimiter = '#'; 173 char* skyjamCookie = strrchr(mUri.string(), kSkyjamCookieDelimiter); 174 if (skyjamCookie) { 175 skyjamCookie++; 176 mUriHeaders.add(String8("Cookie"), String8(skyjamCookie)); 177 mUri = String8(mUri.string(), skyjamCookie - mUri.string()); 178 } 179 180 return OK; 181 } 182 183 status_t AAH_TXPlayer::setDataSource(int fd, int64_t offset, int64_t length) { 184 Mutex::Autolock autoLock(mLock); 185 186 reset_l(); 187 188 sp<DataSource> dataSource = new FileSource(dup(fd), offset, length); 189 190 status_t err = dataSource->initCheck(); 191 192 if (err != OK) { 193 return err; 194 } 195 196 mFileSource = dataSource; 197 198 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 199 200 if (extractor == NULL) { 201 return UNKNOWN_ERROR; 202 } 203 204 return setDataSource_l(extractor); 205 } 206 207 status_t AAH_TXPlayer::setVideoSurface(const sp<Surface>& surface) { 208 return OK; 209 } 210 211 status_t AAH_TXPlayer::setVideoSurfaceTexture( 212 const sp<ISurfaceTexture>& surfaceTexture) { 213 return OK; 214 } 215 216 status_t AAH_TXPlayer::prepare() { 217 return INVALID_OPERATION; 218 } 219 220 status_t AAH_TXPlayer::prepareAsync() { 221 Mutex::Autolock autoLock(mLock); 222 223 return prepareAsync_l(); 224 } 225 226 status_t AAH_TXPlayer::prepareAsync_l() { 227 if (mFlags & PREPARING) { 228 return UNKNOWN_ERROR; // async prepare already pending 229 } 230 231 mAAH_Sender = AAH_TXSender::GetInstance(); 232 if (mAAH_Sender == NULL) { 233 return NO_MEMORY; 234 } 235 236 if (!mQueueStarted) { 237 mQueue.start(); 238 mQueueStarted = true; 239 } 240 241 mFlags |= PREPARING; 242 mAsyncPrepareEvent = new AAH_TXEvent( 243 this, &AAH_TXPlayer::onPrepareAsyncEvent); 244 245 mQueue.postEvent(mAsyncPrepareEvent); 246 247 return OK; 248 } 249 250 status_t AAH_TXPlayer::finishSetDataSource_l() { 251 sp<DataSource> dataSource; 252 253 if (!strncasecmp("http://", mUri.string(), 7) || 254 !strncasecmp("https://", mUri.string(), 8)) { 255 256 mConnectingDataSource = HTTPBase::Create( 257 (mFlags & INCOGNITO) 258 ? HTTPBase::kFlagIncognito 259 : 0); 260 261 mLock.unlock(); 262 status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders); 263 mLock.lock(); 264 265 if (err != OK) { 266 mConnectingDataSource.clear(); 267 268 ALOGI("mConnectingDataSource->connect() returned %d", err); 269 return err; 270 } 271 272 mCachedSource = new NuCachedSource2(mConnectingDataSource); 273 mConnectingDataSource.clear(); 274 275 dataSource = mCachedSource; 276 277 // We're going to prefill the cache before trying to instantiate 278 // the extractor below, as the latter is an operation that otherwise 279 // could block on the datasource for a significant amount of time. 280 // During that time we'd be unable to abort the preparation phase 281 // without this prefill. 282 283 mLock.unlock(); 284 285 for (;;) { 286 status_t finalStatus; 287 size_t cachedDataRemaining = 288 mCachedSource->approxDataRemaining(&finalStatus); 289 290 if (finalStatus != OK || 291 cachedDataRemaining >= kHighWaterMarkBytes || 292 (mFlags & PREPARE_CANCELLED)) { 293 break; 294 } 295 296 usleep(200000); 297 } 298 299 mLock.lock(); 300 301 if (mFlags & PREPARE_CANCELLED) { 302 ALOGI("Prepare cancelled while waiting for initial cache fill."); 303 return UNKNOWN_ERROR; 304 } 305 } else { 306 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders); 307 } 308 309 if (dataSource == NULL) { 310 return UNKNOWN_ERROR; 311 } 312 313 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 314 315 if (extractor == NULL) { 316 return UNKNOWN_ERROR; 317 } 318 319 return setDataSource_l(extractor); 320 } 321 322 status_t AAH_TXPlayer::setDataSource_l(const sp<MediaExtractor> &extractor) { 323 // Attempt to approximate overall stream bitrate by summing all 324 // tracks' individual bitrates, if not all of them advertise bitrate, 325 // we have to fail. 326 327 int64_t totalBitRate = 0; 328 329 for (size_t i = 0; i < extractor->countTracks(); ++i) { 330 sp<MetaData> meta = extractor->getTrackMetaData(i); 331 332 int32_t bitrate; 333 if (!meta->findInt32(kKeyBitRate, &bitrate)) { 334 totalBitRate = -1; 335 break; 336 } 337 338 totalBitRate += bitrate; 339 } 340 341 mBitrate = totalBitRate; 342 343 ALOGV("mBitrate = %lld bits/sec", mBitrate); 344 345 bool haveAudio = false; 346 for (size_t i = 0; i < extractor->countTracks(); ++i) { 347 sp<MetaData> meta = extractor->getTrackMetaData(i); 348 349 const char *mime; 350 CHECK(meta->findCString(kKeyMIMEType, &mime)); 351 352 if (!strncasecmp(mime, "audio/", 6)) { 353 mAudioSource = extractor->getTrack(i); 354 CHECK(mAudioSource != NULL); 355 haveAudio = true; 356 break; 357 } 358 } 359 360 if (!haveAudio) { 361 return UNKNOWN_ERROR; 362 } 363 364 mExtractorFlags = extractor->flags(); 365 366 return OK; 367 } 368 369 void AAH_TXPlayer::abortPrepare(status_t err) { 370 CHECK(err != OK); 371 372 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 373 374 mPrepareResult = err; 375 mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED); 376 mPreparedCondition.broadcast(); 377 } 378 379 void AAH_TXPlayer::onPrepareAsyncEvent() { 380 Mutex::Autolock autoLock(mLock); 381 382 if (mFlags & PREPARE_CANCELLED) { 383 ALOGI("prepare was cancelled before doing anything"); 384 abortPrepare(UNKNOWN_ERROR); 385 return; 386 } 387 388 if (mUri.size() > 0) { 389 status_t err = finishSetDataSource_l(); 390 391 if (err != OK) { 392 abortPrepare(err); 393 return; 394 } 395 } 396 397 mAudioFormat = mAudioSource->getFormat(); 398 if (!mAudioFormat->findInt64(kKeyDuration, &mDurationUs)) 399 mDurationUs = 1; 400 401 const char* mime_type = NULL; 402 if (!mAudioFormat->findCString(kKeyMIMEType, &mime_type)) { 403 ALOGE("Failed to find audio substream MIME type during prepare."); 404 abortPrepare(BAD_VALUE); 405 return; 406 } 407 408 if (!strcmp(mime_type, MEDIA_MIMETYPE_AUDIO_MPEG)) { 409 mAudioCodec = TRTPAudioPacket::kCodecMPEG1Audio; 410 } else 411 if (!strcmp(mime_type, MEDIA_MIMETYPE_AUDIO_AAC)) { 412 mAudioCodec = TRTPAudioPacket::kCodecAACAudio; 413 414 uint32_t type; 415 int32_t sample_rate; 416 int32_t channel_count; 417 const void* esds_data; 418 size_t esds_len; 419 420 if (!mAudioFormat->findInt32(kKeySampleRate, &sample_rate)) { 421 ALOGE("Failed to find sample rate for AAC substream."); 422 abortPrepare(BAD_VALUE); 423 return; 424 } 425 426 if (!mAudioFormat->findInt32(kKeyChannelCount, &channel_count)) { 427 ALOGE("Failed to find channel count for AAC substream."); 428 abortPrepare(BAD_VALUE); 429 return; 430 } 431 432 if (!mAudioFormat->findData(kKeyESDS, &type, &esds_data, &esds_len)) { 433 ALOGE("Failed to find codec init data for AAC substream."); 434 abortPrepare(BAD_VALUE); 435 return; 436 } 437 438 CHECK(NULL == mAudioCodecData); 439 mAudioCodecDataSize = esds_len 440 + sizeof(sample_rate) 441 + sizeof(channel_count); 442 mAudioCodecData = new uint8_t[mAudioCodecDataSize]; 443 if (NULL == mAudioCodecData) { 444 ALOGE("Failed to allocate %u bytes for AAC substream codec aux" 445 " data.", mAudioCodecDataSize); 446 mAudioCodecDataSize = 0; 447 abortPrepare(BAD_VALUE); 448 return; 449 } 450 451 uint8_t* tmp = mAudioCodecData; 452 tmp[0] = static_cast<uint8_t>((sample_rate >> 24) & 0xFF); 453 tmp[1] = static_cast<uint8_t>((sample_rate >> 16) & 0xFF); 454 tmp[2] = static_cast<uint8_t>((sample_rate >> 8) & 0xFF); 455 tmp[3] = static_cast<uint8_t>((sample_rate ) & 0xFF); 456 tmp[4] = static_cast<uint8_t>((channel_count >> 24) & 0xFF); 457 tmp[5] = static_cast<uint8_t>((channel_count >> 16) & 0xFF); 458 tmp[6] = static_cast<uint8_t>((channel_count >> 8) & 0xFF); 459 tmp[7] = static_cast<uint8_t>((channel_count ) & 0xFF); 460 461 memcpy(tmp + 8, esds_data, esds_len); 462 } else { 463 ALOGE("Unsupported MIME type \"%s\" in audio substream", mime_type); 464 abortPrepare(BAD_VALUE); 465 return; 466 } 467 468 status_t err = mAudioSource->start(); 469 if (err != OK) { 470 ALOGI("failed to start audio source, err=%d", err); 471 abortPrepare(err); 472 return; 473 } 474 475 mFlags |= PREPARING_CONNECTED; 476 477 if (mCachedSource != NULL) { 478 postBufferingEvent_l(); 479 } else { 480 finishAsyncPrepare_l(); 481 } 482 } 483 484 void AAH_TXPlayer::finishAsyncPrepare_l() { 485 notifyListener_l(MEDIA_PREPARED); 486 487 mPrepareResult = OK; 488 mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED); 489 mFlags |= PREPARED; 490 mPreparedCondition.broadcast(); 491 } 492 493 status_t AAH_TXPlayer::start() { 494 Mutex::Autolock autoLock(mLock); 495 496 mFlags &= ~CACHE_UNDERRUN; 497 498 return play_l(); 499 } 500 501 status_t AAH_TXPlayer::play_l() { 502 if (mFlags & PLAYING) { 503 return OK; 504 } 505 506 if (!(mFlags & PREPARED)) { 507 return INVALID_OPERATION; 508 } 509 510 { 511 Mutex::Autolock lock(mEndpointLock); 512 if (!mEndpointValid) { 513 return INVALID_OPERATION; 514 } 515 if (!mEndpointRegistered) { 516 mProgramID = mAAH_Sender->registerEndpoint(mEndpoint); 517 mEndpointRegistered = true; 518 } 519 } 520 521 mFlags |= PLAYING; 522 523 updateClockTransform_l(false); 524 525 postPumpAudioEvent_l(-1); 526 527 return OK; 528 } 529 530 status_t AAH_TXPlayer::stop() { 531 status_t ret = pause(); 532 sendEOS_l(); 533 return ret; 534 } 535 536 status_t AAH_TXPlayer::pause() { 537 Mutex::Autolock autoLock(mLock); 538 539 mFlags &= ~CACHE_UNDERRUN; 540 541 return pause_l(); 542 } 543 544 status_t AAH_TXPlayer::pause_l(bool doClockUpdate) { 545 if (!(mFlags & PLAYING)) { 546 return OK; 547 } 548 549 cancelPlayerEvents(true /* keepBufferingGoing */); 550 551 mFlags &= ~PLAYING; 552 553 if (doClockUpdate) { 554 updateClockTransform_l(true); 555 } 556 557 return OK; 558 } 559 560 void AAH_TXPlayer::updateClockTransform_l(bool pause) { 561 // record the new pause status so that onPumpAudio knows what rate to apply 562 // when it initializes the transform 563 mPlayRateIsPaused = pause; 564 565 // if we haven't yet established a valid clock transform, then we can't 566 // do anything here 567 if (!mCurrentClockTransformValid) { 568 return; 569 } 570 571 // sample the current common time 572 int64_t commonTimeNow; 573 if (OK != mCCHelper.getCommonTime(&commonTimeNow)) { 574 ALOGE("updateClockTransform_l get common time failed"); 575 mCurrentClockTransformValid = false; 576 return; 577 } 578 579 // convert the current common time to media time using the old 580 // transform 581 int64_t mediaTimeNow; 582 if (!mCurrentClockTransform.doReverseTransform( 583 commonTimeNow, &mediaTimeNow)) { 584 ALOGE("updateClockTransform_l reverse transform failed"); 585 mCurrentClockTransformValid = false; 586 return; 587 } 588 589 // calculate a new transform that preserves the old transform's 590 // result for the current time 591 mCurrentClockTransform.a_zero = mediaTimeNow; 592 mCurrentClockTransform.b_zero = commonTimeNow; 593 mCurrentClockTransform.a_to_b_numer = 1; 594 mCurrentClockTransform.a_to_b_denom = pause ? 0 : 1; 595 596 // send a packet announcing the new transform 597 sp<TRTPControlPacket> packet = new TRTPControlPacket(); 598 packet->setClockTransform(mCurrentClockTransform); 599 packet->setCommandID(TRTPControlPacket::kCommandNop); 600 queuePacketToSender_l(packet); 601 } 602 603 void AAH_TXPlayer::sendEOS_l() { 604 sp<TRTPControlPacket> packet = new TRTPControlPacket(); 605 packet->setCommandID(TRTPControlPacket::kCommandEOS); 606 queuePacketToSender_l(packet); 607 } 608 609 bool AAH_TXPlayer::isPlaying() { 610 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN); 611 } 612 613 status_t AAH_TXPlayer::seekTo(int msec) { 614 if (mExtractorFlags & MediaExtractor::CAN_SEEK) { 615 Mutex::Autolock autoLock(mLock); 616 return seekTo_l(static_cast<int64_t>(msec) * 1000); 617 } 618 619 notifyListener_l(MEDIA_SEEK_COMPLETE); 620 return OK; 621 } 622 623 status_t AAH_TXPlayer::seekTo_l(int64_t timeUs) { 624 mIsSeeking = true; 625 mSeekTimeUs = timeUs; 626 627 mCurrentClockTransformValid = false; 628 mLastQueuedMediaTimePTSValid = false; 629 630 // send a flush command packet 631 sp<TRTPControlPacket> packet = new TRTPControlPacket(); 632 packet->setCommandID(TRTPControlPacket::kCommandFlush); 633 queuePacketToSender_l(packet); 634 635 return OK; 636 } 637 638 status_t AAH_TXPlayer::getCurrentPosition(int *msec) { 639 if (!msec) { 640 return BAD_VALUE; 641 } 642 643 Mutex::Autolock lock(mLock); 644 645 int position; 646 647 if (mIsSeeking) { 648 position = mSeekTimeUs / 1000; 649 } else if (mCurrentClockTransformValid) { 650 // sample the current common time 651 int64_t commonTimeNow; 652 if (OK != mCCHelper.getCommonTime(&commonTimeNow)) { 653 ALOGE("getCurrentPosition get common time failed"); 654 return INVALID_OPERATION; 655 } 656 657 int64_t mediaTimeNow; 658 if (!mCurrentClockTransform.doReverseTransform(commonTimeNow, 659 &mediaTimeNow)) { 660 ALOGE("getCurrentPosition reverse transform failed"); 661 return INVALID_OPERATION; 662 } 663 664 position = static_cast<int>(mediaTimeNow / 1000); 665 } else { 666 position = 0; 667 } 668 669 int duration; 670 if (getDuration_l(&duration) == OK) { 671 *msec = clamp(position, 0, duration); 672 } else { 673 *msec = (position >= 0) ? position : 0; 674 } 675 676 return OK; 677 } 678 679 status_t AAH_TXPlayer::getDuration(int* msec) { 680 if (!msec) { 681 return BAD_VALUE; 682 } 683 684 Mutex::Autolock lock(mLock); 685 686 return getDuration_l(msec); 687 } 688 689 status_t AAH_TXPlayer::getDuration_l(int* msec) { 690 if (mDurationUs < 0) { 691 return UNKNOWN_ERROR; 692 } 693 694 *msec = (mDurationUs + 500) / 1000; 695 696 return OK; 697 } 698 699 status_t AAH_TXPlayer::reset() { 700 Mutex::Autolock autoLock(mLock); 701 reset_l(); 702 return OK; 703 } 704 705 void AAH_TXPlayer::reset_l() { 706 if (mFlags & PREPARING) { 707 mFlags |= PREPARE_CANCELLED; 708 if (mConnectingDataSource != NULL) { 709 ALOGI("interrupting the connection process"); 710 mConnectingDataSource->disconnect(); 711 } 712 713 if (mFlags & PREPARING_CONNECTED) { 714 // We are basically done preparing, we're just buffering 715 // enough data to start playback, we can safely interrupt that. 716 finishAsyncPrepare_l(); 717 } 718 } 719 720 while (mFlags & PREPARING) { 721 mPreparedCondition.wait(mLock); 722 } 723 724 cancelPlayerEvents(); 725 726 sendEOS_l(); 727 728 mCachedSource.clear(); 729 730 if (mAudioSource != NULL) { 731 mAudioSource->stop(); 732 } 733 mAudioSource.clear(); 734 mAudioCodec = TRTPAudioPacket::kCodecInvalid; 735 mAudioFormat = NULL; 736 delete[] mAudioCodecData; 737 mAudioCodecData = NULL; 738 mAudioCodecDataSize = 0; 739 740 mFlags = 0; 741 mExtractorFlags = 0; 742 743 mDurationUs = -1; 744 mIsSeeking = false; 745 mSeekTimeUs = 0; 746 747 mUri.setTo(""); 748 mUriHeaders.clear(); 749 750 mFileSource.clear(); 751 752 mBitrate = -1; 753 754 { 755 Mutex::Autolock lock(mEndpointLock); 756 if (mAAH_Sender != NULL && mEndpointRegistered) { 757 mAAH_Sender->unregisterEndpoint(mEndpoint); 758 } 759 mEndpointRegistered = false; 760 mEndpointValid = false; 761 } 762 763 mProgramID = 0; 764 765 mAAH_Sender.clear(); 766 mLastQueuedMediaTimePTSValid = false; 767 mCurrentClockTransformValid = false; 768 mPlayRateIsPaused = false; 769 770 mTRTPVolume = 255; 771 } 772 773 status_t AAH_TXPlayer::setLooping(int loop) { 774 return OK; 775 } 776 777 player_type AAH_TXPlayer::playerType() { 778 return AAH_TX_PLAYER; 779 } 780 781 status_t AAH_TXPlayer::setParameter(int key, const Parcel &request) { 782 return ERROR_UNSUPPORTED; 783 } 784 785 status_t AAH_TXPlayer::getParameter(int key, Parcel *reply) { 786 return ERROR_UNSUPPORTED; 787 } 788 789 status_t AAH_TXPlayer::invoke(const Parcel& request, Parcel *reply) { 790 return INVALID_OPERATION; 791 } 792 793 status_t AAH_TXPlayer::getMetadata(const media::Metadata::Filter& ids, 794 Parcel* records) { 795 using media::Metadata; 796 797 Metadata metadata(records); 798 799 metadata.appendBool(Metadata::kPauseAvailable, true); 800 metadata.appendBool(Metadata::kSeekBackwardAvailable, false); 801 metadata.appendBool(Metadata::kSeekForwardAvailable, false); 802 metadata.appendBool(Metadata::kSeekAvailable, false); 803 804 return OK; 805 } 806 807 status_t AAH_TXPlayer::setVolume(float leftVolume, float rightVolume) { 808 if (leftVolume != rightVolume) { 809 ALOGE("%s does not support per channel volume: %f, %f", 810 __PRETTY_FUNCTION__, leftVolume, rightVolume); 811 } 812 813 float volume = clamp(leftVolume, 0.0f, 1.0f); 814 815 Mutex::Autolock lock(mLock); 816 mTRTPVolume = static_cast<uint8_t>((leftVolume * 255.0) + 0.5); 817 818 return OK; 819 } 820 821 status_t AAH_TXPlayer::setAudioStreamType(audio_stream_type_t streamType) { 822 return OK; 823 } 824 825 status_t AAH_TXPlayer::setRetransmitEndpoint( 826 const struct sockaddr_in* endpoint) { 827 Mutex::Autolock lock(mLock); 828 829 if (NULL == endpoint) 830 return BAD_VALUE; 831 832 // Once the endpoint has been registered, it may not be changed. 833 if (mEndpointRegistered) 834 return INVALID_OPERATION; 835 836 mEndpoint.addr = endpoint->sin_addr.s_addr; 837 mEndpoint.port = endpoint->sin_port; 838 mEndpointValid = true; 839 840 return OK; 841 } 842 843 void AAH_TXPlayer::notifyListener_l(int msg, int ext1, int ext2) { 844 sendEvent(msg, ext1, ext2); 845 } 846 847 bool AAH_TXPlayer::getBitrate_l(int64_t *bitrate) { 848 off64_t size; 849 if (mDurationUs >= 0 && 850 mCachedSource != NULL && 851 mCachedSource->getSize(&size) == OK) { 852 *bitrate = size * 8000000ll / mDurationUs; // in bits/sec 853 return true; 854 } 855 856 if (mBitrate >= 0) { 857 *bitrate = mBitrate; 858 return true; 859 } 860 861 *bitrate = 0; 862 863 return false; 864 } 865 866 // Returns true iff cached duration is available/applicable. 867 bool AAH_TXPlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) { 868 int64_t bitrate; 869 870 if (mCachedSource != NULL && getBitrate_l(&bitrate)) { 871 status_t finalStatus; 872 size_t cachedDataRemaining = mCachedSource->approxDataRemaining( 873 &finalStatus); 874 *durationUs = cachedDataRemaining * 8000000ll / bitrate; 875 *eos = (finalStatus != OK); 876 return true; 877 } 878 879 return false; 880 } 881 882 void AAH_TXPlayer::ensureCacheIsFetching_l() { 883 if (mCachedSource != NULL) { 884 mCachedSource->resumeFetchingIfNecessary(); 885 } 886 } 887 888 void AAH_TXPlayer::postBufferingEvent_l() { 889 if (mBufferingEventPending) { 890 return; 891 } 892 mBufferingEventPending = true; 893 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll); 894 } 895 896 void AAH_TXPlayer::postPumpAudioEvent_l(int64_t delayUs) { 897 if (mPumpAudioEventPending) { 898 return; 899 } 900 mPumpAudioEventPending = true; 901 mQueue.postEventWithDelay(mPumpAudioEvent, delayUs < 0 ? 10000 : delayUs); 902 } 903 904 void AAH_TXPlayer::onBufferingUpdate() { 905 Mutex::Autolock autoLock(mLock); 906 if (!mBufferingEventPending) { 907 return; 908 } 909 mBufferingEventPending = false; 910 911 if (mCachedSource != NULL) { 912 status_t finalStatus; 913 size_t cachedDataRemaining = mCachedSource->approxDataRemaining( 914 &finalStatus); 915 bool eos = (finalStatus != OK); 916 917 if (eos) { 918 if (finalStatus == ERROR_END_OF_STREAM) { 919 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100); 920 } 921 if (mFlags & PREPARING) { 922 ALOGV("cache has reached EOS, prepare is done."); 923 finishAsyncPrepare_l(); 924 } 925 } else { 926 int64_t bitrate; 927 if (getBitrate_l(&bitrate)) { 928 size_t cachedSize = mCachedSource->cachedSize(); 929 int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate; 930 931 int percentage = (100.0 * (double) cachedDurationUs) 932 / mDurationUs; 933 if (percentage > 100) { 934 percentage = 100; 935 } 936 937 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage); 938 } else { 939 // We don't know the bitrate of the stream, use absolute size 940 // limits to maintain the cache. 941 942 if ((mFlags & PLAYING) && 943 !eos && 944 (cachedDataRemaining < kLowWaterMarkBytes)) { 945 ALOGI("cache is running low (< %d) , pausing.", 946 kLowWaterMarkBytes); 947 mFlags |= CACHE_UNDERRUN; 948 pause_l(); 949 ensureCacheIsFetching_l(); 950 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); 951 } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) { 952 if (mFlags & CACHE_UNDERRUN) { 953 ALOGI("cache has filled up (> %d), resuming.", 954 kHighWaterMarkBytes); 955 mFlags &= ~CACHE_UNDERRUN; 956 play_l(); 957 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END); 958 } else if (mFlags & PREPARING) { 959 ALOGV("cache has filled up (> %d), prepare is done", 960 kHighWaterMarkBytes); 961 finishAsyncPrepare_l(); 962 } 963 } 964 } 965 } 966 } 967 968 int64_t cachedDurationUs; 969 bool eos; 970 if (getCachedDuration_l(&cachedDurationUs, &eos)) { 971 ALOGV("cachedDurationUs = %.2f secs, eos=%d", 972 cachedDurationUs / 1E6, eos); 973 974 if ((mFlags & PLAYING) && 975 !eos && 976 (cachedDurationUs < kLowWaterMarkUs)) { 977 ALOGI("cache is running low (%.2f secs) , pausing.", 978 cachedDurationUs / 1E6); 979 mFlags |= CACHE_UNDERRUN; 980 pause_l(); 981 ensureCacheIsFetching_l(); 982 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); 983 } else if (eos || cachedDurationUs > kHighWaterMarkUs) { 984 if (mFlags & CACHE_UNDERRUN) { 985 ALOGI("cache has filled up (%.2f secs), resuming.", 986 cachedDurationUs / 1E6); 987 mFlags &= ~CACHE_UNDERRUN; 988 play_l(); 989 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END); 990 } else if (mFlags & PREPARING) { 991 ALOGV("cache has filled up (%.2f secs), prepare is done", 992 cachedDurationUs / 1E6); 993 finishAsyncPrepare_l(); 994 } 995 } 996 } 997 998 postBufferingEvent_l(); 999 } 1000 1001 void AAH_TXPlayer::onPumpAudio() { 1002 while (true) { 1003 Mutex::Autolock autoLock(mLock); 1004 // If this flag is clear, its because someone has externally canceled 1005 // this pump operation (probably because we a resetting/shutting down). 1006 // Get out immediately, do not reschedule ourselves. 1007 if (!mPumpAudioEventPending) { 1008 return; 1009 } 1010 1011 // Start by checking if there is still work to be doing. If we have 1012 // never queued a payload (so we don't know what the last queued PTS is) 1013 // or we have never established a MediaTime->CommonTime transformation, 1014 // then we have work to do (one time through this loop should establish 1015 // both). Otherwise, we want to keep a fixed amt of presentation time 1016 // worth of data buffered. If we cannot get common time (service is 1017 // unavailable, or common time is undefined)) then we don't have a lot 1018 // of good options here. For now, signal an error up to the app level 1019 // and shut down the transmission pump. 1020 int64_t commonTimeNow; 1021 if (OK != mCCHelper.getCommonTime(&commonTimeNow)) { 1022 // Failed to get common time; either the service is down or common 1023 // time is not synced. Raise an error and shutdown the player. 1024 ALOGE("*** Cannot pump audio, unable to fetch common time." 1025 " Shutting down."); 1026 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, UNKNOWN_ERROR); 1027 mPumpAudioEventPending = false; 1028 break; 1029 } 1030 1031 if (mCurrentClockTransformValid && mLastQueuedMediaTimePTSValid) { 1032 int64_t mediaTimeNow; 1033 bool conversionResult = mCurrentClockTransform.doReverseTransform( 1034 commonTimeNow, 1035 &mediaTimeNow); 1036 CHECK(conversionResult); 1037 1038 if ((mediaTimeNow + 1039 kAAHBufferTimeUs - 1040 mLastQueuedMediaTimePTS) <= 0) { 1041 break; 1042 } 1043 } 1044 1045 MediaSource::ReadOptions options; 1046 if (mIsSeeking) { 1047 options.setSeekTo(mSeekTimeUs); 1048 } 1049 1050 MediaBuffer* mediaBuffer; 1051 status_t err = mAudioSource->read(&mediaBuffer, &options); 1052 if (err != NO_ERROR) { 1053 if (err == ERROR_END_OF_STREAM) { 1054 ALOGI("*** %s reached end of stream", __PRETTY_FUNCTION__); 1055 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100); 1056 notifyListener_l(MEDIA_PLAYBACK_COMPLETE); 1057 pause_l(false); 1058 sendEOS_l(); 1059 } else { 1060 ALOGE("*** %s read failed err=%d", __PRETTY_FUNCTION__, err); 1061 } 1062 return; 1063 } 1064 1065 if (mIsSeeking) { 1066 mIsSeeking = false; 1067 notifyListener_l(MEDIA_SEEK_COMPLETE); 1068 } 1069 1070 uint8_t* data = (static_cast<uint8_t*>(mediaBuffer->data()) + 1071 mediaBuffer->range_offset()); 1072 ALOGV("*** %s got media buffer data=[%02hhx %02hhx %02hhx %02hhx]" 1073 " offset=%d length=%d", __PRETTY_FUNCTION__, 1074 data[0], data[1], data[2], data[3], 1075 mediaBuffer->range_offset(), mediaBuffer->range_length()); 1076 1077 int64_t mediaTimeUs; 1078 CHECK(mediaBuffer->meta_data()->findInt64(kKeyTime, &mediaTimeUs)); 1079 ALOGV("*** timeUs=%lld", mediaTimeUs); 1080 1081 if (!mCurrentClockTransformValid) { 1082 if (OK == mCCHelper.getCommonTime(&commonTimeNow)) { 1083 mCurrentClockTransform.a_zero = mediaTimeUs; 1084 mCurrentClockTransform.b_zero = commonTimeNow + 1085 kAAHStartupLeadTimeUs; 1086 mCurrentClockTransform.a_to_b_numer = 1; 1087 mCurrentClockTransform.a_to_b_denom = mPlayRateIsPaused ? 0 : 1; 1088 mCurrentClockTransformValid = true; 1089 } else { 1090 // Failed to get common time; either the service is down or 1091 // common time is not synced. Raise an error and shutdown the 1092 // player. 1093 ALOGE("*** Cannot begin transmission, unable to fetch common" 1094 " time. Dropping sample with pts=%lld", mediaTimeUs); 1095 notifyListener_l(MEDIA_ERROR, 1096 MEDIA_ERROR_UNKNOWN, 1097 UNKNOWN_ERROR); 1098 mPumpAudioEventPending = false; 1099 break; 1100 } 1101 } 1102 1103 ALOGV("*** transmitting packet with pts=%lld", mediaTimeUs); 1104 1105 sp<TRTPAudioPacket> packet = new TRTPAudioPacket(); 1106 packet->setPTS(mediaTimeUs); 1107 packet->setSubstreamID(1); 1108 1109 packet->setCodecType(mAudioCodec); 1110 packet->setVolume(mTRTPVolume); 1111 // TODO : introduce a throttle for this so we can control the 1112 // frequency with which transforms get sent. 1113 packet->setClockTransform(mCurrentClockTransform); 1114 packet->setAccessUnitData(data, mediaBuffer->range_length()); 1115 1116 // TODO : while its pretty much universally true that audio ES payloads 1117 // are all RAPs across all codecs, it might be a good idea to throttle 1118 // the frequency with which we send codec out of band data to the RXers. 1119 // If/when we do, we need to flag only those payloads which have 1120 // required out of band data attached to them as RAPs. 1121 packet->setRandomAccessPoint(true); 1122 1123 if (mAudioCodecData && mAudioCodecDataSize) { 1124 packet->setAuxData(mAudioCodecData, mAudioCodecDataSize); 1125 } 1126 1127 queuePacketToSender_l(packet); 1128 mediaBuffer->release(); 1129 1130 mLastQueuedMediaTimePTSValid = true; 1131 mLastQueuedMediaTimePTS = mediaTimeUs; 1132 } 1133 1134 { // Explicit scope for the autolock pattern. 1135 Mutex::Autolock autoLock(mLock); 1136 1137 // If someone externally has cleared this flag, its because we should be 1138 // shutting down. Do not reschedule ourselves. 1139 if (!mPumpAudioEventPending) { 1140 return; 1141 } 1142 1143 // Looks like no one canceled us explicitly. Clear our flag and post a 1144 // new event to ourselves. 1145 mPumpAudioEventPending = false; 1146 postPumpAudioEvent_l(10000); 1147 } 1148 } 1149 1150 void AAH_TXPlayer::queuePacketToSender_l(const sp<TRTPPacket>& packet) { 1151 if (mAAH_Sender == NULL) { 1152 return; 1153 } 1154 1155 sp<AMessage> message = new AMessage(AAH_TXSender::kWhatSendPacket, 1156 mAAH_Sender->handlerID()); 1157 1158 { 1159 Mutex::Autolock lock(mEndpointLock); 1160 if (!mEndpointValid) { 1161 return; 1162 } 1163 1164 message->setInt32(AAH_TXSender::kSendPacketIPAddr, mEndpoint.addr); 1165 message->setInt32(AAH_TXSender::kSendPacketPort, mEndpoint.port); 1166 } 1167 1168 packet->setProgramID(mProgramID); 1169 packet->setExpireTime(systemTime() + kAAHRetryKeepAroundTimeNs); 1170 packet->pack(); 1171 1172 message->setObject(AAH_TXSender::kSendPacketTRTPPacket, packet); 1173 1174 message->post(); 1175 } 1176 1177 } // namespace android 1178