1 /* 2 * Copyright 2012, 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 "PlaybackSession" 19 #include <utils/Log.h> 20 21 #include "PlaybackSession.h" 22 23 #include "Converter.h" 24 #include "MediaPuller.h" 25 #include "RepeaterSource.h" 26 #include "include/avc_utils.h" 27 #include "WifiDisplaySource.h" 28 29 #include <binder/IServiceManager.h> 30 #include <cutils/properties.h> 31 #include <media/IHDCP.h> 32 #include <media/stagefright/foundation/ABitReader.h> 33 #include <media/stagefright/foundation/ABuffer.h> 34 #include <media/stagefright/foundation/ADebug.h> 35 #include <media/stagefright/foundation/AMessage.h> 36 #include <media/stagefright/foundation/hexdump.h> 37 #include <media/stagefright/AudioSource.h> 38 #include <media/stagefright/DataSource.h> 39 #include <media/stagefright/MediaDefs.h> 40 #include <media/stagefright/MediaErrors.h> 41 #include <media/stagefright/MediaSource.h> 42 #include <media/stagefright/MetaData.h> 43 #include <media/stagefright/NuMediaExtractor.h> 44 #include <media/stagefright/SurfaceMediaSource.h> 45 #include <media/stagefright/Utils.h> 46 47 #include <OMX_IVCommon.h> 48 49 namespace android { 50 51 struct WifiDisplaySource::PlaybackSession::Track : public AHandler { 52 enum { 53 kWhatStopped, 54 }; 55 56 Track(const sp<AMessage> ¬ify, 57 const sp<ALooper> &pullLooper, 58 const sp<ALooper> &codecLooper, 59 const sp<MediaPuller> &mediaPuller, 60 const sp<Converter> &converter); 61 62 Track(const sp<AMessage> ¬ify, const sp<AMessage> &format); 63 64 void setRepeaterSource(const sp<RepeaterSource> &source); 65 66 sp<AMessage> getFormat(); 67 bool isAudio() const; 68 69 const sp<Converter> &converter() const; 70 const sp<RepeaterSource> &repeaterSource() const; 71 72 ssize_t mediaSenderTrackIndex() const; 73 void setMediaSenderTrackIndex(size_t index); 74 75 status_t start(); 76 void stopAsync(); 77 78 void pause(); 79 void resume(); 80 81 void queueAccessUnit(const sp<ABuffer> &accessUnit); 82 sp<ABuffer> dequeueAccessUnit(); 83 84 bool hasOutputBuffer(int64_t *timeUs) const; 85 void queueOutputBuffer(const sp<ABuffer> &accessUnit); 86 sp<ABuffer> dequeueOutputBuffer(); 87 88 #if SUSPEND_VIDEO_IF_IDLE 89 bool isSuspended() const; 90 #endif 91 92 size_t countQueuedOutputBuffers() const { 93 return mQueuedOutputBuffers.size(); 94 } 95 96 void requestIDRFrame(); 97 98 protected: 99 virtual void onMessageReceived(const sp<AMessage> &msg); 100 virtual ~Track(); 101 102 private: 103 enum { 104 kWhatMediaPullerStopped, 105 }; 106 107 sp<AMessage> mNotify; 108 sp<ALooper> mPullLooper; 109 sp<ALooper> mCodecLooper; 110 sp<MediaPuller> mMediaPuller; 111 sp<Converter> mConverter; 112 sp<AMessage> mFormat; 113 bool mStarted; 114 ssize_t mMediaSenderTrackIndex; 115 bool mIsAudio; 116 List<sp<ABuffer> > mQueuedAccessUnits; 117 sp<RepeaterSource> mRepeaterSource; 118 List<sp<ABuffer> > mQueuedOutputBuffers; 119 int64_t mLastOutputBufferQueuedTimeUs; 120 121 static bool IsAudioFormat(const sp<AMessage> &format); 122 123 DISALLOW_EVIL_CONSTRUCTORS(Track); 124 }; 125 126 WifiDisplaySource::PlaybackSession::Track::Track( 127 const sp<AMessage> ¬ify, 128 const sp<ALooper> &pullLooper, 129 const sp<ALooper> &codecLooper, 130 const sp<MediaPuller> &mediaPuller, 131 const sp<Converter> &converter) 132 : mNotify(notify), 133 mPullLooper(pullLooper), 134 mCodecLooper(codecLooper), 135 mMediaPuller(mediaPuller), 136 mConverter(converter), 137 mStarted(false), 138 mIsAudio(IsAudioFormat(mConverter->getOutputFormat())), 139 mLastOutputBufferQueuedTimeUs(-1ll) { 140 } 141 142 WifiDisplaySource::PlaybackSession::Track::Track( 143 const sp<AMessage> ¬ify, const sp<AMessage> &format) 144 : mNotify(notify), 145 mFormat(format), 146 mStarted(false), 147 mIsAudio(IsAudioFormat(format)), 148 mLastOutputBufferQueuedTimeUs(-1ll) { 149 } 150 151 WifiDisplaySource::PlaybackSession::Track::~Track() { 152 CHECK(!mStarted); 153 } 154 155 // static 156 bool WifiDisplaySource::PlaybackSession::Track::IsAudioFormat( 157 const sp<AMessage> &format) { 158 AString mime; 159 CHECK(format->findString("mime", &mime)); 160 161 return !strncasecmp(mime.c_str(), "audio/", 6); 162 } 163 164 sp<AMessage> WifiDisplaySource::PlaybackSession::Track::getFormat() { 165 return mFormat != NULL ? mFormat : mConverter->getOutputFormat(); 166 } 167 168 bool WifiDisplaySource::PlaybackSession::Track::isAudio() const { 169 return mIsAudio; 170 } 171 172 const sp<Converter> &WifiDisplaySource::PlaybackSession::Track::converter() const { 173 return mConverter; 174 } 175 176 const sp<RepeaterSource> & 177 WifiDisplaySource::PlaybackSession::Track::repeaterSource() const { 178 return mRepeaterSource; 179 } 180 181 ssize_t WifiDisplaySource::PlaybackSession::Track::mediaSenderTrackIndex() const { 182 CHECK_GE(mMediaSenderTrackIndex, 0); 183 return mMediaSenderTrackIndex; 184 } 185 186 void WifiDisplaySource::PlaybackSession::Track::setMediaSenderTrackIndex( 187 size_t index) { 188 mMediaSenderTrackIndex = index; 189 } 190 191 status_t WifiDisplaySource::PlaybackSession::Track::start() { 192 ALOGV("Track::start isAudio=%d", mIsAudio); 193 194 CHECK(!mStarted); 195 196 status_t err = OK; 197 198 if (mMediaPuller != NULL) { 199 err = mMediaPuller->start(); 200 } 201 202 if (err == OK) { 203 mStarted = true; 204 } 205 206 return err; 207 } 208 209 void WifiDisplaySource::PlaybackSession::Track::stopAsync() { 210 ALOGV("Track::stopAsync isAudio=%d", mIsAudio); 211 212 if (mConverter != NULL) { 213 mConverter->shutdownAsync(); 214 } 215 216 sp<AMessage> msg = new AMessage(kWhatMediaPullerStopped, id()); 217 218 if (mStarted && mMediaPuller != NULL) { 219 if (mRepeaterSource != NULL) { 220 // Let's unblock MediaPuller's MediaSource::read(). 221 mRepeaterSource->wakeUp(); 222 } 223 224 mMediaPuller->stopAsync(msg); 225 } else { 226 mStarted = false; 227 msg->post(); 228 } 229 } 230 231 void WifiDisplaySource::PlaybackSession::Track::pause() { 232 mMediaPuller->pause(); 233 } 234 235 void WifiDisplaySource::PlaybackSession::Track::resume() { 236 mMediaPuller->resume(); 237 } 238 239 void WifiDisplaySource::PlaybackSession::Track::onMessageReceived( 240 const sp<AMessage> &msg) { 241 switch (msg->what()) { 242 case kWhatMediaPullerStopped: 243 { 244 mConverter.clear(); 245 246 mStarted = false; 247 248 sp<AMessage> notify = mNotify->dup(); 249 notify->setInt32("what", kWhatStopped); 250 notify->post(); 251 252 ALOGI("kWhatStopped %s posted", mIsAudio ? "audio" : "video"); 253 break; 254 } 255 256 default: 257 TRESPASS(); 258 } 259 } 260 261 void WifiDisplaySource::PlaybackSession::Track::queueAccessUnit( 262 const sp<ABuffer> &accessUnit) { 263 mQueuedAccessUnits.push_back(accessUnit); 264 } 265 266 sp<ABuffer> WifiDisplaySource::PlaybackSession::Track::dequeueAccessUnit() { 267 if (mQueuedAccessUnits.empty()) { 268 return NULL; 269 } 270 271 sp<ABuffer> accessUnit = *mQueuedAccessUnits.begin(); 272 CHECK(accessUnit != NULL); 273 274 mQueuedAccessUnits.erase(mQueuedAccessUnits.begin()); 275 276 return accessUnit; 277 } 278 279 void WifiDisplaySource::PlaybackSession::Track::setRepeaterSource( 280 const sp<RepeaterSource> &source) { 281 mRepeaterSource = source; 282 } 283 284 void WifiDisplaySource::PlaybackSession::Track::requestIDRFrame() { 285 if (mIsAudio) { 286 return; 287 } 288 289 if (mRepeaterSource != NULL) { 290 mRepeaterSource->wakeUp(); 291 } 292 293 mConverter->requestIDRFrame(); 294 } 295 296 bool WifiDisplaySource::PlaybackSession::Track::hasOutputBuffer( 297 int64_t *timeUs) const { 298 *timeUs = 0ll; 299 300 if (mQueuedOutputBuffers.empty()) { 301 return false; 302 } 303 304 const sp<ABuffer> &outputBuffer = *mQueuedOutputBuffers.begin(); 305 306 CHECK(outputBuffer->meta()->findInt64("timeUs", timeUs)); 307 308 return true; 309 } 310 311 void WifiDisplaySource::PlaybackSession::Track::queueOutputBuffer( 312 const sp<ABuffer> &accessUnit) { 313 mQueuedOutputBuffers.push_back(accessUnit); 314 mLastOutputBufferQueuedTimeUs = ALooper::GetNowUs(); 315 } 316 317 sp<ABuffer> WifiDisplaySource::PlaybackSession::Track::dequeueOutputBuffer() { 318 CHECK(!mQueuedOutputBuffers.empty()); 319 320 sp<ABuffer> outputBuffer = *mQueuedOutputBuffers.begin(); 321 mQueuedOutputBuffers.erase(mQueuedOutputBuffers.begin()); 322 323 return outputBuffer; 324 } 325 326 #if SUSPEND_VIDEO_IF_IDLE 327 bool WifiDisplaySource::PlaybackSession::Track::isSuspended() const { 328 if (!mQueuedOutputBuffers.empty()) { 329 return false; 330 } 331 332 if (mLastOutputBufferQueuedTimeUs < 0ll) { 333 // We've never seen an output buffer queued, but tracks start 334 // out live, not suspended. 335 return false; 336 } 337 338 // If we've not seen new output data for 60ms or more, we consider 339 // this track suspended for the time being. 340 return (ALooper::GetNowUs() - mLastOutputBufferQueuedTimeUs) > 60000ll; 341 } 342 #endif 343 344 //////////////////////////////////////////////////////////////////////////////// 345 346 WifiDisplaySource::PlaybackSession::PlaybackSession( 347 const sp<ANetworkSession> &netSession, 348 const sp<AMessage> ¬ify, 349 const in_addr &interfaceAddr, 350 const sp<IHDCP> &hdcp, 351 const char *path) 352 : mNetSession(netSession), 353 mNotify(notify), 354 mInterfaceAddr(interfaceAddr), 355 mHDCP(hdcp), 356 mLocalRTPPort(-1), 357 mWeAreDead(false), 358 mPaused(false), 359 mLastLifesignUs(), 360 mVideoTrackIndex(-1), 361 mPrevTimeUs(-1ll), 362 mPullExtractorPending(false), 363 mPullExtractorGeneration(0), 364 mFirstSampleTimeRealUs(-1ll), 365 mFirstSampleTimeUs(-1ll) { 366 if (path != NULL) { 367 mMediaPath.setTo(path); 368 } 369 } 370 371 status_t WifiDisplaySource::PlaybackSession::init( 372 const char *clientIP, 373 int32_t clientRtp, 374 RTPSender::TransportMode rtpMode, 375 int32_t clientRtcp, 376 RTPSender::TransportMode rtcpMode, 377 bool enableAudio, 378 bool usePCMAudio, 379 bool enableVideo, 380 VideoFormats::ResolutionType videoResolutionType, 381 size_t videoResolutionIndex) { 382 sp<AMessage> notify = new AMessage(kWhatMediaSenderNotify, id()); 383 mMediaSender = new MediaSender(mNetSession, notify); 384 looper()->registerHandler(mMediaSender); 385 386 mMediaSender->setHDCP(mHDCP); 387 388 status_t err = setupPacketizer( 389 enableAudio, 390 usePCMAudio, 391 enableVideo, 392 videoResolutionType, 393 videoResolutionIndex); 394 395 if (err == OK) { 396 err = mMediaSender->initAsync( 397 -1 /* trackIndex */, 398 clientIP, 399 clientRtp, 400 rtpMode, 401 clientRtcp, 402 rtcpMode, 403 &mLocalRTPPort); 404 } 405 406 if (err != OK) { 407 mLocalRTPPort = -1; 408 409 looper()->unregisterHandler(mMediaSender->id()); 410 mMediaSender.clear(); 411 412 return err; 413 } 414 415 updateLiveness(); 416 417 return OK; 418 } 419 420 WifiDisplaySource::PlaybackSession::~PlaybackSession() { 421 } 422 423 int32_t WifiDisplaySource::PlaybackSession::getRTPPort() const { 424 return mLocalRTPPort; 425 } 426 427 int64_t WifiDisplaySource::PlaybackSession::getLastLifesignUs() const { 428 return mLastLifesignUs; 429 } 430 431 void WifiDisplaySource::PlaybackSession::updateLiveness() { 432 mLastLifesignUs = ALooper::GetNowUs(); 433 } 434 435 status_t WifiDisplaySource::PlaybackSession::play() { 436 updateLiveness(); 437 438 (new AMessage(kWhatResume, id()))->post(); 439 440 return OK; 441 } 442 443 status_t WifiDisplaySource::PlaybackSession::onMediaSenderInitialized() { 444 for (size_t i = 0; i < mTracks.size(); ++i) { 445 CHECK_EQ((status_t)OK, mTracks.editValueAt(i)->start()); 446 } 447 448 sp<AMessage> notify = mNotify->dup(); 449 notify->setInt32("what", kWhatSessionEstablished); 450 notify->post(); 451 452 return OK; 453 } 454 455 status_t WifiDisplaySource::PlaybackSession::pause() { 456 updateLiveness(); 457 458 (new AMessage(kWhatPause, id()))->post(); 459 460 return OK; 461 } 462 463 void WifiDisplaySource::PlaybackSession::destroyAsync() { 464 ALOGI("destroyAsync"); 465 466 for (size_t i = 0; i < mTracks.size(); ++i) { 467 mTracks.valueAt(i)->stopAsync(); 468 } 469 } 470 471 void WifiDisplaySource::PlaybackSession::onMessageReceived( 472 const sp<AMessage> &msg) { 473 switch (msg->what()) { 474 case kWhatConverterNotify: 475 { 476 if (mWeAreDead) { 477 ALOGV("dropping msg '%s' because we're dead", 478 msg->debugString().c_str()); 479 480 break; 481 } 482 483 int32_t what; 484 CHECK(msg->findInt32("what", &what)); 485 486 size_t trackIndex; 487 CHECK(msg->findSize("trackIndex", &trackIndex)); 488 489 if (what == Converter::kWhatAccessUnit) { 490 sp<ABuffer> accessUnit; 491 CHECK(msg->findBuffer("accessUnit", &accessUnit)); 492 493 const sp<Track> &track = mTracks.valueFor(trackIndex); 494 495 status_t err = mMediaSender->queueAccessUnit( 496 track->mediaSenderTrackIndex(), 497 accessUnit); 498 499 if (err != OK) { 500 notifySessionDead(); 501 } 502 break; 503 } else if (what == Converter::kWhatEOS) { 504 CHECK_EQ(what, Converter::kWhatEOS); 505 506 ALOGI("output EOS on track %d", trackIndex); 507 508 ssize_t index = mTracks.indexOfKey(trackIndex); 509 CHECK_GE(index, 0); 510 511 const sp<Converter> &converter = 512 mTracks.valueAt(index)->converter(); 513 looper()->unregisterHandler(converter->id()); 514 515 mTracks.removeItemsAt(index); 516 517 if (mTracks.isEmpty()) { 518 ALOGI("Reached EOS"); 519 } 520 } else { 521 CHECK_EQ(what, Converter::kWhatError); 522 523 status_t err; 524 CHECK(msg->findInt32("err", &err)); 525 526 ALOGE("converter signaled error %d", err); 527 528 notifySessionDead(); 529 } 530 break; 531 } 532 533 case kWhatMediaSenderNotify: 534 { 535 int32_t what; 536 CHECK(msg->findInt32("what", &what)); 537 538 if (what == MediaSender::kWhatInitDone) { 539 status_t err; 540 CHECK(msg->findInt32("err", &err)); 541 542 if (err == OK) { 543 onMediaSenderInitialized(); 544 } else { 545 notifySessionDead(); 546 } 547 } else if (what == MediaSender::kWhatError) { 548 notifySessionDead(); 549 } else if (what == MediaSender::kWhatNetworkStall) { 550 size_t numBytesQueued; 551 CHECK(msg->findSize("numBytesQueued", &numBytesQueued)); 552 553 if (mVideoTrackIndex >= 0) { 554 const sp<Track> &videoTrack = 555 mTracks.valueFor(mVideoTrackIndex); 556 557 sp<Converter> converter = videoTrack->converter(); 558 if (converter != NULL) { 559 converter->dropAFrame(); 560 } 561 } 562 } else { 563 TRESPASS(); 564 } 565 break; 566 } 567 568 case kWhatTrackNotify: 569 { 570 int32_t what; 571 CHECK(msg->findInt32("what", &what)); 572 573 size_t trackIndex; 574 CHECK(msg->findSize("trackIndex", &trackIndex)); 575 576 if (what == Track::kWhatStopped) { 577 ALOGI("Track %d stopped", trackIndex); 578 579 sp<Track> track = mTracks.valueFor(trackIndex); 580 looper()->unregisterHandler(track->id()); 581 mTracks.removeItem(trackIndex); 582 track.clear(); 583 584 if (!mTracks.isEmpty()) { 585 ALOGI("not all tracks are stopped yet"); 586 break; 587 } 588 589 looper()->unregisterHandler(mMediaSender->id()); 590 mMediaSender.clear(); 591 592 sp<AMessage> notify = mNotify->dup(); 593 notify->setInt32("what", kWhatSessionDestroyed); 594 notify->post(); 595 } 596 break; 597 } 598 599 case kWhatPause: 600 { 601 if (mExtractor != NULL) { 602 ++mPullExtractorGeneration; 603 mFirstSampleTimeRealUs = -1ll; 604 mFirstSampleTimeUs = -1ll; 605 } 606 607 if (mPaused) { 608 break; 609 } 610 611 for (size_t i = 0; i < mTracks.size(); ++i) { 612 mTracks.editValueAt(i)->pause(); 613 } 614 615 mPaused = true; 616 break; 617 } 618 619 case kWhatResume: 620 { 621 if (mExtractor != NULL) { 622 schedulePullExtractor(); 623 } 624 625 if (!mPaused) { 626 break; 627 } 628 629 for (size_t i = 0; i < mTracks.size(); ++i) { 630 mTracks.editValueAt(i)->resume(); 631 } 632 633 mPaused = false; 634 break; 635 } 636 637 case kWhatPullExtractorSample: 638 { 639 int32_t generation; 640 CHECK(msg->findInt32("generation", &generation)); 641 642 if (generation != mPullExtractorGeneration) { 643 break; 644 } 645 646 mPullExtractorPending = false; 647 648 onPullExtractor(); 649 break; 650 } 651 652 default: 653 TRESPASS(); 654 } 655 } 656 657 status_t WifiDisplaySource::PlaybackSession::setupMediaPacketizer( 658 bool enableAudio, bool enableVideo) { 659 DataSource::RegisterDefaultSniffers(); 660 661 mExtractor = new NuMediaExtractor; 662 663 status_t err = mExtractor->setDataSource(mMediaPath.c_str()); 664 665 if (err != OK) { 666 return err; 667 } 668 669 size_t n = mExtractor->countTracks(); 670 bool haveAudio = false; 671 bool haveVideo = false; 672 for (size_t i = 0; i < n; ++i) { 673 sp<AMessage> format; 674 err = mExtractor->getTrackFormat(i, &format); 675 676 if (err != OK) { 677 continue; 678 } 679 680 AString mime; 681 CHECK(format->findString("mime", &mime)); 682 683 bool isAudio = !strncasecmp(mime.c_str(), "audio/", 6); 684 bool isVideo = !strncasecmp(mime.c_str(), "video/", 6); 685 686 if (isAudio && enableAudio && !haveAudio) { 687 haveAudio = true; 688 } else if (isVideo && enableVideo && !haveVideo) { 689 haveVideo = true; 690 } else { 691 continue; 692 } 693 694 err = mExtractor->selectTrack(i); 695 696 size_t trackIndex = mTracks.size(); 697 698 sp<AMessage> notify = new AMessage(kWhatTrackNotify, id()); 699 notify->setSize("trackIndex", trackIndex); 700 701 sp<Track> track = new Track(notify, format); 702 looper()->registerHandler(track); 703 704 mTracks.add(trackIndex, track); 705 706 mExtractorTrackToInternalTrack.add(i, trackIndex); 707 708 if (isVideo) { 709 mVideoTrackIndex = trackIndex; 710 } 711 712 uint32_t flags = MediaSender::FLAG_MANUALLY_PREPEND_SPS_PPS; 713 714 ssize_t mediaSenderTrackIndex = 715 mMediaSender->addTrack(format, flags); 716 CHECK_GE(mediaSenderTrackIndex, 0); 717 718 track->setMediaSenderTrackIndex(mediaSenderTrackIndex); 719 720 if ((haveAudio || !enableAudio) && (haveVideo || !enableVideo)) { 721 break; 722 } 723 } 724 725 return OK; 726 } 727 728 void WifiDisplaySource::PlaybackSession::schedulePullExtractor() { 729 if (mPullExtractorPending) { 730 return; 731 } 732 733 int64_t sampleTimeUs; 734 status_t err = mExtractor->getSampleTime(&sampleTimeUs); 735 736 int64_t nowUs = ALooper::GetNowUs(); 737 738 if (mFirstSampleTimeRealUs < 0ll) { 739 mFirstSampleTimeRealUs = nowUs; 740 mFirstSampleTimeUs = sampleTimeUs; 741 } 742 743 int64_t whenUs = sampleTimeUs - mFirstSampleTimeUs + mFirstSampleTimeRealUs; 744 745 sp<AMessage> msg = new AMessage(kWhatPullExtractorSample, id()); 746 msg->setInt32("generation", mPullExtractorGeneration); 747 msg->post(whenUs - nowUs); 748 749 mPullExtractorPending = true; 750 } 751 752 void WifiDisplaySource::PlaybackSession::onPullExtractor() { 753 sp<ABuffer> accessUnit = new ABuffer(1024 * 1024); 754 status_t err = mExtractor->readSampleData(accessUnit); 755 if (err != OK) { 756 // EOS. 757 return; 758 } 759 760 int64_t timeUs; 761 CHECK_EQ((status_t)OK, mExtractor->getSampleTime(&timeUs)); 762 763 accessUnit->meta()->setInt64( 764 "timeUs", mFirstSampleTimeRealUs + timeUs - mFirstSampleTimeUs); 765 766 size_t trackIndex; 767 CHECK_EQ((status_t)OK, mExtractor->getSampleTrackIndex(&trackIndex)); 768 769 sp<AMessage> msg = new AMessage(kWhatConverterNotify, id()); 770 771 msg->setSize( 772 "trackIndex", mExtractorTrackToInternalTrack.valueFor(trackIndex)); 773 774 msg->setInt32("what", Converter::kWhatAccessUnit); 775 msg->setBuffer("accessUnit", accessUnit); 776 msg->post(); 777 778 mExtractor->advance(); 779 780 schedulePullExtractor(); 781 } 782 783 status_t WifiDisplaySource::PlaybackSession::setupPacketizer( 784 bool enableAudio, 785 bool usePCMAudio, 786 bool enableVideo, 787 VideoFormats::ResolutionType videoResolutionType, 788 size_t videoResolutionIndex) { 789 CHECK(enableAudio || enableVideo); 790 791 if (!mMediaPath.empty()) { 792 return setupMediaPacketizer(enableAudio, enableVideo); 793 } 794 795 if (enableVideo) { 796 status_t err = addVideoSource( 797 videoResolutionType, videoResolutionIndex); 798 799 if (err != OK) { 800 return err; 801 } 802 } 803 804 if (!enableAudio) { 805 return OK; 806 } 807 808 return addAudioSource(usePCMAudio); 809 } 810 811 status_t WifiDisplaySource::PlaybackSession::addSource( 812 bool isVideo, const sp<MediaSource> &source, bool isRepeaterSource, 813 bool usePCMAudio, size_t *numInputBuffers) { 814 CHECK(!usePCMAudio || !isVideo); 815 CHECK(!isRepeaterSource || isVideo); 816 817 sp<ALooper> pullLooper = new ALooper; 818 pullLooper->setName("pull_looper"); 819 820 pullLooper->start( 821 false /* runOnCallingThread */, 822 false /* canCallJava */, 823 PRIORITY_AUDIO); 824 825 sp<ALooper> codecLooper = new ALooper; 826 codecLooper->setName("codec_looper"); 827 828 codecLooper->start( 829 false /* runOnCallingThread */, 830 false /* canCallJava */, 831 PRIORITY_AUDIO); 832 833 size_t trackIndex; 834 835 sp<AMessage> notify; 836 837 trackIndex = mTracks.size(); 838 839 sp<AMessage> format; 840 status_t err = convertMetaDataToMessage(source->getFormat(), &format); 841 CHECK_EQ(err, (status_t)OK); 842 843 if (isVideo) { 844 format->setInt32("store-metadata-in-buffers", true); 845 846 format->setInt32( 847 "color-format", OMX_COLOR_FormatAndroidOpaque); 848 } 849 850 notify = new AMessage(kWhatConverterNotify, id()); 851 notify->setSize("trackIndex", trackIndex); 852 853 sp<Converter> converter = 854 new Converter(notify, codecLooper, format, usePCMAudio); 855 856 err = converter->initCheck(); 857 if (err != OK) { 858 ALOGE("%s converter returned err %d", isVideo ? "video" : "audio", err); 859 return err; 860 } 861 862 looper()->registerHandler(converter); 863 864 notify = new AMessage(Converter::kWhatMediaPullerNotify, converter->id()); 865 notify->setSize("trackIndex", trackIndex); 866 867 sp<MediaPuller> puller = new MediaPuller(source, notify); 868 pullLooper->registerHandler(puller); 869 870 if (numInputBuffers != NULL) { 871 *numInputBuffers = converter->getInputBufferCount(); 872 } 873 874 notify = new AMessage(kWhatTrackNotify, id()); 875 notify->setSize("trackIndex", trackIndex); 876 877 sp<Track> track = new Track( 878 notify, pullLooper, codecLooper, puller, converter); 879 880 if (isRepeaterSource) { 881 track->setRepeaterSource(static_cast<RepeaterSource *>(source.get())); 882 } 883 884 looper()->registerHandler(track); 885 886 mTracks.add(trackIndex, track); 887 888 if (isVideo) { 889 mVideoTrackIndex = trackIndex; 890 } 891 892 uint32_t flags = 0; 893 if (converter->needToManuallyPrependSPSPPS()) { 894 flags |= MediaSender::FLAG_MANUALLY_PREPEND_SPS_PPS; 895 } 896 897 ssize_t mediaSenderTrackIndex = 898 mMediaSender->addTrack(converter->getOutputFormat(), flags); 899 CHECK_GE(mediaSenderTrackIndex, 0); 900 901 track->setMediaSenderTrackIndex(mediaSenderTrackIndex); 902 903 return OK; 904 } 905 906 status_t WifiDisplaySource::PlaybackSession::addVideoSource( 907 VideoFormats::ResolutionType videoResolutionType, 908 size_t videoResolutionIndex) { 909 size_t width, height, framesPerSecond; 910 bool interlaced; 911 CHECK(VideoFormats::GetConfiguration( 912 videoResolutionType, 913 videoResolutionIndex, 914 &width, 915 &height, 916 &framesPerSecond, 917 &interlaced)); 918 919 sp<SurfaceMediaSource> source = new SurfaceMediaSource(width, height); 920 921 source->setUseAbsoluteTimestamps(); 922 923 sp<RepeaterSource> videoSource = 924 new RepeaterSource(source, framesPerSecond); 925 926 size_t numInputBuffers; 927 status_t err = addSource( 928 true /* isVideo */, videoSource, true /* isRepeaterSource */, 929 false /* usePCMAudio */, &numInputBuffers); 930 931 if (err != OK) { 932 return err; 933 } 934 935 err = source->setMaxAcquiredBufferCount(numInputBuffers); 936 CHECK_EQ(err, (status_t)OK); 937 938 mBufferQueue = source->getBufferQueue(); 939 940 return OK; 941 } 942 943 status_t WifiDisplaySource::PlaybackSession::addAudioSource(bool usePCMAudio) { 944 sp<AudioSource> audioSource = new AudioSource( 945 AUDIO_SOURCE_REMOTE_SUBMIX, 946 48000 /* sampleRate */, 947 2 /* channelCount */); 948 949 if (audioSource->initCheck() == OK) { 950 return addSource( 951 false /* isVideo */, audioSource, false /* isRepeaterSource */, 952 usePCMAudio, NULL /* numInputBuffers */); 953 } 954 955 ALOGW("Unable to instantiate audio source"); 956 957 return OK; 958 } 959 960 sp<IGraphicBufferProducer> WifiDisplaySource::PlaybackSession::getSurfaceTexture() { 961 return mBufferQueue; 962 } 963 964 void WifiDisplaySource::PlaybackSession::requestIDRFrame() { 965 for (size_t i = 0; i < mTracks.size(); ++i) { 966 const sp<Track> &track = mTracks.valueAt(i); 967 968 track->requestIDRFrame(); 969 } 970 } 971 972 void WifiDisplaySource::PlaybackSession::notifySessionDead() { 973 // Inform WifiDisplaySource of our premature death (wish). 974 sp<AMessage> notify = mNotify->dup(); 975 notify->setInt32("what", kWhatSessionDead); 976 notify->post(); 977 978 mWeAreDead = true; 979 } 980 981 } // namespace android 982 983