Home | History | Annotate | Download | only in source
      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> &notify,
     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> &notify, 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> &notify,
    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> &notify, 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> &notify,
    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