17a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber/*
27a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * Copyright (C) 2010 The Android Open Source Project
37a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber *
47a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
57a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * you may not use this file except in compliance with the License.
67a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * You may obtain a copy of the License at
77a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber *
87a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
97a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber *
107a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * Unless required by applicable law or agreed to in writing, software
117a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
127a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * See the License for the specific language governing permissions and
147a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * limitations under the License.
157a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber */
167a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
177a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#ifndef MY_TRANSMITTER_H_
187a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
197a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#define MY_TRANSMITTER_H_
207a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
217a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include "ARTPConnection.h"
227a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
237a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include <arpa/inet.h>
247a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include <sys/socket.h>
257a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
267a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include <openssl/md5.h>
277a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
287a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include <media/stagefright/foundation/ADebug.h>
297a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include <media/stagefright/foundation/base64.h>
307a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include <media/stagefright/foundation/hexdump.h>
317a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
327a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#ifdef ANDROID
337a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include "VideoSource.h"
347a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
357a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include <media/stagefright/OMXClient.h>
367a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include <media/stagefright/OMXCodec.h>
377a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#endif
387a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
397a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Hubernamespace android {
407a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
417a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#define TRACK_SUFFIX    "trackid=1"
427a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#define PT              96
437a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#define PT_STR          "96"
447a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
457a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#define USERNAME        "bcast"
467a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#define PASSWORD        "test"
477a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
487a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huberstatic int uniformRand(int limit) {
497a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    return ((double)rand() * limit) / RAND_MAX;
507a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber}
517a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
527a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huberstatic bool GetAttribute(const char *s, const char *key, AString *value) {
537a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    value->clear();
547a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
557a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    size_t keyLen = strlen(key);
567a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
577a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    for (;;) {
587a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        const char *colonPos = strchr(s, ';');
597a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
607a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        size_t len =
617a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            (colonPos == NULL) ? strlen(s) : colonPos - s;
627a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
637a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) {
647a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            value->setTo(&s[keyLen + 1], len - keyLen - 1);
657a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            return true;
667a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        }
677a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
687a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        if (colonPos == NULL) {
697a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            return false;
707a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        }
717a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
727a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        s = colonPos + 1;
737a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    }
747a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber}
757a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
767a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huberstruct MyTransmitter : public AHandler {
777a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    MyTransmitter(const char *url, const sp<ALooper> &looper)
787a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        : mServerURL(url),
797a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber          mLooper(looper),
807a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber          mConn(new ARTSPConnection),
817a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber          mConnected(false),
827a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber          mAuthType(NONE),
837a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber          mRTPSocket(-1),
847a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber          mRTCPSocket(-1),
857a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber          mSourceID(rand()),
867a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber          mSeqNo(uniformRand(65536)),
877a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber          mRTPTimeBase(rand()),
887a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber          mNumSamplesSent(0),
897a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber          mNumRTPSent(0),
907a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber          mNumRTPOctetsSent(0),
917a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber          mLastRTPTime(0),
927a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber          mLastNTPTime(0) {
937a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        mStreamURL = mServerURL;
947a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        mStreamURL.append("/bazong.sdp");
957a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
967a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        mTrackURL = mStreamURL;
977a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        mTrackURL.append("/");
987a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        mTrackURL.append(TRACK_SUFFIX);
997a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1007a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        mLooper->registerHandler(this);
1017a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        mLooper->registerHandler(mConn);
1027a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1037a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sp<AMessage> reply = new AMessage('conn', id());
1047a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        mConn->connect(mServerURL.c_str(), reply);
1057a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1067a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#ifdef ANDROID
1077a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        int width = 640;
1087a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        int height = 480;
1097a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1107a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sp<MediaSource> source = new VideoSource(width, height);
1117a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1127a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sp<MetaData> encMeta = new MetaData;
1137a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        encMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
1147a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        encMeta->setInt32(kKeyWidth, width);
1157a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        encMeta->setInt32(kKeyHeight, height);
1167a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1177a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        OMXClient client;
1187a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        client.connect();
1197a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1207a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        mEncoder = OMXCodec::Create(
1217a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                client.interface(), encMeta,
1227a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                true /* createEncoder */, source);
1237a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1247a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        mEncoder->start();
1257a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1267a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        MediaBuffer *buffer;
1277a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        CHECK_EQ(mEncoder->read(&buffer), (status_t)OK);
1287a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        CHECK(buffer != NULL);
1297a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1307a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        makeH264SPropParamSets(buffer);
1317a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1327a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        buffer->release();
1337a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        buffer = NULL;
1347a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#endif
1357a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    }
1367a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1377a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    uint64_t ntpTime() {
1387a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        struct timeval tv;
1397a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        gettimeofday(&tv, NULL);
1407a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1417a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        uint64_t nowUs = tv.tv_sec * 1000000ll + tv.tv_usec;
1427a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1437a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        nowUs += ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll;
1447a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1457a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        uint64_t hi = nowUs / 1000000ll;
1467a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        uint64_t lo = ((1ll << 32) * (nowUs % 1000000ll)) / 1000000ll;
1477a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1487a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        return (hi << 32) | lo;
1497a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    }
1507a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1517a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    void issueAnnounce() {
1527a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        AString sdp;
1537a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp = "v=0\r\n";
1547a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1557a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append("o=- ");
1567a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1577a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        uint64_t ntp = ntpTime();
1587a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append(ntp);
1597a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append(" ");
1607a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append(ntp);
1617a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append(" IN IP4 127.0.0.0\r\n");
1627a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1637a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append(
1647a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber              "s=Sample\r\n"
1657a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber              "i=Playing around with ANNOUNCE\r\n"
1667a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber              "c=IN IP4 ");
1677a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1687a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        struct in_addr addr;
1697a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        addr.s_addr = htonl(mServerIP);
1707a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1717a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append(inet_ntoa(addr));
1727a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1737a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append(
1747a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber              "\r\n"
1757a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber              "t=0 0\r\n"
1767a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber              "a=range:npt=now-\r\n");
1777a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1787a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#ifdef ANDROID
1797a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sp<MetaData> meta = mEncoder->getFormat();
1807a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        int32_t width, height;
1817a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        CHECK(meta->findInt32(kKeyWidth, &width));
1827a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        CHECK(meta->findInt32(kKeyHeight, &height));
1837a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1847a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append(
1857a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber              "m=video 0 RTP/AVP " PT_STR "\r\n"
1867a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber              "b=AS 320000\r\n"
1877a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber              "a=rtpmap:" PT_STR " H264/90000\r\n");
1887a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1897a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append("a=cliprect 0,0,");
1907a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append(height);
1917a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append(",");
1927a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append(width);
1937a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append("\r\n");
1947a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
1957a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append(
1967a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber              "a=framesize:" PT_STR " ");
1977a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append(width);
1987a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append("-");
1997a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append(height);
2007a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append("\r\n");
2017a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
2027a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append(
2037a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber              "a=fmtp:" PT_STR " profile-level-id=42C015;sprop-parameter-sets=");
2047a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
2057a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append(mSeqParamSet);
2067a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append(",");
2077a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append(mPicParamSet);
2087a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append(";packetization-mode=1\r\n");
2097a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#else
2107a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append(
2117a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                "m=audio 0 RTP/AVP " PT_STR "\r\n"
2127a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                "a=rtpmap:" PT_STR " L8/8000/1\r\n");
2137a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#endif
2147a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
2157a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sdp.append("a=control:" TRACK_SUFFIX "\r\n");
2167a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
2177a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        AString request;
2187a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        request.append("ANNOUNCE ");
2197a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        request.append(mStreamURL);
2207a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        request.append(" RTSP/1.0\r\n");
2217a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
2227a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        addAuthentication(&request, "ANNOUNCE", mStreamURL.c_str());
2237a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
2247a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        request.append("Content-Type: application/sdp\r\n");
2257a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        request.append("Content-Length: ");
2267a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        request.append(sdp.size());
2277a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        request.append("\r\n");
2287a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
2297a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        request.append("\r\n");
2307a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        request.append(sdp);
2317a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
2327a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        sp<AMessage> reply = new AMessage('anno', id());
2337a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        mConn->sendRequest(request.c_str(), reply);
2347a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    }
2357a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
2367a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    void H(const AString &s, AString *out) {
2377a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        out->clear();
2387a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
2397a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        MD5_CTX m;
2407a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        MD5_Init(&m);
2417a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        MD5_Update(&m, s.c_str(), s.size());
2427a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
2437a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        uint8_t key[16];
2447a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        MD5_Final(key, &m);
2457a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
2467a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        for (size_t i = 0; i < 16; ++i) {
2477a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            char nibble = key[i] >> 4;
2487a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            if (nibble <= 9) {
2497a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                nibble += '0';
2507a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            } else {
2517a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                nibble += 'a' - 10;
2527a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            }
2537a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            out->append(&nibble, 1);
2547a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
2557a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            nibble = key[i] & 0x0f;
2567a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            if (nibble <= 9) {
2577a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                nibble += '0';
2587a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            } else {
2597a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                nibble += 'a' - 10;
2607a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            }
2617a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            out->append(&nibble, 1);
2627a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        }
2637a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    }
2647a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
2657a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    void authenticate(const sp<ARTSPResponse> &response) {
2667a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        ssize_t i = response->mHeaders.indexOfKey("www-authenticate");
2677a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        CHECK_GE(i, 0);
2687a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
2697a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        AString value = response->mHeaders.valueAt(i);
2707a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
2717a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        if (!strncmp(value.c_str(), "Basic", 5)) {
2727a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            mAuthType = BASIC;
2737a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        } else {
2747a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            CHECK(!strncmp(value.c_str(), "Digest", 6));
2757a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            mAuthType = DIGEST;
2767a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
2777a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            i = value.find("nonce=");
2787a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            CHECK_GE(i, 0);
2797a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            CHECK_EQ(value.c_str()[i + 6], '\"');
2807a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            ssize_t j = value.find("\"", i + 7);
2817a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            CHECK_GE(j, 0);
2827a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
2837a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            mNonce.setTo(value, i + 7, j - i - 7);
2847a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        }
2857a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
2867a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        issueAnnounce();
2877a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    }
2887a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
2897a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    void addAuthentication(
2907a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            AString *request, const char *method, const char *url) {
2917a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        if (mAuthType == NONE) {
2927a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            return;
2937a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        }
2947a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
2957a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        if (mAuthType == BASIC) {
2967a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            request->append("Authorization: Basic YmNhc3Q6dGVzdAo=\r\n");
2977a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            return;
2987a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        }
2997a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
3007a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        CHECK_EQ((int)mAuthType, (int)DIGEST);
3017a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
3027a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        AString A1;
3037a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        A1.append(USERNAME);
3047a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        A1.append(":");
3057a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        A1.append("Streaming Server");
3067a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        A1.append(":");
3077a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        A1.append(PASSWORD);
3087a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
3097a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        AString A2;
3107a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        A2.append(method);
3117a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        A2.append(":");
3127a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        A2.append(url);
3137a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
3147a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        AString HA1, HA2;
3157a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        H(A1, &HA1);
3167a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        H(A2, &HA2);
3177a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
3187a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        AString tmp;
3197a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        tmp.append(HA1);
3207a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        tmp.append(":");
3217a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        tmp.append(mNonce);
3227a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        tmp.append(":");
3237a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        tmp.append(HA2);
3247a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
3257a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        AString digest;
3267a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        H(tmp, &digest);
3277a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
3287a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        request->append("Authorization: Digest ");
3297a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        request->append("nonce=\"");
3307a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        request->append(mNonce);
3317a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        request->append("\", ");
3327a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        request->append("username=\"" USERNAME "\", ");
3337a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        request->append("uri=\"");
3347a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        request->append(url);
3357a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        request->append("\", ");
3367a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        request->append("response=\"");
3377a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        request->append(digest);
3387a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        request->append("\"");
3397a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        request->append("\r\n");
3407a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    }
3417a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
3427a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    virtual void onMessageReceived(const sp<AMessage> &msg) {
3437a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        switch (msg->what()) {
3447a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            case 'conn':
3457a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            {
3467a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                int32_t result;
3477a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK(msg->findInt32("result", &result));
3487a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
3497a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                LOG(INFO) << "connection request completed with result "
3507a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                     << result << " (" << strerror(-result) << ")";
3517a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
3527a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                if (result != OK) {
3537a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    (new AMessage('quit', id()))->post();
3547a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    break;
3557a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                }
3567a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
3577a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                mConnected = true;
3587a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
3597a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK(msg->findInt32("server-ip", (int32_t *)&mServerIP));
3607a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
3617a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                issueAnnounce();
3627a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                break;
3637a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            }
3647a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
3657a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            case 'anno':
3667a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            {
3677a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                int32_t result;
3687a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK(msg->findInt32("result", &result));
3697a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
3707a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                LOG(INFO) << "ANNOUNCE completed with result "
3717a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                     << result << " (" << strerror(-result) << ")";
3727a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
3737a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                sp<RefBase> obj;
3747a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK(msg->findObject("response", &obj));
3757a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                sp<ARTSPResponse> response;
3767a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
3777a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                if (result == OK) {
3787a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    response = static_cast<ARTSPResponse *>(obj.get());
3797a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    CHECK(response != NULL);
3807a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
3817a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    if (response->mStatusCode == 401) {
3827a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                        if (mAuthType != NONE) {
3837a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                            LOG(INFO) << "FAILED to authenticate";
3847a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                            (new AMessage('quit', id()))->post();
3857a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                            break;
3867a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                        }
3877a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
3887a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                        authenticate(response);
3897a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                        break;
3907a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    }
3917a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                }
3927a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
3937a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                if (result != OK || response->mStatusCode != 200) {
3947a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    (new AMessage('quit', id()))->post();
3957a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    break;
3967a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                }
3977a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
3987a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                unsigned rtpPort;
3997a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                ARTPConnection::MakePortPair(&mRTPSocket, &mRTCPSocket, &rtpPort);
4007a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4017a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                // (new AMessage('poll', id()))->post();
4027a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4037a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                AString request;
4047a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append("SETUP ");
4057a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append(mTrackURL);
4067a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append(" RTSP/1.0\r\n");
4077a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4087a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                addAuthentication(&request, "SETUP", mTrackURL.c_str());
4097a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4107a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append("Transport: RTP/AVP;unicast;client_port=");
4117a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append(rtpPort);
4127a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append("-");
4137a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append(rtpPort + 1);
4147a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append(";mode=record\r\n");
4157a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append("\r\n");
4167a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4177a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                sp<AMessage> reply = new AMessage('setu', id());
4187a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                mConn->sendRequest(request.c_str(), reply);
4197a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                break;
4207a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            }
4217a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4227a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#if 0
4237a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            case 'poll':
4247a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            {
4257a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                fd_set rs;
4267a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                FD_ZERO(&rs);
4277a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                FD_SET(mRTCPSocket, &rs);
4287a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4297a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                struct timeval tv;
4307a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                tv.tv_sec = 0;
4317a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                tv.tv_usec = 0;
4327a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4337a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                int res = select(mRTCPSocket + 1, &rs, NULL, NULL, &tv);
4347a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4357a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                if (res == 1) {
4367a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    sp<ABuffer> buffer = new ABuffer(65536);
4377a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    ssize_t n = recv(mRTCPSocket, buffer->data(), buffer->size(), 0);
4387a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4397a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    if (n <= 0) {
4407a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                        LOG(ERROR) << "recv returned " << n;
4417a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    } else {
4427a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                        LOG(INFO) << "recv returned " << n << " bytes of data.";
4437a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4447a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                        hexdump(buffer->data(), n);
4457a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    }
4467a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                }
4477a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4487a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                msg->post(50000);
4497a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                break;
4507a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            }
4517a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#endif
4527a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4537a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            case 'setu':
4547a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            {
4557a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                int32_t result;
4567a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK(msg->findInt32("result", &result));
4577a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4587a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                LOG(INFO) << "SETUP completed with result "
4597a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                     << result << " (" << strerror(-result) << ")";
4607a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4617a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                sp<RefBase> obj;
4627a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK(msg->findObject("response", &obj));
4637a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                sp<ARTSPResponse> response;
4647a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4657a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                if (result == OK) {
4667a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    response = static_cast<ARTSPResponse *>(obj.get());
4677a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    CHECK(response != NULL);
4687a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                }
4697a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4707a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                if (result != OK || response->mStatusCode != 200) {
4717a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    (new AMessage('quit', id()))->post();
4727a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    break;
4737a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                }
4747a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4757a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                ssize_t i = response->mHeaders.indexOfKey("session");
4767a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK_GE(i, 0);
4777a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                mSessionID = response->mHeaders.valueAt(i);
4787a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                i = mSessionID.find(";");
4797a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                if (i >= 0) {
4807a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    // Remove options, i.e. ";timeout=90"
4817a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    mSessionID.erase(i, mSessionID.size() - i);
4827a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                }
4837a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4847a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                i = response->mHeaders.indexOfKey("transport");
4857a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK_GE(i, 0);
4867a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                AString transport = response->mHeaders.valueAt(i);
4877a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4887a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                LOG(INFO) << "transport = '" << transport << "'";
4897a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4907a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                AString value;
4917a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK(GetAttribute(transport.c_str(), "server_port", &value));
4927a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4937a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                unsigned rtpPort, rtcpPort;
4947a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK_EQ(sscanf(value.c_str(), "%u-%u", &rtpPort, &rtcpPort), 2);
4957a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4967a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK(GetAttribute(transport.c_str(), "source", &value));
4977a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
4987a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                memset(mRemoteAddr.sin_zero, 0, sizeof(mRemoteAddr.sin_zero));
4997a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                mRemoteAddr.sin_family = AF_INET;
5007a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                mRemoteAddr.sin_addr.s_addr = inet_addr(value.c_str());
5017a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                mRemoteAddr.sin_port = htons(rtpPort);
5027a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
5037a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                mRemoteRTCPAddr = mRemoteAddr;
5047a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                mRemoteRTCPAddr.sin_port = htons(rtpPort + 1);
5057a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
5067a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK_EQ(0, connect(mRTPSocket,
5077a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                                    (const struct sockaddr *)&mRemoteAddr,
5087a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                                    sizeof(mRemoteAddr)));
5097a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
5107a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK_EQ(0, connect(mRTCPSocket,
5117a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                                    (const struct sockaddr *)&mRemoteRTCPAddr,
5127a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                                    sizeof(mRemoteRTCPAddr)));
5137a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
5147a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                uint32_t x = ntohl(mRemoteAddr.sin_addr.s_addr);
5157a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                LOG(INFO) << "sending data to "
5167a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                     << (x >> 24)
5177a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                     << "."
5187a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                     << ((x >> 16) & 0xff)
5197a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                     << "."
5207a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                     << ((x >> 8) & 0xff)
5217a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                     << "."
5227a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                     << (x & 0xff)
5237a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                     << ":"
5247a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                     << rtpPort;
5257a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
5267a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                AString request;
5277a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append("RECORD ");
5287a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append(mStreamURL);
5297a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append(" RTSP/1.0\r\n");
5307a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
5317a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                addAuthentication(&request, "RECORD", mStreamURL.c_str());
5327a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
5337a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append("Session: ");
5347a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append(mSessionID);
5357a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append("\r\n");
5367a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append("\r\n");
5377a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
5387a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                sp<AMessage> reply = new AMessage('reco', id());
5397a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                mConn->sendRequest(request.c_str(), reply);
5407a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                break;
5417a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            }
5427a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
5437a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            case 'reco':
5447a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            {
5457a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                int32_t result;
5467a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK(msg->findInt32("result", &result));
5477a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
5487a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                LOG(INFO) << "RECORD completed with result "
5497a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                     << result << " (" << strerror(-result) << ")";
5507a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
5517a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                sp<RefBase> obj;
5527a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK(msg->findObject("response", &obj));
5537a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                sp<ARTSPResponse> response;
5547a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
5557a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                if (result == OK) {
5567a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    response = static_cast<ARTSPResponse *>(obj.get());
5577a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    CHECK(response != NULL);
5587a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                }
5597a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
5607a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                if (result != OK) {
5617a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    (new AMessage('quit', id()))->post();
5627a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    break;
5637a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                }
5647a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
5657a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                (new AMessage('more', id()))->post();
5667a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                (new AMessage('sr  ', id()))->post();
5677a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                (new AMessage('aliv', id()))->post(30000000ll);
5687a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                break;
5697a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            }
5707a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
5717a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            case 'aliv':
5727a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            {
5737a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                if (!mConnected) {
5747a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    break;
5757a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                }
5767a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
5777a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                AString request;
5787a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append("OPTIONS ");
5797a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append(mStreamURL);
5807a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append(" RTSP/1.0\r\n");
5817a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
5827a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                addAuthentication(&request, "RECORD", mStreamURL.c_str());
5837a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
5847a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append("Session: ");
5857a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append(mSessionID);
5867a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append("\r\n");
5877a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append("\r\n");
5887a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
5897a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                sp<AMessage> reply = new AMessage('opts', id());
5907a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                mConn->sendRequest(request.c_str(), reply);
5917a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                break;
5927a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            }
5937a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
5947a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            case 'opts':
5957a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            {
5967a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                int32_t result;
5977a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK(msg->findInt32("result", &result));
5987a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
5997a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                LOG(INFO) << "OPTIONS completed with result "
6007a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                     << result << " (" << strerror(-result) << ")";
6017a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
6027a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                if (!mConnected) {
6037a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    break;
6047a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                }
6057a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
6067a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                (new AMessage('aliv', id()))->post(30000000ll);
6077a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                break;
6087a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            }
6097a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
6107a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            case 'more':
6117a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            {
6127a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                if (!mConnected) {
6137a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    break;
6147a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                }
6157a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
6167a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                sp<ABuffer> buffer = new ABuffer(65536);
6177a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                uint8_t *data = buffer->data();
6187a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                data[0] = 0x80;
6197a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                data[1] = (1 << 7) | PT;  // M-bit
6207a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                data[2] = (mSeqNo >> 8) & 0xff;
6217a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                data[3] = mSeqNo & 0xff;
6227a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                data[8] = mSourceID >> 24;
6237a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                data[9] = (mSourceID >> 16) & 0xff;
6247a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                data[10] = (mSourceID >> 8) & 0xff;
6257a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                data[11] = mSourceID & 0xff;
6267a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
6277a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#ifdef ANDROID
6287a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                MediaBuffer *mediaBuf = NULL;
6297a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                for (;;) {
6307a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    CHECK_EQ(mEncoder->read(&mediaBuf), (status_t)OK);
6317a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    if (mediaBuf->range_length() > 0) {
6327a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                        break;
6337a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    }
6347a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    mediaBuf->release();
6357a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    mediaBuf = NULL;
6367a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                }
6377a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
6387a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                int64_t timeUs;
6397a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK(mediaBuf->meta_data()->findInt64(kKeyTime, &timeUs));
6407a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
6417a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll);
6427a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
6437a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                const uint8_t *mediaData =
6447a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
6457a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
6467a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK(!memcmp("\x00\x00\x00\x01", mediaData, 4));
6477a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
6487a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK_LE(mediaBuf->range_length() - 4 + 12, buffer->size());
6497a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
6507a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                memcpy(&data[12],
6517a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                       mediaData + 4, mediaBuf->range_length() - 4);
6527a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
6537a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                buffer->setRange(0, mediaBuf->range_length() - 4 + 12);
6547a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
6557a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                mediaBuf->release();
6567a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                mediaBuf = NULL;
6577a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#else
6587a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                uint32_t rtpTime = mRTPTimeBase + mNumRTPSent * 128;
6597a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                memset(&data[12], 0, 128);
6607a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                buffer->setRange(0, 12 + 128);
6617a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#endif
6627a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
6637a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                data[4] = rtpTime >> 24;
6647a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                data[5] = (rtpTime >> 16) & 0xff;
6657a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                data[6] = (rtpTime >> 8) & 0xff;
6667a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                data[7] = rtpTime & 0xff;
6677a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
6687a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                ssize_t n = send(
6697a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                        mRTPSocket, data, buffer->size(), 0);
6707a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                if (n < 0) {
6717a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    LOG(ERROR) << "send failed (" << strerror(errno) << ")";
6727a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                }
6737a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK_EQ(n, (ssize_t)buffer->size());
6747a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
6757a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                ++mSeqNo;
6767a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
6777a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                ++mNumRTPSent;
6787a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                mNumRTPOctetsSent += buffer->size() - 12;
6797a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
6807a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                mLastRTPTime = rtpTime;
6817a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                mLastNTPTime = ntpTime();
6827a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
6837a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#ifdef ANDROID
6847a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                if (mNumRTPSent < 60 * 25) {  // 60 secs worth
6857a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    msg->post(40000);
6867a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#else
6877a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                if (mNumRTPOctetsSent < 8000 * 60) {
6887a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    msg->post(1000000ll * 128 / 8000);
6897a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#endif
6907a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                } else {
6917a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    LOG(INFO) << "That's enough, pausing.";
6927a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
6937a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    AString request;
6947a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    request.append("PAUSE ");
6957a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    request.append(mStreamURL);
6967a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    request.append(" RTSP/1.0\r\n");
6977a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
6987a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    addAuthentication(&request, "PAUSE", mStreamURL.c_str());
6997a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7007a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    request.append("Session: ");
7017a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    request.append(mSessionID);
7027a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    request.append("\r\n");
7037a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    request.append("\r\n");
7047a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7057a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    sp<AMessage> reply = new AMessage('paus', id());
7067a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    mConn->sendRequest(request.c_str(), reply);
7077a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                }
7087a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                break;
7097a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            }
7107a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7117a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            case 'sr  ':
7127a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            {
7137a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                if (!mConnected) {
7147a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    break;
7157a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                }
7167a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7177a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                sp<ABuffer> buffer = new ABuffer(65536);
7187a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                buffer->setRange(0, 0);
7197a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7207a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                addSR(buffer);
7217a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                addSDES(buffer);
7227a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7237a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                uint8_t *data = buffer->data();
7247a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                ssize_t n = send(
7257a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                        mRTCPSocket, data, buffer->size(), 0);
7267a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK_EQ(n, (ssize_t)buffer->size());
7277a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7287a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                msg->post(3000000);
7297a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                break;
7307a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            }
7317a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7327a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            case 'paus':
7337a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            {
7347a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                int32_t result;
7357a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK(msg->findInt32("result", &result));
7367a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7377a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                LOG(INFO) << "PAUSE completed with result "
7387a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                     << result << " (" << strerror(-result) << ")";
7397a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7407a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                sp<RefBase> obj;
7417a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK(msg->findObject("response", &obj));
7427a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                sp<ARTSPResponse> response;
7437a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7447a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                AString request;
7457a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append("TEARDOWN ");
7467a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append(mStreamURL);
7477a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append(" RTSP/1.0\r\n");
7487a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7497a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                addAuthentication(&request, "TEARDOWN", mStreamURL.c_str());
7507a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7517a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append("Session: ");
7527a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append(mSessionID);
7537a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append("\r\n");
7547a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                request.append("\r\n");
7557a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7567a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                sp<AMessage> reply = new AMessage('tear', id());
7577a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                mConn->sendRequest(request.c_str(), reply);
7587a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                break;
7597a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            }
7607a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7617a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            case 'tear':
7627a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            {
7637a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                int32_t result;
7647a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK(msg->findInt32("result", &result));
7657a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7667a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                LOG(INFO) << "TEARDOWN completed with result "
7677a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                     << result << " (" << strerror(-result) << ")";
7687a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7697a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                sp<RefBase> obj;
7707a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                CHECK(msg->findObject("response", &obj));
7717a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                sp<ARTSPResponse> response;
7727a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7737a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                if (result == OK) {
7747a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    response = static_cast<ARTSPResponse *>(obj.get());
7757a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    CHECK(response != NULL);
7767a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                }
7777a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7787a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                (new AMessage('quit', id()))->post();
7797a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                break;
7807a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            }
7817a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7827a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            case 'disc':
7837a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            {
7847a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                LOG(INFO) << "disconnect completed";
7857a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7867a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                mConnected = false;
7877a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                (new AMessage('quit', id()))->post();
7887a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                break;
7897a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            }
7907a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7917a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            case 'quit':
7927a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            {
7937a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                if (mConnected) {
7947a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    mConn->disconnect(new AMessage('disc', id()));
7957a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    break;
7967a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                }
7977a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
7987a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                if (mRTPSocket >= 0) {
7997a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    close(mRTPSocket);
8007a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    mRTPSocket = -1;
8017a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                }
8027a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
8037a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                if (mRTCPSocket >= 0) {
8047a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    close(mRTCPSocket);
8057a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    mRTCPSocket = -1;
8067a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                }
8077a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
8087a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#ifdef ANDROID
8097a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                mEncoder->stop();
8107a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                mEncoder.clear();
8117a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#endif
8127a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
8137a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                mLooper->stop();
8147a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                break;
8157a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            }
8167a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
8177a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            default:
8187a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                TRESPASS();
8197a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        }
8207a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    }
8217a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
8227a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huberprotected:
8237a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    virtual ~MyTransmitter() {
8247a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    }
8257a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
8267a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huberprivate:
8277a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    enum AuthType {
8287a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        NONE,
8297a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        BASIC,
8307a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        DIGEST
8317a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    };
8327a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
8337a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    AString mServerURL;
8347a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    AString mTrackURL;
8357a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    AString mStreamURL;
8367a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
8377a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    sp<ALooper> mLooper;
8387a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    sp<ARTSPConnection> mConn;
8397a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    bool mConnected;
8407a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    uint32_t mServerIP;
8417a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    AuthType mAuthType;
8427a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    AString mNonce;
8437a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    AString mSessionID;
8447a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    int mRTPSocket, mRTCPSocket;
8457a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    uint32_t mSourceID;
8467a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    uint32_t mSeqNo;
8477a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    uint32_t mRTPTimeBase;
8487a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    struct sockaddr_in mRemoteAddr;
8497a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    struct sockaddr_in mRemoteRTCPAddr;
8507a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    size_t mNumSamplesSent;
8517a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    uint32_t mNumRTPSent;
8527a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    uint32_t mNumRTPOctetsSent;
8537a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    uint32_t mLastRTPTime;
8547a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    uint64_t mLastNTPTime;
8557a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
8567a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#ifdef ANDROID
8577a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    sp<MediaSource> mEncoder;
8587a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    AString mSeqParamSet;
8597a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    AString mPicParamSet;
8607a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
8617a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    void makeH264SPropParamSets(MediaBuffer *buffer) {
8627a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        static const char kStartCode[] = "\x00\x00\x00\x01";
8637a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
8647a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        const uint8_t *data =
8657a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            (const uint8_t *)buffer->data() + buffer->range_offset();
8667a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        size_t size = buffer->range_length();
8677a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
8687a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        CHECK_GE(size, 0u);
8697a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        CHECK(!memcmp(kStartCode, data, 4));
8707a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
8717a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data += 4;
8727a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        size -= 4;
8737a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
8747a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        size_t startCodePos = 0;
8757a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        while (startCodePos + 3 < size
8767a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                && memcmp(kStartCode, &data[startCodePos], 4)) {
8777a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            ++startCodePos;
8787a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        }
8797a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
8807a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        CHECK_LT(startCodePos + 3, size);
8817a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
8827a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        encodeBase64(data, startCodePos, &mSeqParamSet);
8837a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
8847a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        encodeBase64(&data[startCodePos + 4], size - startCodePos - 4,
8857a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                     &mPicParamSet);
8867a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    }
8877a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#endif
8887a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
8897a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    void addSR(const sp<ABuffer> &buffer) {
8907a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        uint8_t *data = buffer->data() + buffer->size();
8917a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
8927a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[0] = 0x80 | 0;
8937a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[1] = 200;  // SR
8947a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[2] = 0;
8957a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[3] = 6;
8967a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[4] = mSourceID >> 24;
8977a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[5] = (mSourceID >> 16) & 0xff;
8987a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[6] = (mSourceID >> 8) & 0xff;
8997a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[7] = mSourceID & 0xff;
9007a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
9017a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[8] = mLastNTPTime >> (64 - 8);
9027a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[9] = (mLastNTPTime >> (64 - 16)) & 0xff;
9037a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[10] = (mLastNTPTime >> (64 - 24)) & 0xff;
9047a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[11] = (mLastNTPTime >> 32) & 0xff;
9057a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[12] = (mLastNTPTime >> 24) & 0xff;
9067a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[13] = (mLastNTPTime >> 16) & 0xff;
9077a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[14] = (mLastNTPTime >> 8) & 0xff;
9087a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[15] = mLastNTPTime & 0xff;
9097a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
9107a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[16] = (mLastRTPTime >> 24) & 0xff;
9117a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[17] = (mLastRTPTime >> 16) & 0xff;
9127a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[18] = (mLastRTPTime >> 8) & 0xff;
9137a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[19] = mLastRTPTime & 0xff;
9147a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
9157a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[20] = mNumRTPSent >> 24;
9167a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[21] = (mNumRTPSent >> 16) & 0xff;
9177a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[22] = (mNumRTPSent >> 8) & 0xff;
9187a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[23] = mNumRTPSent & 0xff;
9197a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
9207a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[24] = mNumRTPOctetsSent >> 24;
9217a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[25] = (mNumRTPOctetsSent >> 16) & 0xff;
9227a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[26] = (mNumRTPOctetsSent >> 8) & 0xff;
9237a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[27] = mNumRTPOctetsSent & 0xff;
9247a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
9257a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        buffer->setRange(buffer->offset(), buffer->size() + 28);
9267a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    }
9277a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
9287a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    void addSDES(const sp<ABuffer> &buffer) {
9297a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        uint8_t *data = buffer->data() + buffer->size();
9307a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[0] = 0x80 | 1;
9317a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[1] = 202;  // SDES
9327a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[4] = mSourceID >> 24;
9337a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[5] = (mSourceID >> 16) & 0xff;
9347a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[6] = (mSourceID >> 8) & 0xff;
9357a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[7] = mSourceID & 0xff;
9367a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
9377a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        size_t offset = 8;
9387a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
9397a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[offset++] = 1;  // CNAME
9407a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
9417a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        static const char *kCNAME = "andih@laptop";
9427a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[offset++] = strlen(kCNAME);
9437a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
9447a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        memcpy(&data[offset], kCNAME, strlen(kCNAME));
9457a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        offset += strlen(kCNAME);
9467a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
9477a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[offset++] = 7;  // NOTE
9487a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
9497a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        static const char *kNOTE = "Hell's frozen over.";
9507a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[offset++] = strlen(kNOTE);
9517a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
9527a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        memcpy(&data[offset], kNOTE, strlen(kNOTE));
9537a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        offset += strlen(kNOTE);
9547a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
9557a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[offset++] = 0;
9567a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
9577a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        if ((offset % 4) > 0) {
9587a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            size_t count = 4 - (offset % 4);
9597a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            switch (count) {
9607a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                case 3:
9617a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    data[offset++] = 0;
9627a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                case 2:
9637a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    data[offset++] = 0;
9647a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                case 1:
9657a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber                    data[offset++] = 0;
9667a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber            }
9677a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        }
9687a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
9697a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        size_t numWords = (offset / 4) - 1;
9707a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[2] = numWords >> 8;
9717a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        data[3] = numWords & 0xff;
9727a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
9737a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber        buffer->setRange(buffer->offset(), buffer->size() + offset);
9747a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    }
9757a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
9767a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(MyTransmitter);
9777a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber};
9787a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
9797a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber}  // namespace android
9807a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber
9817a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#endif  // MY_TRANSMITTER_H_
982