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