12bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber/*
22bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * Copyright (C) 2010 The Android Open Source Project
32bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber *
42bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
52bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * you may not use this file except in compliance with the License.
62bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * You may obtain a copy of the License at
72bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber *
82bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
92bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber *
102bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * Unless required by applicable law or agreed to in writing, software
112bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
122bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * See the License for the specific language governing permissions and
142bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * limitations under the License.
152bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber */
162bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
172bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber//#define LOG_NDEBUG 0
182bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber#define LOG_TAG "RTSPSource"
192bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber#include <utils/Log.h>
202bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
212bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber#include "RTSPSource.h"
222bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
232bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber#include "AnotherPacketSource.h"
242bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber#include "MyHandler.h"
2581dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé#include "SDPLoader.h"
262bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
271b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/IMediaHTTPService.h>
2849694688c82214f5fd9e969e177c9e126a240a26Andreas Huber#include <media/stagefright/MediaDefs.h>
292bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber#include <media/stagefright/MetaData.h>
302bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
312bfdd428c56c7524d1a11979f200a1762866032dAndreas Hubernamespace android {
322bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
33cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönssonconst int64_t kNearEOSTimeoutUs = 2000000ll; // 2 secs
34cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson
3548fa06d1e80a872c7495804979256e021e566ae0Wei Jia// Default Buffer Underflow/Prepare/StartServer/Overflow Marks
3648fa06d1e80a872c7495804979256e021e566ae0Wei Jiastatic const int kUnderflowMarkMs   =  1000;  // 1 second
3748fa06d1e80a872c7495804979256e021e566ae0Wei Jiastatic const int kPrepareMarkMs     =  3000;  // 3 seconds
3848fa06d1e80a872c7495804979256e021e566ae0Wei Jia//static const int kStartServerMarkMs =  5000;
3948fa06d1e80a872c7495804979256e021e566ae0Wei Jiastatic const int kOverflowMarkMs    = 10000;  // 10 seconds
40641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih
412bfdd428c56c7524d1a11979f200a1762866032dAndreas HuberNuPlayer::RTSPSource::RTSPSource(
425ab368af38fefacc4009e3ab1c1bbd00e62b3bcfAndreas Huber        const sp<AMessage> &notify,
431b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        const sp<IMediaHTTPService> &httpService,
442bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        const char *url,
452bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        const KeyedVector<String8, String8> *headers,
462bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        bool uidValid,
4781dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        uid_t uid,
4881dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        bool isSDP)
495ab368af38fefacc4009e3ab1c1bbd00e62b3bcfAndreas Huber    : Source(notify),
501b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mHTTPService(httpService),
515ab368af38fefacc4009e3ab1c1bbd00e62b3bcfAndreas Huber      mURL(url),
522bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber      mUIDValid(uidValid),
532bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber      mUID(uid),
542bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber      mFlags(0),
5581dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé      mIsSDP(isSDP),
562bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber      mState(DISCONNECTED),
572bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber      mFinalResult(OK),
58ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber      mDisconnectReplyID(0),
59180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang      mBuffering(false),
60641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih      mInPreparationPhase(true),
61f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih      mEOSPending(false),
62cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson      mSeekGeneration(0),
63cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson      mEOSTimeoutAudio(0),
64cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson      mEOSTimeoutVideo(0) {
659bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia    mBufferingSettings.mInitialMarkMs = kPrepareMarkMs;
669bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia    mBufferingSettings.mResumePlaybackMarkMs = kOverflowMarkMs;
672bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    if (headers) {
682bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        mExtraHeaders = *headers;
692bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
702bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        ssize_t index =
712bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log"));
722bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
732bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        if (index >= 0) {
742bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            mFlags |= kFlagIncognito;
752bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
762bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            mExtraHeaders.removeItemsAt(index);
772bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        }
782bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
792bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber}
802bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
812bfdd428c56c7524d1a11979f200a1762866032dAndreas HuberNuPlayer::RTSPSource::~RTSPSource() {
82602f5bbd7596ec3fe447fde4329d5d4f0b370835Andreas Huber    if (mLooper != NULL) {
831228d6b175de8b21787cbe0c6c4bb5642f4d555eChong Zhang        mLooper->unregisterHandler(id());
84602f5bbd7596ec3fe447fde4329d5d4f0b370835Andreas Huber        mLooper->stop();
85602f5bbd7596ec3fe447fde4329d5d4f0b370835Andreas Huber    }
862bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber}
872bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
889bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jiastatus_t NuPlayer::RTSPSource::getBufferingSettings(
8948fa06d1e80a872c7495804979256e021e566ae0Wei Jia            BufferingSettings* buffering /* nonnull */) {
909bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia    Mutex::Autolock _l(mBufferingSettingsLock);
919bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia    *buffering = mBufferingSettings;
9248fa06d1e80a872c7495804979256e021e566ae0Wei Jia    return OK;
9348fa06d1e80a872c7495804979256e021e566ae0Wei Jia}
9448fa06d1e80a872c7495804979256e021e566ae0Wei Jia
9548fa06d1e80a872c7495804979256e021e566ae0Wei Jiastatus_t NuPlayer::RTSPSource::setBufferingSettings(const BufferingSettings& buffering) {
969bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia    Mutex::Autolock _l(mBufferingSettingsLock);
979bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia    mBufferingSettings = buffering;
989bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia    return OK;
9948fa06d1e80a872c7495804979256e021e566ae0Wei Jia}
10048fa06d1e80a872c7495804979256e021e566ae0Wei Jia
10157cea553cb19235553463412db5ad04c99835411Andreas Hubervoid NuPlayer::RTSPSource::prepareAsync() {
102ce84b2240497cd0923e190ae115e319e4c17d303Wei Jia    if (mIsSDP && mHTTPService == NULL) {
103ce84b2240497cd0923e190ae115e319e4c17d303Wei Jia        notifyPrepared(BAD_VALUE);
104ce84b2240497cd0923e190ae115e319e4c17d303Wei Jia        return;
105ce84b2240497cd0923e190ae115e319e4c17d303Wei Jia    }
106ce84b2240497cd0923e190ae115e319e4c17d303Wei Jia
1072bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    if (mLooper == NULL) {
1082bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        mLooper = new ALooper;
1092bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        mLooper->setName("rtsp");
1102bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        mLooper->start();
1112bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
1121228d6b175de8b21787cbe0c6c4bb5642f4d555eChong Zhang        mLooper->registerHandler(this);
1132bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
1142bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
1152bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    CHECK(mHandler == NULL);
11681dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé    CHECK(mSDPLoader == NULL);
1172bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
1181d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> notify = new AMessage(kWhatNotify, this);
1192bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
1202bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    CHECK_EQ(mState, (int)DISCONNECTED);
1212bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    mState = CONNECTING;
1222bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
12381dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé    if (mIsSDP) {
12481dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        mSDPLoader = new SDPLoader(notify,
12581dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                (mFlags & kFlagIncognito) ? SDPLoader::kFlagIncognito : 0,
12681e68448f3361eaf8618930471fdc3c21bdf5cbcAndreas Huber                mHTTPService);
12781dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
12857cea553cb19235553463412db5ad04c99835411Andreas Huber        mSDPLoader->load(
12957cea553cb19235553463412db5ad04c99835411Andreas Huber                mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
13081dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé    } else {
13181dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        mHandler = new MyHandler(mURL.c_str(), notify, mUIDValid, mUID);
13281dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        mLooper->registerHandler(mHandler);
13381dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
13481dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        mHandler->connect();
13581dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé    }
136cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson
137180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang    startBufferingIfNecessary();
13857cea553cb19235553463412db5ad04c99835411Andreas Huber}
13957cea553cb19235553463412db5ad04c99835411Andreas Huber
14057cea553cb19235553463412db5ad04c99835411Andreas Hubervoid NuPlayer::RTSPSource::start() {
1412bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber}
1422bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
1432bfdd428c56c7524d1a11979f200a1762866032dAndreas Hubervoid NuPlayer::RTSPSource::stop() {
1445834181d3f168acb8ff4bf3eff1fd1186afb0bd4James Dong    if (mLooper == NULL) {
1455834181d3f168acb8ff4bf3eff1fd1186afb0bd4James Dong        return;
1465834181d3f168acb8ff4bf3eff1fd1186afb0bd4James Dong    }
1471d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
1482bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
1492bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    sp<AMessage> dummy;
1502bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    msg->postAndAwaitResponse(&dummy);
1512bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber}
1522bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
1532bfdd428c56c7524d1a11979f200a1762866032dAndreas Huberstatus_t NuPlayer::RTSPSource::feedMoreTSData() {
154180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang    Mutex::Autolock _l(mBufferingLock);
1552bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    return mFinalResult;
1562bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber}
1572bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
158840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Hubersp<MetaData> NuPlayer::RTSPSource::getFormatMeta(bool audio) {
1592bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    sp<AnotherPacketSource> source = getSource(audio);
1602bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
1612bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    if (source == NULL) {
1622bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        return NULL;
1632bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
1642bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
1652bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    return source->getFormat();
1662bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber}
1672bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
168bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huberbool NuPlayer::RTSPSource::haveSufficientDataOnAllTracks() {
169bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber    // We're going to buffer at least 2 secs worth data on all tracks before
170bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber    // starting playback (both at startup and after a seek).
171bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber
172bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber    static const int64_t kMinDurationUs = 2000000ll;
173bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber
174cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson    int64_t mediaDurationUs = 0;
175cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson    getDuration(&mediaDurationUs);
176cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson    if ((mAudioTrack != NULL && mAudioTrack->isFinished(mediaDurationUs))
177cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson            || (mVideoTrack != NULL && mVideoTrack->isFinished(mediaDurationUs))) {
178cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson        return true;
179cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson    }
180cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson
181bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber    status_t err;
182bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber    int64_t durationUs;
183bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber    if (mAudioTrack != NULL
184bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber            && (durationUs = mAudioTrack->getBufferedDurationUs(&err))
185bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber                    < kMinDurationUs
186bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber            && err == OK) {
187bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber        ALOGV("audio track doesn't have enough data yet. (%.2f secs buffered)",
188bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber              durationUs / 1E6);
189bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber        return false;
190bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber    }
191bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber
192bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber    if (mVideoTrack != NULL
193bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber            && (durationUs = mVideoTrack->getBufferedDurationUs(&err))
194bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber                    < kMinDurationUs
195bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber            && err == OK) {
196bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber        ALOGV("video track doesn't have enough data yet. (%.2f secs buffered)",
197bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber              durationUs / 1E6);
198bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber        return false;
199bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber    }
200bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber
201bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber    return true;
202bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber}
203bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber
2042bfdd428c56c7524d1a11979f200a1762866032dAndreas Huberstatus_t NuPlayer::RTSPSource::dequeueAccessUnit(
2052bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        bool audio, sp<ABuffer> *accessUnit) {
206180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang    if (!stopBufferingIfNecessary()) {
207180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang        return -EWOULDBLOCK;
208bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber    }
209bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber
2102bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    sp<AnotherPacketSource> source = getSource(audio);
2112bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
2122bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    if (source == NULL) {
2132bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        return -EWOULDBLOCK;
2142bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
2152bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
2162bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    status_t finalResult;
2172bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    if (!source->hasBufferAvailable(&finalResult)) {
218cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson        if (finalResult == OK) {
219f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih
220f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih            // If other source already signaled EOS, this source should also return EOS
221f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih            if (sourceReachedEOS(!audio)) {
222cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson                return ERROR_END_OF_STREAM;
223cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson            }
224cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson
225cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson            // If this source has detected near end, give it some time to retrieve more
226f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih            // data before returning EOS
227f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih            int64_t mediaDurationUs = 0;
228f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih            getDuration(&mediaDurationUs);
229cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson            if (source->isFinished(mediaDurationUs)) {
230cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson                int64_t eosTimeout = audio ? mEOSTimeoutAudio : mEOSTimeoutVideo;
231cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson                if (eosTimeout == 0) {
232cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson                    setEOSTimeout(audio, ALooper::GetNowUs());
233cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson                } else if ((ALooper::GetNowUs() - eosTimeout) > kNearEOSTimeoutUs) {
234cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson                    setEOSTimeout(audio, 0);
235cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson                    return ERROR_END_OF_STREAM;
236cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson                }
237cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson                return -EWOULDBLOCK;
238cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson            }
239cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson
240f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih            if (!sourceNearEOS(!audio)) {
241cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson                // We should not enter buffering mode
242cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson                // if any of the sources already have detected EOS.
243180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang                startBufferingIfNecessary();
244cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson            }
245cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson
246cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson            return -EWOULDBLOCK;
247cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson        }
248cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson        return finalResult;
2492bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
2502bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
251cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson    setEOSTimeout(audio, 0);
252cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson
2532bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    return source->dequeueAccessUnit(accessUnit);
2542bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber}
2552bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
2562bfdd428c56c7524d1a11979f200a1762866032dAndreas Hubersp<AnotherPacketSource> NuPlayer::RTSPSource::getSource(bool audio) {
25749694688c82214f5fd9e969e177c9e126a240a26Andreas Huber    if (mTSParser != NULL) {
25849694688c82214f5fd9e969e177c9e126a240a26Andreas Huber        sp<MediaSource> source = mTSParser->getSource(
25949694688c82214f5fd9e969e177c9e126a240a26Andreas Huber                audio ? ATSParser::AUDIO : ATSParser::VIDEO);
26049694688c82214f5fd9e969e177c9e126a240a26Andreas Huber
26149694688c82214f5fd9e969e177c9e126a240a26Andreas Huber        return static_cast<AnotherPacketSource *>(source.get());
26249694688c82214f5fd9e969e177c9e126a240a26Andreas Huber    }
26349694688c82214f5fd9e969e177c9e126a240a26Andreas Huber
2642bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    return audio ? mAudioTrack : mVideoTrack;
2652bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber}
2662bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
267cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönssonvoid NuPlayer::RTSPSource::setEOSTimeout(bool audio, int64_t timeout) {
268cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson    if (audio) {
269cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson        mEOSTimeoutAudio = timeout;
270cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson    } else {
271cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson        mEOSTimeoutVideo = timeout;
272cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson    }
273cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson}
274cfc3083927df14bf82403b20a45ae303a01c39f5Roger Jönsson
2752bfdd428c56c7524d1a11979f200a1762866032dAndreas Huberstatus_t NuPlayer::RTSPSource::getDuration(int64_t *durationUs) {
2767e074a8b7548ac769d1f55addacd97f885651b0dRobert Shih    *durationUs = -1ll;
2772bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
2782bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    int64_t audioDurationUs;
2792bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    if (mAudioTrack != NULL
2802bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            && mAudioTrack->getFormat()->findInt64(
2812bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                kKeyDuration, &audioDurationUs)
2822bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            && audioDurationUs > *durationUs) {
2832bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        *durationUs = audioDurationUs;
2842bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
2852bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
2862bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    int64_t videoDurationUs;
2872bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    if (mVideoTrack != NULL
2882bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            && mVideoTrack->getFormat()->findInt64(
2892bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                kKeyDuration, &videoDurationUs)
2902bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            && videoDurationUs > *durationUs) {
2912bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        *durationUs = videoDurationUs;
2922bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
2932bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
2942bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    return OK;
2952bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber}
2962bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
297c5de09127e9e0d5df7aa587be317e1487d793245Wei Jiastatus_t NuPlayer::RTSPSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
2981d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatPerformSeek, this);
299ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber    msg->setInt32("generation", ++mSeekGeneration);
300ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber    msg->setInt64("timeUs", seekTimeUs);
301c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia    msg->setInt32("mode", mode);
302ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber
3038d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih    sp<AMessage> response;
3048d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih    status_t err = msg->postAndAwaitResponse(&response);
3058d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih    if (err == OK && response != NULL) {
3068d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih        CHECK(response->findInt32("err", &err));
3078d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih    }
3088d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih
3098d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih    return err;
310ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber}
311ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber
312ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Hubervoid NuPlayer::RTSPSource::performSeek(int64_t seekTimeUs) {
3132bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    if (mState != CONNECTED) {
3148d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih        finishSeek(INVALID_OPERATION);
315ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber        return;
3162bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
3172bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
3182bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    mState = SEEKING;
3192bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    mHandler->seek(seekTimeUs);
320f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    mEOSPending = false;
3212bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber}
3222bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
323641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shihvoid NuPlayer::RTSPSource::schedulePollBuffering() {
324641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih    sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
325641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih    msg->post(1000000ll); // 1 second intervals
326641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih}
327641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih
328641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shihvoid NuPlayer::RTSPSource::checkBuffering(
329f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih        bool *prepared, bool *underflow, bool *overflow, bool *startServer, bool *finished) {
330641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih    size_t numTracks = mTracks.size();
331f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    size_t preparedCount, underflowCount, overflowCount, startCount, finishedCount;
332f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    preparedCount = underflowCount = overflowCount = startCount = finishedCount = 0;
333c622c584ea0ffb807eb9f711aa30016eae069c92Takahiro Aizawa
334c622c584ea0ffb807eb9f711aa30016eae069c92Takahiro Aizawa    size_t count = numTracks;
335c622c584ea0ffb807eb9f711aa30016eae069c92Takahiro Aizawa    for (size_t i = 0; i < count; ++i) {
336641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih        status_t finalResult;
337641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih        TrackInfo *info = &mTracks.editItemAt(i);
338641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih        sp<AnotherPacketSource> src = info->mSource;
339c622c584ea0ffb807eb9f711aa30016eae069c92Takahiro Aizawa        if (src == NULL) {
340c622c584ea0ffb807eb9f711aa30016eae069c92Takahiro Aizawa            --numTracks;
341c622c584ea0ffb807eb9f711aa30016eae069c92Takahiro Aizawa            continue;
342c622c584ea0ffb807eb9f711aa30016eae069c92Takahiro Aizawa        }
343641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih        int64_t bufferedDurationUs = src->getBufferedDurationUs(&finalResult);
344641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih
3459bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia        int64_t initialMarkUs;
3469bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia        int64_t maxRebufferingMarkUs;
3479bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia        {
3489bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia            Mutex::Autolock _l(mBufferingSettingsLock);
3499bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia            initialMarkUs = mBufferingSettings.mInitialMarkMs * 1000ll;
3509bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia            // TODO: maxRebufferingMarkUs could be larger than
3519bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia            // mBufferingSettings.mResumePlaybackMarkMs * 1000ll.
3529bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia            maxRebufferingMarkUs = mBufferingSettings.mResumePlaybackMarkMs * 1000ll;
3539bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia        }
354641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih        // isFinished when duration is 0 checks for EOS result only
3559bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia        if (bufferedDurationUs > initialMarkUs
35648fa06d1e80a872c7495804979256e021e566ae0Wei Jia                || src->isFinished(/* duration */ 0)) {
357641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih            ++preparedCount;
358641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih        }
359641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih
360641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih        if (src->isFinished(/* duration */ 0)) {
361641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih            ++overflowCount;
362f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih            ++finishedCount;
363641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih        } else {
3649bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia            // TODO: redefine kUnderflowMarkMs to a fair value,
3659bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia            if (bufferedDurationUs < kUnderflowMarkMs * 1000) {
366641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih                ++underflowCount;
367641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih            }
3689bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia            if (bufferedDurationUs > maxRebufferingMarkUs) {
369641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih                ++overflowCount;
370641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih            }
37148fa06d1e80a872c7495804979256e021e566ae0Wei Jia            int64_t startServerMarkUs =
3729bb3803a80a680ea7a3bc11e07b8a89ccddee003Wei Jia                    (kUnderflowMarkMs * 1000ll + maxRebufferingMarkUs) / 2;
37348fa06d1e80a872c7495804979256e021e566ae0Wei Jia            if (bufferedDurationUs < startServerMarkUs) {
374641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih                ++startCount;
375641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih            }
376641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih        }
377641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih    }
378641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih
379641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih    *prepared    = (preparedCount == numTracks);
380641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih    *underflow   = (underflowCount > 0);
381641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih    *overflow    = (overflowCount == numTracks);
382641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih    *startServer = (startCount > 0);
383f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    *finished    = (finishedCount > 0);
384641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih}
385641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih
386641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shihvoid NuPlayer::RTSPSource::onPollBuffering() {
387f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    bool prepared, underflow, overflow, startServer, finished;
388f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    checkBuffering(&prepared, &underflow, &overflow, &startServer, &finished);
389641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih
390641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih    if (prepared && mInPreparationPhase) {
391641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih        mInPreparationPhase = false;
392641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih        notifyPrepared();
393641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih    }
394641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih
395641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih    if (!mInPreparationPhase && underflow) {
396641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih        startBufferingIfNecessary();
397641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih    }
398641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih
39991ea571836401ba77854d7b3aefb3ccee9c20eb3Robert Shih    if (haveSufficientDataOnAllTracks()) {
400641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih        stopBufferingIfNecessary();
40191ea571836401ba77854d7b3aefb3ccee9c20eb3Robert Shih    }
40291ea571836401ba77854d7b3aefb3ccee9c20eb3Robert Shih
40391ea571836401ba77854d7b3aefb3ccee9c20eb3Robert Shih    if (overflow && mHandler != NULL) {
404641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih        mHandler->pause();
405641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih    }
406641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih
407641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih    if (startServer && mHandler != NULL) {
408641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih        mHandler->resume();
409641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih    }
410641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih
411f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    if (finished && mHandler != NULL) {
412f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih        mHandler->cancelAccessUnitTimeoutCheck();
413f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    }
414f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih
415641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih    schedulePollBuffering();
416641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih}
417641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih
418f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shihvoid NuPlayer::RTSPSource::signalSourceEOS(status_t result) {
419f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    const bool audio = true;
420f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    const bool video = false;
421f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih
422f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    sp<AnotherPacketSource> source = getSource(audio);
423f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    if (source != NULL) {
424f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih        source->signalEOS(result);
425f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    }
426f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih
427f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    source = getSource(video);
428f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    if (source != NULL) {
429f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih        source->signalEOS(result);
430f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    }
431f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih}
432f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih
433f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shihbool NuPlayer::RTSPSource::sourceReachedEOS(bool audio) {
434f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    sp<AnotherPacketSource> source = getSource(audio);
435f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    status_t finalResult;
436f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    return (source != NULL &&
437f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih            !source->hasBufferAvailable(&finalResult) &&
438f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih            finalResult == ERROR_END_OF_STREAM);
439f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih}
440f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih
441f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shihbool NuPlayer::RTSPSource::sourceNearEOS(bool audio) {
442f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    sp<AnotherPacketSource> source = getSource(audio);
443f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    int64_t mediaDurationUs = 0;
444f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    getDuration(&mediaDurationUs);
445f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    return (source != NULL && source->isFinished(mediaDurationUs));
446f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih}
447f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih
448f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shihvoid NuPlayer::RTSPSource::onSignalEOS(const sp<AMessage> &msg) {
449f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    int32_t generation;
450f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    CHECK(msg->findInt32("generation", &generation));
451f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih
452f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    if (generation != mSeekGeneration) {
453f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih        return;
454f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    }
455f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih
456f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    if (mEOSPending) {
457f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih        signalSourceEOS(ERROR_END_OF_STREAM);
458f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih        mEOSPending = false;
459f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    }
460f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih}
461f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih
462f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shihvoid NuPlayer::RTSPSource::postSourceEOSIfNecessary() {
463f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    const bool audio = true;
464f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    const bool video = false;
465f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    // If a source has detected near end, give it some time to retrieve more
466f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    // data before signaling EOS
467f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    if (sourceNearEOS(audio) || sourceNearEOS(video)) {
468f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih        if (!mEOSPending) {
469f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih            sp<AMessage> msg = new AMessage(kWhatSignalEOS, this);
470f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih            msg->setInt32("generation", mSeekGeneration);
471f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih            msg->post(kNearEOSTimeoutUs);
472f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih            mEOSPending = true;
473f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih        }
474f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    }
475f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih}
476f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih
4772bfdd428c56c7524d1a11979f200a1762866032dAndreas Hubervoid NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
4782bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    if (msg->what() == kWhatDisconnect) {
4793f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar        sp<AReplyToken> replyID;
4802bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        CHECK(msg->senderAwaitsResponse(&replyID));
4812bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
4822bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        mDisconnectReplyID = replyID;
4832bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        finishDisconnectIfPossible();
4842bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        return;
485ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber    } else if (msg->what() == kWhatPerformSeek) {
486ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber        int32_t generation;
487ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber        CHECK(msg->findInt32("generation", &generation));
4888d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih        CHECK(msg->senderAwaitsResponse(&mSeekReplyID));
489ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber
490ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber        if (generation != mSeekGeneration) {
491ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber            // obsolete.
4928d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih            finishSeek(OK);
493ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber            return;
494ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber        }
495ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber
496ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber        int64_t seekTimeUs;
497c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia        int32_t mode;
498ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber        CHECK(msg->findInt64("timeUs", &seekTimeUs));
499c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia        CHECK(msg->findInt32("mode", &mode));
500ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber
501c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia        // TODO: add "mode" to performSeek.
502c5de09127e9e0d5df7aa587be317e1487d793245Wei Jia        performSeek(seekTimeUs/*, (MediaPlayerSeekMode)mode */);
503ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber        return;
504641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih    } else if (msg->what() == kWhatPollBuffering) {
505641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih        onPollBuffering();
506641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih        return;
507f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih    } else if (msg->what() == kWhatSignalEOS) {
508f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih        onSignalEOS(msg);
509f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih        return;
5102bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
5112bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
512b8c35f94470d1518e2def0582aaec4e038c92af0Colin Cross    CHECK_EQ(msg->what(), kWhatNotify);
5132bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
5142bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    int32_t what;
5152bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    CHECK(msg->findInt32("what", &what));
5162bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
5172bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    switch (what) {
5182bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        case MyHandler::kWhatConnected:
5197f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber        {
5202bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            onConnected();
5217f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber
522ced1c2f8f6c422063092f5cc5c675ccdebb2dc10Chong Zhang            notifyVideoSizeChanged();
5237f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber
5247f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber            uint32_t flags = 0;
5257f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber
5267f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber            if (mHandler->isSeekable()) {
5274b7069dac546ad21cf62ca6132d50ea41857d08eChong Zhang                flags = FLAG_CAN_PAUSE
5284b7069dac546ad21cf62ca6132d50ea41857d08eChong Zhang                        | FLAG_CAN_SEEK
5294b7069dac546ad21cf62ca6132d50ea41857d08eChong Zhang                        | FLAG_CAN_SEEK_BACKWARD
5304b7069dac546ad21cf62ca6132d50ea41857d08eChong Zhang                        | FLAG_CAN_SEEK_FORWARD;
5317f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber            }
5327f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber
5337f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber            notifyFlagsChanged(flags);
534641e0c718da1c58e5b89379f60465c4e564ebb73Robert Shih            schedulePollBuffering();
5352bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            break;
5367f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber        }
5372bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
5382bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        case MyHandler::kWhatDisconnected:
5397f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber        {
5402bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            onDisconnected(msg);
5412bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            break;
5427f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber        }
5432bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
5442bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        case MyHandler::kWhatSeekDone:
5452bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        {
5462bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            mState = CONNECTED;
5474ad74b2b4507c8b2714b7b7584578d2d43ae2633Wei Jia            // Unblock seekTo here in case we attempted to seek in a live stream
5484ad74b2b4507c8b2714b7b7584578d2d43ae2633Wei Jia            finishSeek(OK);
5498d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih            break;
5508d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih        }
5518d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih
5528d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih        case MyHandler::kWhatSeekPaused:
5538d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih        {
5548d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih            sp<AnotherPacketSource> source = getSource(true /* audio */);
5558d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih            if (source != NULL) {
5568d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih                source->queueDiscontinuity(ATSParser::DISCONTINUITY_NONE,
5578d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih                        /* extra */ NULL,
5588d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih                        /* discard */ true);
5598d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih            }
5608d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih            source = getSource(false /* video */);
5618d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih            if (source != NULL) {
5628d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih                source->queueDiscontinuity(ATSParser::DISCONTINUITY_NONE,
5638d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih                        /* extra */ NULL,
5648d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih                        /* discard */ true);
5658d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih            };
5668d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih
5678d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih            status_t err = OK;
5688d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih            msg->findInt32("err", &err);
5698d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih
5708d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih            if (err == OK) {
5718d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih                int64_t timeUs;
5728d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih                CHECK(msg->findInt64("time", &timeUs));
5738d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih                mHandler->continueSeekAfterPause(timeUs);
5744ad74b2b4507c8b2714b7b7584578d2d43ae2633Wei Jia            } else {
5754ad74b2b4507c8b2714b7b7584578d2d43ae2633Wei Jia                finishSeek(err);
5768d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih            }
5772bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            break;
5782bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        }
5792bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
5802bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        case MyHandler::kWhatAccessUnit:
5812bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        {
5822bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            size_t trackIndex;
5832bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            CHECK(msg->findSize("trackIndex", &trackIndex));
58449694688c82214f5fd9e969e177c9e126a240a26Andreas Huber
58549694688c82214f5fd9e969e177c9e126a240a26Andreas Huber            if (mTSParser == NULL) {
58649694688c82214f5fd9e969e177c9e126a240a26Andreas Huber                CHECK_LT(trackIndex, mTracks.size());
58749694688c82214f5fd9e969e177c9e126a240a26Andreas Huber            } else {
58849694688c82214f5fd9e969e177c9e126a240a26Andreas Huber                CHECK_EQ(trackIndex, 0u);
58949694688c82214f5fd9e969e177c9e126a240a26Andreas Huber            }
5902bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
5912d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber            sp<ABuffer> accessUnit;
5922d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber            CHECK(msg->findBuffer("accessUnit", &accessUnit));
5932bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
5942bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            int32_t damaged;
5952bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            if (accessUnit->meta()->findInt32("damaged", &damaged)
5962bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                    && damaged) {
597df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block                ALOGI("dropping damaged access unit.");
5982bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                break;
5992bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            }
6002bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
60149694688c82214f5fd9e969e177c9e126a240a26Andreas Huber            if (mTSParser != NULL) {
60249694688c82214f5fd9e969e177c9e126a240a26Andreas Huber                size_t offset = 0;
60349694688c82214f5fd9e969e177c9e126a240a26Andreas Huber                status_t err = OK;
60449694688c82214f5fd9e969e177c9e126a240a26Andreas Huber                while (offset + 188 <= accessUnit->size()) {
60549694688c82214f5fd9e969e177c9e126a240a26Andreas Huber                    err = mTSParser->feedTSPacket(
60649694688c82214f5fd9e969e177c9e126a240a26Andreas Huber                            accessUnit->data() + offset, 188);
60749694688c82214f5fd9e969e177c9e126a240a26Andreas Huber                    if (err != OK) {
60849694688c82214f5fd9e969e177c9e126a240a26Andreas Huber                        break;
60949694688c82214f5fd9e969e177c9e126a240a26Andreas Huber                    }
61049694688c82214f5fd9e969e177c9e126a240a26Andreas Huber
61149694688c82214f5fd9e969e177c9e126a240a26Andreas Huber                    offset += 188;
61249694688c82214f5fd9e969e177c9e126a240a26Andreas Huber                }
61349694688c82214f5fd9e969e177c9e126a240a26Andreas Huber
61449694688c82214f5fd9e969e177c9e126a240a26Andreas Huber                if (offset < accessUnit->size()) {
61549694688c82214f5fd9e969e177c9e126a240a26Andreas Huber                    err = ERROR_MALFORMED;
61649694688c82214f5fd9e969e177c9e126a240a26Andreas Huber                }
61749694688c82214f5fd9e969e177c9e126a240a26Andreas Huber
61849694688c82214f5fd9e969e177c9e126a240a26Andreas Huber                if (err != OK) {
619f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih                    signalSourceEOS(err);
62049694688c82214f5fd9e969e177c9e126a240a26Andreas Huber                }
621f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih
622f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih                postSourceEOSIfNecessary();
62349694688c82214f5fd9e969e177c9e126a240a26Andreas Huber                break;
62449694688c82214f5fd9e969e177c9e126a240a26Andreas Huber            }
62549694688c82214f5fd9e969e177c9e126a240a26Andreas Huber
6261906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber            TrackInfo *info = &mTracks.editItemAt(trackIndex);
6271906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber
6281906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber            sp<AnotherPacketSource> source = info->mSource;
6292bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            if (source != NULL) {
6302bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                uint32_t rtpTime;
6312bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
6322bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
6331906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber                if (!info->mNPTMappingValid) {
6341906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber                    // This is a live stream, we didn't receive any normal
635c9d1696d214d2175327067ccc1991bcb36976404Andreas Huber                    // playtime mapping. We won't map to npt time.
636c9d1696d214d2175327067ccc1991bcb36976404Andreas Huber                    source->queueAccessUnit(accessUnit);
637c9d1696d214d2175327067ccc1991bcb36976404Andreas Huber                    break;
6381906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber                }
6391906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber
6402bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                int64_t nptUs =
6411906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber                    ((double)rtpTime - (double)info->mRTPTime)
6421906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber                        / info->mTimeScale
6432bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                        * 1000000ll
6441906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber                        + info->mNormalPlaytimeUs;
6452bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
6462bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                accessUnit->meta()->setInt64("timeUs", nptUs);
6472bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
6482bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                source->queueAccessUnit(accessUnit);
6492bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            }
650f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih            postSourceEOSIfNecessary();
6512bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            break;
6522bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        }
6532bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
6542bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        case MyHandler::kWhatEOS:
6552bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        {
6562bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            int32_t finalResult;
6572bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            CHECK(msg->findInt32("finalResult", &finalResult));
6582bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            CHECK_NE(finalResult, (status_t)OK);
6592bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
66049694688c82214f5fd9e969e177c9e126a240a26Andreas Huber            if (mTSParser != NULL) {
661f1d261f1b5914ddc219a23b763ab19363eeedd85Robert Shih                signalSourceEOS(finalResult);
66249694688c82214f5fd9e969e177c9e126a240a26Andreas Huber            }
66349694688c82214f5fd9e969e177c9e126a240a26Andreas Huber
66449694688c82214f5fd9e969e177c9e126a240a26Andreas Huber            size_t trackIndex;
66549694688c82214f5fd9e969e177c9e126a240a26Andreas Huber            CHECK(msg->findSize("trackIndex", &trackIndex));
66649694688c82214f5fd9e969e177c9e126a240a26Andreas Huber            CHECK_LT(trackIndex, mTracks.size());
66749694688c82214f5fd9e969e177c9e126a240a26Andreas Huber
6682bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            TrackInfo *info = &mTracks.editItemAt(trackIndex);
6692bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            sp<AnotherPacketSource> source = info->mSource;
6702bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            if (source != NULL) {
6712bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                source->signalEOS(finalResult);
6722bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            }
6732bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
6742bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            break;
6752bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        }
6762bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
6772bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        case MyHandler::kWhatSeekDiscontinuity:
6782bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        {
6792bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            size_t trackIndex;
6802bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            CHECK(msg->findSize("trackIndex", &trackIndex));
6812bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            CHECK_LT(trackIndex, mTracks.size());
6822bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
6832bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            TrackInfo *info = &mTracks.editItemAt(trackIndex);
6842bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            sp<AnotherPacketSource> source = info->mSource;
6852bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            if (source != NULL) {
686632740c58119a132ce19f6d498e39c5c3773971aChong Zhang                source->queueDiscontinuity(
687fef808d42a9c94b0b5ef3c3d5fb0a090edbc42daWei Jia                        ATSParser::DISCONTINUITY_TIME,
688632740c58119a132ce19f6d498e39c5c3773971aChong Zhang                        NULL,
689632740c58119a132ce19f6d498e39c5c3773971aChong Zhang                        true /* discard */);
6902bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            }
6912bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
6922bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            break;
6932bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        }
6942bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
6952bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        case MyHandler::kWhatNormalPlayTimeMapping:
6962bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        {
6972bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            size_t trackIndex;
6982bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            CHECK(msg->findSize("trackIndex", &trackIndex));
6992bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            CHECK_LT(trackIndex, mTracks.size());
7002bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
7012bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            uint32_t rtpTime;
7022bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            CHECK(msg->findInt32("rtpTime", (int32_t *)&rtpTime));
7032bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
7042bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            int64_t nptUs;
7052bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            CHECK(msg->findInt64("nptUs", &nptUs));
7062bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
7072bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            TrackInfo *info = &mTracks.editItemAt(trackIndex);
7082bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            info->mRTPTime = rtpTime;
7092bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            info->mNormalPlaytimeUs = nptUs;
7101906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber            info->mNPTMappingValid = true;
7112bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            break;
7122bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        }
7132bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
71481dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        case SDPLoader::kWhatSDPLoaded:
71581dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        {
71681dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé            onSDPLoaded(msg);
71781dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé            break;
71881dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        }
71981dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
7202bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        default:
7212bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            TRESPASS();
7222bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
7232bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber}
7242bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
7252bfdd428c56c7524d1a11979f200a1762866032dAndreas Hubervoid NuPlayer::RTSPSource::onConnected() {
7262bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    CHECK(mAudioTrack == NULL);
7272bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    CHECK(mVideoTrack == NULL);
7282bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
7292bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    size_t numTracks = mHandler->countTracks();
7302bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    for (size_t i = 0; i < numTracks; ++i) {
7312bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        int32_t timeScale;
7322bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        sp<MetaData> format = mHandler->getTrackFormat(i, &timeScale);
7332bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
7342bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        const char *mime;
7352bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        CHECK(format->findCString(kKeyMIMEType, &mime));
7362bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
73749694688c82214f5fd9e969e177c9e126a240a26Andreas Huber        if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
73849694688c82214f5fd9e969e177c9e126a240a26Andreas Huber            // Very special case for MPEG2 Transport Streams.
73949694688c82214f5fd9e969e177c9e126a240a26Andreas Huber            CHECK_EQ(numTracks, 1u);
74049694688c82214f5fd9e969e177c9e126a240a26Andreas Huber
74149694688c82214f5fd9e969e177c9e126a240a26Andreas Huber            mTSParser = new ATSParser;
74249694688c82214f5fd9e969e177c9e126a240a26Andreas Huber            return;
74349694688c82214f5fd9e969e177c9e126a240a26Andreas Huber        }
74449694688c82214f5fd9e969e177c9e126a240a26Andreas Huber
7452bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        bool isAudio = !strncasecmp(mime, "audio/", 6);
7462bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        bool isVideo = !strncasecmp(mime, "video/", 6);
7472bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
7482bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        TrackInfo info;
7492bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        info.mTimeScale = timeScale;
7502bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        info.mRTPTime = 0;
7512bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        info.mNormalPlaytimeUs = 0ll;
7521906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber        info.mNPTMappingValid = false;
7532bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
7542bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        if ((isAudio && mAudioTrack == NULL)
7552bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                || (isVideo && mVideoTrack == NULL)) {
7562bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            sp<AnotherPacketSource> source = new AnotherPacketSource(format);
7572bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
7582bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            if (isAudio) {
7592bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                mAudioTrack = source;
7602bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            } else {
7612bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                mVideoTrack = source;
7622bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            }
7632bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
7642bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            info.mSource = source;
7652bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        }
7662bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
7672bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        mTracks.push(info);
7682bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
7692bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
7702bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    mState = CONNECTED;
7712bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber}
7722bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
77381dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhévoid NuPlayer::RTSPSource::onSDPLoaded(const sp<AMessage> &msg) {
77481dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé    status_t err;
77581dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé    CHECK(msg->findInt32("result", &err));
77681dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
77781dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé    mSDPLoader.clear();
77881dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
77981dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé    if (mDisconnectReplyID != 0) {
78081dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        err = UNKNOWN_ERROR;
78181dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé    }
78281dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
78381dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé    if (err == OK) {
78481dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        sp<ASessionDescription> desc;
78581dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        sp<RefBase> obj;
78681dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        CHECK(msg->findObject("description", &obj));
78781dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        desc = static_cast<ASessionDescription *>(obj.get());
78881dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
78981dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        AString rtspUri;
79081dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        if (!desc->findAttribute(0, "a=control", &rtspUri)) {
79181dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé            ALOGE("Unable to find url in SDP");
79281dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé            err = UNKNOWN_ERROR;
79381dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        } else {
7941d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar            sp<AMessage> notify = new AMessage(kWhatNotify, this);
79581dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
79681dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé            mHandler = new MyHandler(rtspUri.c_str(), notify, mUIDValid, mUID);
79781dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé            mLooper->registerHandler(mHandler);
79881dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
79981dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé            mHandler->loadSDP(desc);
80081dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        }
80181dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé    }
80281dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
80381dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé    if (err != OK) {
8047f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber        if (mState == CONNECTING) {
8057f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber            // We're still in the preparation phase, signal that it
8067f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber            // failed.
8077f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber            notifyPrepared(err);
8087f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber        }
8097f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber
81081dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        mState = DISCONNECTED;
811180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang        setError(err);
81281dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
81381dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        if (mDisconnectReplyID != 0) {
81481dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé            finishDisconnectIfPossible();
81581dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        }
81681dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé    }
81781dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé}
81881dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
8192bfdd428c56c7524d1a11979f200a1762866032dAndreas Hubervoid NuPlayer::RTSPSource::onDisconnected(const sp<AMessage> &msg) {
8200ad03bc59d090a0455f858d2f629834c105f6f37Fredrik Rosin    if (mState == DISCONNECTED) {
8210ad03bc59d090a0455f858d2f629834c105f6f37Fredrik Rosin        return;
8220ad03bc59d090a0455f858d2f629834c105f6f37Fredrik Rosin    }
8230ad03bc59d090a0455f858d2f629834c105f6f37Fredrik Rosin
8242bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    status_t err;
8252bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    CHECK(msg->findInt32("result", &err));
8262bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    CHECK_NE(err, (status_t)OK);
8272bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
8282bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    mLooper->unregisterHandler(mHandler->id());
8292bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    mHandler.clear();
8302bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
8317f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber    if (mState == CONNECTING) {
8327f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber        // We're still in the preparation phase, signal that it
8337f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber        // failed.
8347f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber        notifyPrepared(err);
8357f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber    }
8367f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber
8372bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    mState = DISCONNECTED;
838180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang    setError(err);
8392bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
8402bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    if (mDisconnectReplyID != 0) {
8412bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        finishDisconnectIfPossible();
8422bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
8432bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber}
8442bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
8452bfdd428c56c7524d1a11979f200a1762866032dAndreas Hubervoid NuPlayer::RTSPSource::finishDisconnectIfPossible() {
8462bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    if (mState != DISCONNECTED) {
84781dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        if (mHandler != NULL) {
84881dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé            mHandler->disconnect();
84981dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        } else if (mSDPLoader != NULL) {
85081dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé            mSDPLoader->cancel();
85181dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        }
8522bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        return;
8532bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
8542bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
8552bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    (new AMessage)->postReply(mDisconnectReplyID);
8562bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    mDisconnectReplyID = 0;
8572bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber}
8582bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
859180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhangvoid NuPlayer::RTSPSource::setError(status_t err) {
860180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang    Mutex::Autolock _l(mBufferingLock);
861180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang    mFinalResult = err;
862180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang}
863180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang
864180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhangvoid NuPlayer::RTSPSource::startBufferingIfNecessary() {
865180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang    Mutex::Autolock _l(mBufferingLock);
866180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang
867180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang    if (!mBuffering) {
868180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang        mBuffering = true;
869180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang
870180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang        sp<AMessage> notify = dupNotify();
871c9ff2009a0a010eeaba80d76493fbf33fcb561c8Wei Jia        notify->setInt32("what", kWhatPauseOnBufferingStart);
872180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang        notify->post();
873180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang    }
874180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang}
875180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang
876180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhangbool NuPlayer::RTSPSource::stopBufferingIfNecessary() {
877180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang    Mutex::Autolock _l(mBufferingLock);
878180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang
879180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang    if (mBuffering) {
880180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang        if (!haveSufficientDataOnAllTracks()) {
881180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang            return false;
882180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang        }
883180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang
884180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang        mBuffering = false;
885180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang
886180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang        sp<AMessage> notify = dupNotify();
887c9ff2009a0a010eeaba80d76493fbf33fcb561c8Wei Jia        notify->setInt32("what", kWhatResumeOnBufferingEnd);
888180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang        notify->post();
889180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang    }
890180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang
891180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang    return true;
892180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang}
893180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang
8948d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shihvoid NuPlayer::RTSPSource::finishSeek(status_t err) {
8954ad74b2b4507c8b2714b7b7584578d2d43ae2633Wei Jia    if (mSeekReplyID == NULL) {
8964ad74b2b4507c8b2714b7b7584578d2d43ae2633Wei Jia        return;
8974ad74b2b4507c8b2714b7b7584578d2d43ae2633Wei Jia    }
8988d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih    sp<AMessage> seekReply = new AMessage;
8998d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih    seekReply->setInt32("err", err);
9008d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih    seekReply->postReply(mSeekReplyID);
9018d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih    mSeekReplyID = NULL;
9028d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih}
903180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang
9042bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber}  // namespace android
905