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