MyHandler.h revision e56121bc4cb29c91d736eab181b1f51c4f125e78
1cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber/*
2cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * Copyright (C) 2010 The Android Open Source Project
3cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber *
4cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * you may not use this file except in compliance with the License.
6cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * You may obtain a copy of the License at
7cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber *
8cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber *
10cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * Unless required by applicable law or agreed to in writing, software
11cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * See the License for the specific language governing permissions and
14cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * limitations under the License.
15cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber */
16cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
17cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#ifndef MY_HANDLER_H_
18cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
19cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#define MY_HANDLER_H_
20cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
21cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "APacketSource.h"
22cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "ARTPConnection.h"
23cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "ARTSPConnection.h"
24cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "ASessionDescription.h"
25cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
268d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber#include <ctype.h>
278d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
28cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
29cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ADebug.h>
30cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ALooper.h>
31cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/AMessage.h>
32cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/MediaErrors.h>
33cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
340792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber#define USE_TCP_INTERLEAVED     0
350792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
36e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber// If no access units are received within 3 secs, assume that the rtp
37e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber// stream has ended and signal end of stream.
38e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huberstatic int64_t kAccessUnitTimeoutUs = 3000000ll;
39e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber
40e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber// If no access units arrive for the first 10 secs after starting the
41e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber// stream, assume none ever will and signal EOS or switch transports.
42e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huberstatic int64_t kStartupTimeoutUs = 10000000ll;
43e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber
44cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubernamespace android {
45cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
468d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huberstatic bool GetAttribute(const char *s, const char *key, AString *value) {
478d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    value->clear();
488d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
498d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    size_t keyLen = strlen(key);
508d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
518d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    for (;;) {
528d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        while (isspace(*s)) {
538d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            ++s;
548d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        }
558d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
568d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        const char *colonPos = strchr(s, ';');
578d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
588d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        size_t len =
598d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            (colonPos == NULL) ? strlen(s) : colonPos - s;
608d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
618d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) {
628d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            value->setTo(&s[keyLen + 1], len - keyLen - 1);
638d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            return true;
648d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        }
658d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
668d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        if (colonPos == NULL) {
678d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            return false;
688d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        }
698d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
708d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        s = colonPos + 1;
718d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    }
728d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber}
738d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
74cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstruct MyHandler : public AHandler {
75cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    MyHandler(const char *url, const sp<ALooper> &looper)
76cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        : mLooper(looper),
77348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber          mNetLooper(new ALooper),
78cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber          mConn(new ARTSPConnection),
79cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber          mRTPConn(new ARTPConnection),
80cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber          mSessionURL(url),
81cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber          mSetupTracksSuccessful(false),
82cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber          mSeekPending(false),
83cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber          mFirstAccessUnit(true),
848d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber          mFirstAccessUnitNTP(0),
858d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber          mNumAccessUnitsReceived(0),
868d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber          mCheckPending(false) {
87a814c1fdc2acf0ed2ee3b175110f6039be7c4873Andreas Huber        mNetLooper->setName("rtsp net");
88348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber        mNetLooper->start(false /* runOnCallingThread */,
89348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                          false /* canCallJava */,
90348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                          PRIORITY_HIGHEST);
91348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber    }
92348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber
931b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber    void connect(const sp<AMessage> &doneMsg) {
941b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber        mDoneMsg = doneMsg;
951b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber
96cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mLooper->registerHandler(this);
97cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mLooper->registerHandler(mConn);
98348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber        (1 ? mNetLooper : mLooper)->registerHandler(mRTPConn);
99348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber
1000792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        sp<AMessage> notify = new AMessage('biny', id());
1010792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        mConn->observeBinaryData(notify);
1020792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
1031b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber        sp<AMessage> reply = new AMessage('conn', id());
104cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mConn->connect(mSessionURL.c_str(), reply);
105cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
106cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1071b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber    void disconnect(const sp<AMessage> &doneMsg) {
1081b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber        mDoneMsg = doneMsg;
1091b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber
1101b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber        (new AMessage('abor', id()))->post();
111348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber    }
112348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber
113cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber    void seek(int64_t timeUs) {
114cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber        sp<AMessage> msg = new AMessage('seek', id());
115cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber        msg->setInt64("time", timeUs);
116cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber        msg->post();
117cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber    }
118cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
1198d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    int64_t getNormalPlayTimeUs() {
1208d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        int64_t maxTimeUs = 0;
1218d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        for (size_t i = 0; i < mTracks.size(); ++i) {
1228d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            int64_t timeUs = mTracks.editItemAt(i).mPacketSource
1238d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                ->getNormalPlayTimeUs();
1248d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
1258d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            if (i == 0 || timeUs > maxTimeUs) {
1268d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                maxTimeUs = timeUs;
1278d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            }
1288d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        }
1298d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
1308d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        return maxTimeUs;
1318d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    }
1328d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
133cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    virtual void onMessageReceived(const sp<AMessage> &msg) {
134cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        switch (msg->what()) {
135cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            case 'conn':
136cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
137cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                int32_t result;
138cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                CHECK(msg->findInt32("result", &result));
139cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
140cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                LOG(INFO) << "connection request completed with result "
141cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                     << result << " (" << strerror(-result) << ")";
142cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
143cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                if (result == OK) {
144cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    AString request;
145cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    request = "DESCRIBE ";
146cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    request.append(mSessionURL);
147cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    request.append(" RTSP/1.0\r\n");
148cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    request.append("Accept: application/sdp\r\n");
149cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    request.append("\r\n");
150cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
151cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    sp<AMessage> reply = new AMessage('desc', id());
152cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    mConn->sendRequest(request.c_str(), reply);
1530792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                } else {
1540792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                    (new AMessage('disc', id()))->post();
155cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                }
156cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
157cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
158cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
159cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            case 'disc':
160cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
161cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                (new AMessage('quit', id()))->post();
162cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
163cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
164cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
165cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            case 'desc':
166cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
167cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                int32_t result;
168cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                CHECK(msg->findInt32("result", &result));
169cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
170cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                LOG(INFO) << "DESCRIBE completed with result "
171cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                     << result << " (" << strerror(-result) << ")";
172cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
173cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                if (result == OK) {
174cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    sp<RefBase> obj;
175cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    CHECK(msg->findObject("response", &obj));
176cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    sp<ARTSPResponse> response =
177cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        static_cast<ARTSPResponse *>(obj.get());
178cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
179cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    if (response->mStatusCode == 302) {
180cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        ssize_t i = response->mHeaders.indexOfKey("location");
181cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        CHECK_GE(i, 0);
182cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
183cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        mSessionURL = response->mHeaders.valueAt(i);
184cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
185cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        AString request;
186cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        request = "DESCRIBE ";
187cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        request.append(mSessionURL);
188cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        request.append(" RTSP/1.0\r\n");
189cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        request.append("Accept: application/sdp\r\n");
190cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        request.append("\r\n");
191cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
192cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        sp<AMessage> reply = new AMessage('desc', id());
193cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        mConn->sendRequest(request.c_str(), reply);
194cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        break;
195cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    }
196cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
197cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    CHECK_EQ(response->mStatusCode, 200u);
198cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
199cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    mSessionDesc = new ASessionDescription;
200cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
201cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    mSessionDesc->setTo(
202cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                            response->mContent->data(),
203cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                            response->mContent->size());
204cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
205cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    CHECK(mSessionDesc->isValid());
206cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
207cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    ssize_t i = response->mHeaders.indexOfKey("content-base");
208cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    if (i >= 0) {
209cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        mBaseURL = response->mHeaders.valueAt(i);
210cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    } else {
211cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        i = response->mHeaders.indexOfKey("content-location");
212cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        if (i >= 0) {
213cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                            mBaseURL = response->mHeaders.valueAt(i);
214cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        } else {
215cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                            mBaseURL = mSessionURL;
216cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        }
217cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    }
218cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
219cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    CHECK_GT(mSessionDesc->countTracks(), 1u);
220cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    setupTrack(1);
221cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                } else {
222cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    sp<AMessage> reply = new AMessage('disc', id());
223cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    mConn->disconnect(reply);
224cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                }
225cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
226cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
227cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
228cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            case 'setu':
229cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
230cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                size_t index;
231cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                CHECK(msg->findSize("index", &index));
232cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
23339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                TrackInfo *track = NULL;
234cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                size_t trackIndex;
23539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                if (msg->findSize("track-index", &trackIndex)) {
23639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                    track = &mTracks.editItemAt(trackIndex);
23739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                }
238cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
239cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                int32_t result;
240cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                CHECK(msg->findInt32("result", &result));
241cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
242cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                LOG(INFO) << "SETUP(" << index << ") completed with result "
243cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                     << result << " (" << strerror(-result) << ")";
244cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
24539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                if (result != OK) {
24639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                    if (track) {
2470792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                        if (!track->mUsingInterleavedTCP) {
2480792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                            close(track->mRTPSocket);
2490792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                            close(track->mRTCPSocket);
2500792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                        }
25139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
25239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                        mTracks.removeItemsAt(trackIndex);
25339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                    }
25439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                } else {
25539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                    CHECK(track != NULL);
256cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
257cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    sp<RefBase> obj;
258cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    CHECK(msg->findObject("response", &obj));
259cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    sp<ARTSPResponse> response =
260cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        static_cast<ARTSPResponse *>(obj.get());
261cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
262cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    CHECK_EQ(response->mStatusCode, 200u);
263cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
264cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    ssize_t i = response->mHeaders.indexOfKey("session");
265cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    CHECK_GE(i, 0);
266cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
267cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    if (index == 1) {
268cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        mSessionID = response->mHeaders.valueAt(i);
269cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        i = mSessionID.find(";");
270cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        if (i >= 0) {
271cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                            // Remove options, i.e. ";timeout=90"
272cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                            mSessionID.erase(i, mSessionID.size() - i);
273cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        }
274cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    }
275cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
276cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    sp<AMessage> notify = new AMessage('accu', id());
277cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    notify->setSize("track-index", trackIndex);
278cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
279cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    mRTPConn->addStream(
280cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                            track->mRTPSocket, track->mRTCPSocket,
281cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                            mSessionDesc, index,
2820792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                            notify, track->mUsingInterleavedTCP);
283cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
284cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    mSetupTracksSuccessful = true;
285cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                }
286cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
28739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                ++index;
28839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                if (index < mSessionDesc->countTracks()) {
28939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                    setupTrack(index);
29039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                } else if (mSetupTracksSuccessful) {
291cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    AString request = "PLAY ";
292cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    request.append(mSessionURL);
293cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    request.append(" RTSP/1.0\r\n");
294cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
295cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    request.append("Session: ");
296cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    request.append(mSessionID);
297cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    request.append("\r\n");
298cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
299cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    request.append("\r\n");
300cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
301cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    sp<AMessage> reply = new AMessage('play', id());
302cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    mConn->sendRequest(request.c_str(), reply);
303cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                } else {
304cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    sp<AMessage> reply = new AMessage('disc', id());
305cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    mConn->disconnect(reply);
306cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                }
307cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
308cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
309cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
310cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            case 'play':
311cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
312cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                int32_t result;
313cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                CHECK(msg->findInt32("result", &result));
314cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
315cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                LOG(INFO) << "PLAY completed with result "
316cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                     << result << " (" << strerror(-result) << ")";
317cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
318cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                if (result == OK) {
319cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    sp<RefBase> obj;
320cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    CHECK(msg->findObject("response", &obj));
321cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    sp<ARTSPResponse> response =
322cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        static_cast<ARTSPResponse *>(obj.get());
323cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
324cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    CHECK_EQ(response->mStatusCode, 200u);
325cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
3268d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                    parsePlayResponse(response);
3278d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
3281b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber                    mDoneMsg->setInt32("result", OK);
3291b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber                    mDoneMsg->post();
3301b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber                    mDoneMsg = NULL;
3310792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
3320792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                    sp<AMessage> timeout = new AMessage('tiou', id());
333e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber                    timeout->post(kStartupTimeoutUs);
334cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                } else {
335cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    sp<AMessage> reply = new AMessage('disc', id());
336cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    mConn->disconnect(reply);
337cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                }
338cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
339cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
340cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
341cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
342cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            case 'abor':
343cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
344cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                for (size_t i = 0; i < mTracks.size(); ++i) {
345cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    mTracks.editItemAt(i).mPacketSource->signalEOS(
346cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                            ERROR_END_OF_STREAM);
347cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                }
348cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
349cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                sp<AMessage> reply = new AMessage('tear', id());
350cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
351cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                AString request;
352cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                request = "TEARDOWN ";
353cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
354cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                // XXX should use aggregate url from SDP here...
355cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                request.append(mSessionURL);
356cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                request.append(" RTSP/1.0\r\n");
357cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
358cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                request.append("Session: ");
359cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                request.append(mSessionID);
360cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                request.append("\r\n");
361cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
362cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                request.append("\r\n");
363cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
364cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                mConn->sendRequest(request.c_str(), reply);
365cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
366cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
367cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
368cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            case 'tear':
369cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
370cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                int32_t result;
371cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                CHECK(msg->findInt32("result", &result));
372cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
373cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                LOG(INFO) << "TEARDOWN completed with result "
374cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                     << result << " (" << strerror(-result) << ")";
375cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
376cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                sp<AMessage> reply = new AMessage('disc', id());
377cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                mConn->disconnect(reply);
378cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
379cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
380cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
381cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            case 'quit':
382cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
3831b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber                if (mDoneMsg != NULL) {
3841b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber                    mDoneMsg->setInt32("result", UNKNOWN_ERROR);
3851b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber                    mDoneMsg->post();
3861b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber                    mDoneMsg = NULL;
3871b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber                }
388cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
389cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
390cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
3918d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            case 'chek':
3928d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            {
3938d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                if (mNumAccessUnitsReceived == 0) {
3948d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                    LOG(INFO) << "stream ended? aborting.";
3958d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                    (new AMessage('abor', id()))->post();
3968d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                    break;
3978d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                }
3988d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
3998d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                mNumAccessUnitsReceived = 0;
400e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber                msg->post(kAccessUnitTimeoutUs);
4018d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                break;
4028d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            }
4038d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
404cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            case 'accu':
405cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
4068d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                ++mNumAccessUnitsReceived;
4078d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
4088d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                if (!mCheckPending) {
4098d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                    mCheckPending = true;
4108d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                    sp<AMessage> check = new AMessage('chek', id());
411e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber                    check->post(kAccessUnitTimeoutUs);
4128d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                }
4138d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
414cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                size_t trackIndex;
415cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                CHECK(msg->findSize("track-index", &trackIndex));
416cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
4178d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                TrackInfo *track = &mTracks.editItemAt(trackIndex);
4188d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
419ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber                int32_t eos;
420ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber                if (msg->findInt32("eos", &eos)) {
421ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber                    LOG(INFO) << "received BYE on track index " << trackIndex;
422ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber#if 0
423ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber                    track->mPacketSource->signalEOS(ERROR_END_OF_STREAM);
424ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber#endif
425ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber                    return;
426ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber                }
427ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber
428cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                sp<RefBase> obj;
429cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                CHECK(msg->findObject("access-unit", &obj));
430cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
431cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                sp<ABuffer> accessUnit = static_cast<ABuffer *>(obj.get());
432cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
4338d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                uint32_t seqNum = (uint32_t)accessUnit->int32Data();
4348d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
4358d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                if (seqNum < track->mFirstSeqNumInSegment) {
4368d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                    LOG(INFO) << "dropping stale access-unit "
4378d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                              << "(" << seqNum << " < "
4388d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                              << track->mFirstSeqNumInSegment << ")";
4398d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                    break;
4408d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                }
4418d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
442cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                uint64_t ntpTime;
443cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                CHECK(accessUnit->meta()->findInt64(
444cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                            "ntp-time", (int64_t *)&ntpTime));
445cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
4468d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                uint32_t rtpTime;
4478d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                CHECK(accessUnit->meta()->findInt32(
4488d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                            "rtp-time", (int32_t *)&rtpTime));
4498d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
4508d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                if (track->mNewSegment) {
4518d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                    track->mNewSegment = false;
4528d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
4538d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                    LOG(VERBOSE) << "first segment unit ntpTime="
4548d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                              << StringPrintf("0x%016llx", ntpTime)
4558d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                              << " rtpTime=" << rtpTime
4568d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                              << " seq=" << seqNum;
4578d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                }
4588d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
459cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                if (mFirstAccessUnit) {
460cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                    mFirstAccessUnit = false;
461cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                    mFirstAccessUnitNTP = ntpTime;
462cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                }
463cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
464cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                if (ntpTime >= mFirstAccessUnitNTP) {
465cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                    ntpTime -= mFirstAccessUnitNTP;
466cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                } else {
467cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                    ntpTime = 0;
468cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                }
469cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
470cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                int64_t timeUs = (int64_t)(ntpTime * 1E6 / (1ll << 32));
471cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
472cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                accessUnit->meta()->setInt64("timeUs", timeUs);
473cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
474348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber#if 0
475348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                int32_t damaged;
476348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                if (accessUnit->meta()->findInt32("damaged", &damaged)
477348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                        && damaged != 0) {
478348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                    LOG(INFO) << "ignoring damaged AU";
479348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                } else
480348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber#endif
481348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                {
482348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                    TrackInfo *track = &mTracks.editItemAt(trackIndex);
483348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                    track->mPacketSource->queueAccessUnit(accessUnit);
484348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                }
485cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
486cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
487cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
488cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber            case 'seek':
489cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber            {
490cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                if (mSeekPending) {
491cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                    break;
492cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                }
493cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
494cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                int64_t timeUs;
495cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                CHECK(msg->findInt64("time", &timeUs));
496cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
497cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                mSeekPending = true;
498cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
499cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                AString request = "PAUSE ";
500cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append(mSessionURL);
501cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append(" RTSP/1.0\r\n");
502cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
503cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append("Session: ");
504cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append(mSessionID);
505cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append("\r\n");
506cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
507cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append("\r\n");
508cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
509cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                sp<AMessage> reply = new AMessage('see1', id());
510cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                reply->setInt64("time", timeUs);
511cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                mConn->sendRequest(request.c_str(), reply);
512cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                break;
513cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber            }
514cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
515cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber            case 'see1':
516cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber            {
5178d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                // Session is paused now.
5188d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                for (size_t i = 0; i < mTracks.size(); ++i) {
5198d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                    mTracks.editItemAt(i).mPacketSource->flushQueue();
5208d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                }
5218d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
522cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                int64_t timeUs;
523cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                CHECK(msg->findInt64("time", &timeUs));
524cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
525cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                AString request = "PLAY ";
526cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append(mSessionURL);
527cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append(" RTSP/1.0\r\n");
528cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
529cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append("Session: ");
530cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append(mSessionID);
531cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append("\r\n");
532cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
533cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append(
534cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                        StringPrintf(
535cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                            "Range: npt=%lld-\r\n", timeUs / 1000000ll));
536cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
537cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append("\r\n");
538cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
539cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                sp<AMessage> reply = new AMessage('see2', id());
540cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                mConn->sendRequest(request.c_str(), reply);
541cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                break;
542cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber            }
543cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
544cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber            case 'see2':
545cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber            {
546cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                CHECK(mSeekPending);
547cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
548cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                int32_t result;
549cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                CHECK(msg->findInt32("result", &result));
5508d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
5518d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                LOG(INFO) << "PLAY completed with result "
5528d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                     << result << " (" << strerror(-result) << ")";
5538d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
5548d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                CHECK_EQ(result, (status_t)OK);
555cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
556cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                sp<RefBase> obj;
557cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                CHECK(msg->findObject("response", &obj));
558cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                sp<ARTSPResponse> response =
559cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                    static_cast<ARTSPResponse *>(obj.get());
560cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
561cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                CHECK_EQ(response->mStatusCode, 200u);
562cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
5638d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                parsePlayResponse(response);
5648d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
5658d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                LOG(INFO) << "seek completed.";
5668d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                mSeekPending = false;
567cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                break;
568cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber            }
569cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
5700792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            case 'biny':
5710792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            {
5720792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                sp<RefBase> obj;
5730792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                CHECK(msg->findObject("buffer", &obj));
5740792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get());
5750792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
5760792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                int32_t index;
5770792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                CHECK(buffer->meta()->findInt32("index", &index));
5780792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
5790792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                mRTPConn->injectPacket(index, buffer);
5800792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                break;
5810792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            }
5820792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
5830792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            case 'tiou':
5840792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            {
5850792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                if (mFirstAccessUnit) {
5860792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                    LOG(WARNING) << "Never received any data, disconnecting.";
587cc6adf524c1bb3bfaa5be464b50b8bcca899761cAndreas Huber                    (new AMessage('abor', id()))->post();
5880792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                }
5890792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                break;
5900792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            }
5910792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
592cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            default:
593cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                TRESPASS();
594cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
595cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
596cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
597cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
5988d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    static void SplitString(
5998d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            const AString &s, const char *separator, List<AString> *items) {
6008d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        items->clear();
6018d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        size_t start = 0;
6028d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        while (start < s.size()) {
6038d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            ssize_t offset = s.find(separator, start);
6048d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
6058d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            if (offset < 0) {
6068d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                items->push_back(AString(s, start, s.size() - start));
6078d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                break;
6088d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            }
6098d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
6108d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            items->push_back(AString(s, start, offset - start));
6118d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            start = offset + strlen(separator);
6128d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        }
6138d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    }
6148d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
6158d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    void parsePlayResponse(const sp<ARTSPResponse> &response) {
6168d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        ssize_t i = response->mHeaders.indexOfKey("range");
6178d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        if (i < 0) {
6188d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            // Server doesn't even tell use what range it is going to
6198d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            // play, therefore we won't support seeking.
6208d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            return;
6218d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        }
6228d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
6238d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        AString range = response->mHeaders.valueAt(i);
6248d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        LOG(VERBOSE) << "Range: " << range;
6258d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
6268d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        AString val;
6278d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        CHECK(GetAttribute(range.c_str(), "npt", &val));
6288d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        float npt1, npt2;
6298d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
6308d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        if (val == "now-") {
6318d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            // This is a live stream and therefore not seekable.
6328d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            return;
6338d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        } else {
6348d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            CHECK_EQ(sscanf(val.c_str(), "%f-%f", &npt1, &npt2), 2);
6358d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        }
6368d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
6378d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        i = response->mHeaders.indexOfKey("rtp-info");
6388d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        CHECK_GE(i, 0);
6398d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
6408d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        AString rtpInfo = response->mHeaders.valueAt(i);
6418d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        List<AString> streamInfos;
6428d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        SplitString(rtpInfo, ",", &streamInfos);
6438d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
6448d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        int n = 1;
6458d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        for (List<AString>::iterator it = streamInfos.begin();
6468d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber             it != streamInfos.end(); ++it) {
6478d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            (*it).trim();
6488d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            LOG(VERBOSE) << "streamInfo[" << n << "] = " << *it;
6498d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
6508d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            CHECK(GetAttribute((*it).c_str(), "url", &val));
6518d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
6528d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            size_t trackIndex = 0;
6538d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            while (trackIndex < mTracks.size()
6548d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                    && !(val == mTracks.editItemAt(trackIndex).mURL)) {
6558d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                ++trackIndex;
6568d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            }
6578d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            CHECK_LT(trackIndex, mTracks.size());
6588d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
6598d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            CHECK(GetAttribute((*it).c_str(), "seq", &val));
6608d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
6618d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            char *end;
6628d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            unsigned long seq = strtoul(val.c_str(), &end, 10);
6638d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
6648d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            TrackInfo *info = &mTracks.editItemAt(trackIndex);
6658d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            info->mFirstSeqNumInSegment = seq;
6668d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            info->mNewSegment = true;
6678d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
6688d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            CHECK(GetAttribute((*it).c_str(), "rtptime", &val));
6698d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
6708d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            uint32_t rtpTime = strtoul(val.c_str(), &end, 10);
6718d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
6728d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            LOG(VERBOSE) << "track #" << n
6738d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                      << ": rtpTime=" << rtpTime << " <=> npt=" << npt1;
6748d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
6758d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            info->mPacketSource->setNormalPlayTimeMapping(
6768d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                    rtpTime, (int64_t)(npt1 * 1E6));
6778d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
6788d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            ++n;
6798d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        }
6808d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    }
6818d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
682cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<APacketSource> getPacketSource(size_t index) {
683cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        CHECK_GE(index, 0u);
684cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        CHECK_LT(index, mTracks.size());
685cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
686cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return mTracks.editItemAt(index).mPacketSource;
687cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
688cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
689cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    size_t countTracks() const {
690cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return mTracks.size();
691cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
692cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
693cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberprivate:
694cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<ALooper> mLooper;
695348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber    sp<ALooper> mNetLooper;
696cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<ARTSPConnection> mConn;
697cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<ARTPConnection> mRTPConn;
698cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<ASessionDescription> mSessionDesc;
699cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    AString mSessionURL;
700cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    AString mBaseURL;
701cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    AString mSessionID;
702cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    bool mSetupTracksSuccessful;
703cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber    bool mSeekPending;
704cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber    bool mFirstAccessUnit;
705cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber    uint64_t mFirstAccessUnitNTP;
7068d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    int64_t mNumAccessUnitsReceived;
7078d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    bool mCheckPending;
708cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
709cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    struct TrackInfo {
7108d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        AString mURL;
711cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        int mRTPSocket;
712cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        int mRTCPSocket;
7130792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        bool mUsingInterleavedTCP;
7148d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        uint32_t mFirstSeqNumInSegment;
7158d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        bool mNewSegment;
716cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
717cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        sp<APacketSource> mPacketSource;
718cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    };
719cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    Vector<TrackInfo> mTracks;
720cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
7211b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber    sp<AMessage> mDoneMsg;
7221b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber
723cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    void setupTrack(size_t index) {
72439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sp<APacketSource> source =
72539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            new APacketSource(mSessionDesc, index);
72639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        if (source->initCheck() != OK) {
72739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            LOG(WARNING) << "Unsupported format. Ignoring track #"
72839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                         << index << ".";
72939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
73039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            sp<AMessage> reply = new AMessage('setu', id());
73139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            reply->setSize("index", index);
73239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            reply->setInt32("result", ERROR_UNSUPPORTED);
73339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            reply->post();
73439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            return;
73539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        }
73639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
737cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        AString url;
738cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        CHECK(mSessionDesc->findAttribute(index, "a=control", &url));
739cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
740cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        AString trackURL;
741cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        CHECK(MakeURL(mBaseURL.c_str(), url.c_str(), &trackURL));
742cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
743cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mTracks.push(TrackInfo());
744cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        TrackInfo *info = &mTracks.editItemAt(mTracks.size() - 1);
7458d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        info->mURL = trackURL;
74639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        info->mPacketSource = source;
7470792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        info->mUsingInterleavedTCP = false;
7488d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        info->mFirstSeqNumInSegment = 0;
7498d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        info->mNewSegment = true;
7508d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
7518d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        LOG(VERBOSE) << "track #" << mTracks.size() << " URL=" << trackURL;
752cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
753cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        AString request = "SETUP ";
754cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        request.append(trackURL);
755cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        request.append(" RTSP/1.0\r\n");
756cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
7570792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber#if USE_TCP_INTERLEAVED
7580792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        size_t interleaveIndex = 2 * (mTracks.size() - 1);
7590792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        info->mUsingInterleavedTCP = true;
7600792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        info->mRTPSocket = interleaveIndex;
7610792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        info->mRTCPSocket = interleaveIndex + 1;
7620792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
7630792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        request.append("Transport: RTP/AVP/TCP;interleaved=");
7640792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        request.append(interleaveIndex);
7650792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        request.append("-");
7660792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        request.append(interleaveIndex + 1);
7670792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber#else
7680792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        unsigned rtpPort;
7690792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        ARTPConnection::MakePortPair(
7700792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                &info->mRTPSocket, &info->mRTCPSocket, &rtpPort);
7710792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
772cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        request.append("Transport: RTP/AVP/UDP;unicast;client_port=");
773cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        request.append(rtpPort);
774cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        request.append("-");
775cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        request.append(rtpPort + 1);
7760792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber#endif
7770792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
778cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        request.append("\r\n");
779cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
780cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (index > 1) {
781cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            request.append("Session: ");
782cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            request.append(mSessionID);
783cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            request.append("\r\n");
784cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
785cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
786cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        request.append("\r\n");
787cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
788cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        sp<AMessage> reply = new AMessage('setu', id());
789cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->setSize("index", index);
790cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->setSize("track-index", mTracks.size() - 1);
791cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mConn->sendRequest(request.c_str(), reply);
792cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
793cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
794cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    static bool MakeURL(const char *baseURL, const char *url, AString *out) {
795cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        out->clear();
796cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
797cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (strncasecmp("rtsp://", baseURL, 7)) {
798cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // Base URL must be absolute
799cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return false;
800cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
801cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
802cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (!strncasecmp("rtsp://", url, 7)) {
803cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // "url" is already an absolute URL, ignore base URL.
804cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            out->setTo(url);
805cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return true;
806cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
807cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
808cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        size_t n = strlen(baseURL);
809cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (baseURL[n - 1] == '/') {
810cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            out->setTo(baseURL);
811cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            out->append(url);
812cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        } else {
813cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            char *slashPos = strrchr(baseURL, '/');
814cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
815cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            if (slashPos > &baseURL[6]) {
816cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                out->setTo(baseURL, slashPos - baseURL);
817cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            } else {
818cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                out->setTo(baseURL);
819cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
820cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
821cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            out->append("/");
822cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            out->append(url);
823cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
824cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
825cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return true;
826cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
827cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
828cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(MyHandler);
829cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber};
830cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
831cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}  // namespace android
832cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
833cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#endif  // MY_HANDLER_H_
834