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