1cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber/* 2cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * Copyright (C) 2010 The Android Open Source Project 3cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * 4cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * you may not use this file except in compliance with the License. 6cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * You may obtain a copy of the License at 7cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * 8cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * 10cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * Unless required by applicable law or agreed to in writing, software 11cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * See the License for the specific language governing permissions and 14cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * limitations under the License. 15cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber */ 16cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 17cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#ifndef MY_TRANSMITTER_H_ 18cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 19cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#define MY_TRANSMITTER_H_ 20cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 21cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "ARTPConnection.h" 22cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 23cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <arpa/inet.h> 24cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <sys/socket.h> 25cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 26cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <openssl/md5.h> 27cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 28cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ADebug.h> 29cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/base64.h> 30cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/hexdump.h> 31cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 32cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#ifdef ANDROID 33cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "VideoSource.h" 34cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 35cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/OMXClient.h> 36cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/OMXCodec.h> 37cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#endif 38cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 39cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubernamespace android { 40cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 41cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#define TRACK_SUFFIX "trackid=1" 42cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#define PT 96 43cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#define PT_STR "96" 44cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 45cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#define USERNAME "bcast" 46cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#define PASSWORD "test" 47cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 48cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstatic int uniformRand(int limit) { 49cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return ((double)rand() * limit) / RAND_MAX; 50cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber} 51cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 52cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstatic bool GetAttribute(const char *s, const char *key, AString *value) { 53cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber value->clear(); 54cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 55cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t keyLen = strlen(key); 56cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 57cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber for (;;) { 58cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber const char *colonPos = strchr(s, ';'); 59cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 60cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t len = 61cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber (colonPos == NULL) ? strlen(s) : colonPos - s; 62cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 63cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) { 64cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber value->setTo(&s[keyLen + 1], len - keyLen - 1); 65cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return true; 66cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 67cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 68cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (colonPos == NULL) { 69cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return false; 70cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 71cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 72cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber s = colonPos + 1; 73cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 74cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber} 75cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 76cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstruct MyTransmitter : public AHandler { 77cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber MyTransmitter(const char *url, const sp<ALooper> &looper) 78cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber : mServerURL(url), 79cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mLooper(looper), 80cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn(new ARTSPConnection), 81cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConnected(false), 82cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mAuthType(NONE), 83cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mRTPSocket(-1), 84cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mRTCPSocket(-1), 85cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSourceID(rand()), 86cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSeqNo(uniformRand(65536)), 87cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mRTPTimeBase(rand()), 88cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mNumSamplesSent(0), 89cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mNumRTPSent(0), 90cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mNumRTPOctetsSent(0), 91cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mLastRTPTime(0), 92cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mLastNTPTime(0) { 93cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mStreamURL = mServerURL; 94cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mStreamURL.append("/bazong.sdp"); 95cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 96cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mTrackURL = mStreamURL; 97cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mTrackURL.append("/"); 98cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mTrackURL.append(TRACK_SUFFIX); 99cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 100cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mLooper->registerHandler(this); 101cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mLooper->registerHandler(mConn); 102cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 103cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('conn', id()); 104cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->connect(mServerURL.c_str(), reply); 105cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 106cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#ifdef ANDROID 107cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int width = 640; 108cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int height = 480; 109cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 110cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<MediaSource> source = new VideoSource(width, height); 111cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 112cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<MetaData> encMeta = new MetaData; 113cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber encMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); 114cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber encMeta->setInt32(kKeyWidth, width); 115cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber encMeta->setInt32(kKeyHeight, height); 116cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 117cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber OMXClient client; 118cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber client.connect(); 119cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 120cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mEncoder = OMXCodec::Create( 121cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber client.interface(), encMeta, 122cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber true /* createEncoder */, source); 123cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 124cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mEncoder->start(); 125cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 126cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber MediaBuffer *buffer; 127cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_EQ(mEncoder->read(&buffer), (status_t)OK); 128cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(buffer != NULL); 129cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 130cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber makeH264SPropParamSets(buffer); 131cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 132cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber buffer->release(); 133cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber buffer = NULL; 134cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#endif 135cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 136cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 137cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint64_t ntpTime() { 138cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber struct timeval tv; 139cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber gettimeofday(&tv, NULL); 140cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 141cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint64_t nowUs = tv.tv_sec * 1000000ll + tv.tv_usec; 142cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 143cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber nowUs += ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll; 144cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 145cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint64_t hi = nowUs / 1000000ll; 146cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint64_t lo = ((1ll << 32) * (nowUs % 1000000ll)) / 1000000ll; 147cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 148cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return (hi << 32) | lo; 149cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 150cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 151cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber void issueAnnounce() { 152cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString sdp; 153cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp = "v=0\r\n"; 154cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 155cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append("o=- "); 156cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 157cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint64_t ntp = ntpTime(); 158cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append(ntp); 159cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append(" "); 160cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append(ntp); 161cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append(" IN IP4 127.0.0.0\r\n"); 162cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 163cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append( 164cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber "s=Sample\r\n" 165cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber "i=Playing around with ANNOUNCE\r\n" 166cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber "c=IN IP4 "); 167cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 168cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber struct in_addr addr; 169cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber addr.s_addr = htonl(mServerIP); 170cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 171cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append(inet_ntoa(addr)); 172cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 173cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append( 174cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber "\r\n" 175cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber "t=0 0\r\n" 176cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber "a=range:npt=now-\r\n"); 177cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 178cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#ifdef ANDROID 179cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<MetaData> meta = mEncoder->getFormat(); 180cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t width, height; 181cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(meta->findInt32(kKeyWidth, &width)); 182cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(meta->findInt32(kKeyHeight, &height)); 183cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 184cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append( 185cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber "m=video 0 RTP/AVP " PT_STR "\r\n" 186cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber "b=AS 320000\r\n" 187cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber "a=rtpmap:" PT_STR " H264/90000\r\n"); 188cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 189cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append("a=cliprect 0,0,"); 190cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append(height); 191cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append(","); 192cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append(width); 193cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append("\r\n"); 194cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 195cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append( 196cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber "a=framesize:" PT_STR " "); 197cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append(width); 198cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append("-"); 199cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append(height); 200cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append("\r\n"); 201cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 202cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append( 203cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber "a=fmtp:" PT_STR " profile-level-id=42C015;sprop-parameter-sets="); 204cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 205cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append(mSeqParamSet); 206cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append(","); 207cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append(mPicParamSet); 208cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append(";packetization-mode=1\r\n"); 209cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#else 210cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append( 211cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber "m=audio 0 RTP/AVP " PT_STR "\r\n" 212cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber "a=rtpmap:" PT_STR " L8/8000/1\r\n"); 213cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#endif 214cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 215cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sdp.append("a=control:" TRACK_SUFFIX "\r\n"); 216cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 217cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request; 218cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("ANNOUNCE "); 219cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mStreamURL); 220cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 221cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 222cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber addAuthentication(&request, "ANNOUNCE", mStreamURL.c_str()); 223cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 224cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Content-Type: application/sdp\r\n"); 225cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Content-Length: "); 226cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(sdp.size()); 227cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 228cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 229cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 230cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(sdp); 231cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 232cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('anno', id()); 233cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 234cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 235cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 236cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber void H(const AString &s, AString *out) { 237cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->clear(); 238cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 239cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber MD5_CTX m; 240cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber MD5_Init(&m); 241cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber MD5_Update(&m, s.c_str(), s.size()); 242cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 243cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint8_t key[16]; 244cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber MD5_Final(key, &m); 245cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 246cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber for (size_t i = 0; i < 16; ++i) { 247cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber char nibble = key[i] >> 4; 248cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (nibble <= 9) { 249cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber nibble += '0'; 250cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 251cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber nibble += 'a' - 10; 252cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 253cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->append(&nibble, 1); 254cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 255cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber nibble = key[i] & 0x0f; 256cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (nibble <= 9) { 257cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber nibble += '0'; 258cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 259cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber nibble += 'a' - 10; 260cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 261cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->append(&nibble, 1); 262cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 263cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 264cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 265cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber void authenticate(const sp<ARTSPResponse> &response) { 266cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ssize_t i = response->mHeaders.indexOfKey("www-authenticate"); 267cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_GE(i, 0); 268cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 269cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString value = response->mHeaders.valueAt(i); 270cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 271cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (!strncmp(value.c_str(), "Basic", 5)) { 272cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mAuthType = BASIC; 273cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 274cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(!strncmp(value.c_str(), "Digest", 6)); 275cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mAuthType = DIGEST; 276cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 277cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber i = value.find("nonce="); 278cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_GE(i, 0); 279cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_EQ(value.c_str()[i + 6], '\"'); 280cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ssize_t j = value.find("\"", i + 7); 281cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_GE(j, 0); 282cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 283cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mNonce.setTo(value, i + 7, j - i - 7); 284cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 285cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 286cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber issueAnnounce(); 287cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 288cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 289cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber void addAuthentication( 290cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString *request, const char *method, const char *url) { 291cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (mAuthType == NONE) { 292cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return; 293cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 294cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 295cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (mAuthType == BASIC) { 296cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request->append("Authorization: Basic YmNhc3Q6dGVzdAo=\r\n"); 297cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return; 298cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 299cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 300cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_EQ((int)mAuthType, (int)DIGEST); 301cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 302cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString A1; 303cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber A1.append(USERNAME); 304cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber A1.append(":"); 305cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber A1.append("Streaming Server"); 306cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber A1.append(":"); 307cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber A1.append(PASSWORD); 308cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 309cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString A2; 310cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber A2.append(method); 311cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber A2.append(":"); 312cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber A2.append(url); 313cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 314cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString HA1, HA2; 315cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber H(A1, &HA1); 316cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber H(A2, &HA2); 317cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 318cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString tmp; 319cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber tmp.append(HA1); 320cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber tmp.append(":"); 321cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber tmp.append(mNonce); 322cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber tmp.append(":"); 323cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber tmp.append(HA2); 324cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 325cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString digest; 326cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber H(tmp, &digest); 327cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 328cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request->append("Authorization: Digest "); 329cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request->append("nonce=\""); 330cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request->append(mNonce); 331cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request->append("\", "); 332cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request->append("username=\"" USERNAME "\", "); 333cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request->append("uri=\""); 334cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request->append(url); 335cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request->append("\", "); 336cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request->append("response=\""); 337cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request->append(digest); 338cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request->append("\""); 339cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request->append("\r\n"); 340cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 341cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 342cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber virtual void onMessageReceived(const sp<AMessage> &msg) { 343cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber switch (msg->what()) { 344cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'conn': 345cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 346cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 347cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 348cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 349cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "connection request completed with result " 350cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << result << " (" << strerror(-result) << ")"; 351cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 352cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result != OK) { 353cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber (new AMessage('quit', id()))->post(); 354cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 355cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 356cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 357cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConnected = true; 358cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 359cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("server-ip", (int32_t *)&mServerIP)); 360cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 361cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber issueAnnounce(); 362cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 363cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 364cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 365cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'anno': 366cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 367cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 368cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 369cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 370cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "ANNOUNCE completed with result " 371cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << result << " (" << strerror(-result) << ")"; 372cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 373cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 374cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("response", &obj)); 375cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPResponse> response; 376cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 377cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result == OK) { 378cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber response = static_cast<ARTSPResponse *>(obj.get()); 379cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(response != NULL); 380cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 381cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (response->mStatusCode == 401) { 382cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (mAuthType != NONE) { 383cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "FAILED to authenticate"; 384cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber (new AMessage('quit', id()))->post(); 385cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 386cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 387cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 388cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber authenticate(response); 389cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 390cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 391cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 392cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 393cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result != OK || response->mStatusCode != 200) { 394cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber (new AMessage('quit', id()))->post(); 395cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 396cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 397cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 398cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber unsigned rtpPort; 399cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ARTPConnection::MakePortPair(&mRTPSocket, &mRTCPSocket, &rtpPort); 400cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 401cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // (new AMessage('poll', id()))->post(); 402cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 403cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request; 404cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("SETUP "); 405cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mTrackURL); 406cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 407cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 408cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber addAuthentication(&request, "SETUP", mTrackURL.c_str()); 409cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 410cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Transport: RTP/AVP;unicast;client_port="); 411cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(rtpPort); 412cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("-"); 413cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(rtpPort + 1); 414cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(";mode=record\r\n"); 415cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 416cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 417cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('setu', id()); 418cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 419cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 420cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 421cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 422cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#if 0 423cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'poll': 424cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 425cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber fd_set rs; 426cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber FD_ZERO(&rs); 427cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber FD_SET(mRTCPSocket, &rs); 428cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 429cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber struct timeval tv; 430cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber tv.tv_sec = 0; 431cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber tv.tv_usec = 0; 432cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 433cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int res = select(mRTCPSocket + 1, &rs, NULL, NULL, &tv); 434cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 435cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (res == 1) { 436cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ABuffer> buffer = new ABuffer(65536); 437cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ssize_t n = recv(mRTCPSocket, buffer->data(), buffer->size(), 0); 438cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 439cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (n <= 0) { 440cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(ERROR) << "recv returned " << n; 441cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 442cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "recv returned " << n << " bytes of data."; 443cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 444cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber hexdump(buffer->data(), n); 445cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 446cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 447cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 448cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber msg->post(50000); 449cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 450cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 451cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#endif 452cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 453cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'setu': 454cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 455cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 456cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 457cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 458cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "SETUP completed with result " 459cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << result << " (" << strerror(-result) << ")"; 460cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 461cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 462cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("response", &obj)); 463cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPResponse> response; 464cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 465cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result == OK) { 466cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber response = static_cast<ARTSPResponse *>(obj.get()); 467cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(response != NULL); 468cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 469cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 470cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result != OK || response->mStatusCode != 200) { 471cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber (new AMessage('quit', id()))->post(); 472cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 473cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 474cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 475cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ssize_t i = response->mHeaders.indexOfKey("session"); 476cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_GE(i, 0); 477cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionID = response->mHeaders.valueAt(i); 478cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber i = mSessionID.find(";"); 479cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (i >= 0) { 480cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // Remove options, i.e. ";timeout=90" 481cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionID.erase(i, mSessionID.size() - i); 482cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 483cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 484cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber i = response->mHeaders.indexOfKey("transport"); 485cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_GE(i, 0); 486cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString transport = response->mHeaders.valueAt(i); 487cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 488cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "transport = '" << transport << "'"; 489cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 490cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString value; 491cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(GetAttribute(transport.c_str(), "server_port", &value)); 492cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 493cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber unsigned rtpPort, rtcpPort; 494cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_EQ(sscanf(value.c_str(), "%u-%u", &rtpPort, &rtcpPort), 2); 495cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 496cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(GetAttribute(transport.c_str(), "source", &value)); 497cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 498cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber memset(mRemoteAddr.sin_zero, 0, sizeof(mRemoteAddr.sin_zero)); 499cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mRemoteAddr.sin_family = AF_INET; 500cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mRemoteAddr.sin_addr.s_addr = inet_addr(value.c_str()); 501cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mRemoteAddr.sin_port = htons(rtpPort); 502cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 503cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mRemoteRTCPAddr = mRemoteAddr; 504cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mRemoteRTCPAddr.sin_port = htons(rtpPort + 1); 505cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 506cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_EQ(0, connect(mRTPSocket, 507cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber (const struct sockaddr *)&mRemoteAddr, 508cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sizeof(mRemoteAddr))); 509cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 510cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_EQ(0, connect(mRTCPSocket, 511cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber (const struct sockaddr *)&mRemoteRTCPAddr, 512cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sizeof(mRemoteRTCPAddr))); 513cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 514cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint32_t x = ntohl(mRemoteAddr.sin_addr.s_addr); 515cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "sending data to " 516cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << (x >> 24) 517cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << "." 518cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << ((x >> 16) & 0xff) 519cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << "." 520cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << ((x >> 8) & 0xff) 521cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << "." 522cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << (x & 0xff) 523cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << ":" 524cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << rtpPort; 525cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 526cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request; 527cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("RECORD "); 528cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mStreamURL); 529cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 530cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 531cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber addAuthentication(&request, "RECORD", mStreamURL.c_str()); 532cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 533cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Session: "); 534cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionID); 535cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 536cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 537cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 538cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('reco', id()); 539cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 540cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 541cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 542cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 543cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'reco': 544cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 545cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 546cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 547cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 548cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "RECORD completed with result " 549cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << result << " (" << strerror(-result) << ")"; 550cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 551cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 552cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("response", &obj)); 553cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPResponse> response; 554cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 555cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result == OK) { 556cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber response = static_cast<ARTSPResponse *>(obj.get()); 557cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(response != NULL); 558cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 559cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 560cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result != OK) { 561cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber (new AMessage('quit', id()))->post(); 562cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 563cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 564cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 565cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber (new AMessage('more', id()))->post(); 566cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber (new AMessage('sr ', id()))->post(); 567cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber (new AMessage('aliv', id()))->post(30000000ll); 568cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 569cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 570cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 571cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'aliv': 572cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 573cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (!mConnected) { 574cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 575cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 576cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 577cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request; 578cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("OPTIONS "); 579cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mStreamURL); 580cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 581cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 582cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber addAuthentication(&request, "RECORD", mStreamURL.c_str()); 583cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 584cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Session: "); 585cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionID); 586cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 587cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 588cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 589cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('opts', id()); 590cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 591cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 592cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 593cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 594cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'opts': 595cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 596cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 597cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 598cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 599cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "OPTIONS completed with result " 600cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << result << " (" << strerror(-result) << ")"; 601cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 602cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (!mConnected) { 603cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 604cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 605cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 606cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber (new AMessage('aliv', id()))->post(30000000ll); 607cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 608cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 609cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 610cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'more': 611cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 612cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (!mConnected) { 613cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 614cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 615cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 616cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ABuffer> buffer = new ABuffer(65536); 617cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint8_t *data = buffer->data(); 618cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[0] = 0x80; 619cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[1] = (1 << 7) | PT; // M-bit 620cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[2] = (mSeqNo >> 8) & 0xff; 621cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[3] = mSeqNo & 0xff; 622cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[8] = mSourceID >> 24; 623cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[9] = (mSourceID >> 16) & 0xff; 624cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[10] = (mSourceID >> 8) & 0xff; 625cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[11] = mSourceID & 0xff; 626cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 627cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#ifdef ANDROID 628cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber MediaBuffer *mediaBuf = NULL; 629cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber for (;;) { 630cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_EQ(mEncoder->read(&mediaBuf), (status_t)OK); 631cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (mediaBuf->range_length() > 0) { 632cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 633cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 634cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mediaBuf->release(); 635cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mediaBuf = NULL; 636cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 637cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 638cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int64_t timeUs; 639cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(mediaBuf->meta_data()->findInt64(kKeyTime, &timeUs)); 640cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 641cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll); 642cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 643cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber const uint8_t *mediaData = 644cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset(); 645cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 646cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(!memcmp("\x00\x00\x00\x01", mediaData, 4)); 647cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 648cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_LE(mediaBuf->range_length() - 4 + 12, buffer->size()); 649cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 650cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber memcpy(&data[12], 651cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mediaData + 4, mediaBuf->range_length() - 4); 652cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 653cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber buffer->setRange(0, mediaBuf->range_length() - 4 + 12); 654cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 655cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mediaBuf->release(); 656cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mediaBuf = NULL; 657cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#else 658cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint32_t rtpTime = mRTPTimeBase + mNumRTPSent * 128; 659cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber memset(&data[12], 0, 128); 660cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber buffer->setRange(0, 12 + 128); 661cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#endif 662cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 663cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[4] = rtpTime >> 24; 664cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[5] = (rtpTime >> 16) & 0xff; 665cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[6] = (rtpTime >> 8) & 0xff; 666cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[7] = rtpTime & 0xff; 667cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 668cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ssize_t n = send( 669cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mRTPSocket, data, buffer->size(), 0); 670cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (n < 0) { 671cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(ERROR) << "send failed (" << strerror(errno) << ")"; 672cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 673cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_EQ(n, (ssize_t)buffer->size()); 674cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 675cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ++mSeqNo; 676cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 677cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ++mNumRTPSent; 678cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mNumRTPOctetsSent += buffer->size() - 12; 679cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 680cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mLastRTPTime = rtpTime; 681cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mLastNTPTime = ntpTime(); 682cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 683cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#ifdef ANDROID 684cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (mNumRTPSent < 60 * 25) { // 60 secs worth 685cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber msg->post(40000); 686cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#else 687cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (mNumRTPOctetsSent < 8000 * 60) { 688cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber msg->post(1000000ll * 128 / 8000); 689cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#endif 690cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 691cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "That's enough, pausing."; 692cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 693cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request; 694cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("PAUSE "); 695cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mStreamURL); 696cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 697cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 698cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber addAuthentication(&request, "PAUSE", mStreamURL.c_str()); 699cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 700cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Session: "); 701cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionID); 702cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 703cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 704cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 705cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('paus', id()); 706cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 707cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 708cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 709cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 710cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 711cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'sr ': 712cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 713cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (!mConnected) { 714cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 715cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 716cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 717cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ABuffer> buffer = new ABuffer(65536); 718cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber buffer->setRange(0, 0); 719cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 720cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber addSR(buffer); 721cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber addSDES(buffer); 722cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 723cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint8_t *data = buffer->data(); 724cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ssize_t n = send( 725cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mRTCPSocket, data, buffer->size(), 0); 726cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_EQ(n, (ssize_t)buffer->size()); 727cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 728cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber msg->post(3000000); 729cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 730cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 731cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 732cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'paus': 733cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 734cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 735cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 736cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 737cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "PAUSE completed with result " 738cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << result << " (" << strerror(-result) << ")"; 739cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 740cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 741cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("response", &obj)); 742cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPResponse> response; 743cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 744cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request; 745cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("TEARDOWN "); 746cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mStreamURL); 747cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 748cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 749cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber addAuthentication(&request, "TEARDOWN", mStreamURL.c_str()); 750cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 751cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Session: "); 752cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionID); 753cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 754cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 755cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 756cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('tear', id()); 757cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 758cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 759cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 760cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 761cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'tear': 762cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 763cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 764cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 765cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 766cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "TEARDOWN completed with result " 767cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << result << " (" << strerror(-result) << ")"; 768cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 769cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 770cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("response", &obj)); 771cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPResponse> response; 772cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 773cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result == OK) { 774cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber response = static_cast<ARTSPResponse *>(obj.get()); 775cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(response != NULL); 776cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 777cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 778cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber (new AMessage('quit', id()))->post(); 779cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 780cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 781cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 782cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'disc': 783cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 784cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "disconnect completed"; 785cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 786cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConnected = false; 787cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber (new AMessage('quit', id()))->post(); 788cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 789cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 790cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 791cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'quit': 792cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 793cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (mConnected) { 794cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->disconnect(new AMessage('disc', id())); 795cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 796cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 797cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 798cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (mRTPSocket >= 0) { 799cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber close(mRTPSocket); 800cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mRTPSocket = -1; 801cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 802cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 803cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (mRTCPSocket >= 0) { 804cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber close(mRTCPSocket); 805cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mRTCPSocket = -1; 806cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 807cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 808cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#ifdef ANDROID 809cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mEncoder->stop(); 810cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mEncoder.clear(); 811cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#endif 812cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 813cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mLooper->stop(); 814cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 815cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 816cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 817cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber default: 818cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber TRESPASS(); 819cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 820cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 821cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 822cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberprotected: 823cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber virtual ~MyTransmitter() { 824cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 825cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 826cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberprivate: 827cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber enum AuthType { 828cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber NONE, 829cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber BASIC, 830cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber DIGEST 831cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber }; 832cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 833cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mServerURL; 834cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mTrackURL; 835cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mStreamURL; 836cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 837cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ALooper> mLooper; 838cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPConnection> mConn; 839cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber bool mConnected; 840cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint32_t mServerIP; 841cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AuthType mAuthType; 842cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mNonce; 843cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mSessionID; 844cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int mRTPSocket, mRTCPSocket; 845cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint32_t mSourceID; 846cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint32_t mSeqNo; 847cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint32_t mRTPTimeBase; 848cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber struct sockaddr_in mRemoteAddr; 849cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber struct sockaddr_in mRemoteRTCPAddr; 850cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t mNumSamplesSent; 851cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint32_t mNumRTPSent; 852cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint32_t mNumRTPOctetsSent; 853cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint32_t mLastRTPTime; 854cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint64_t mLastNTPTime; 855cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 856cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#ifdef ANDROID 857cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<MediaSource> mEncoder; 858cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mSeqParamSet; 859cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mPicParamSet; 860cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 861cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber void makeH264SPropParamSets(MediaBuffer *buffer) { 862cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static const char kStartCode[] = "\x00\x00\x00\x01"; 863cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 864cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber const uint8_t *data = 865cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 866cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t size = buffer->range_length(); 867cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 868cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_GE(size, 0u); 869cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(!memcmp(kStartCode, data, 4)); 870cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 871cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data += 4; 872cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size -= 4; 873cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 874cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t startCodePos = 0; 875cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber while (startCodePos + 3 < size 876cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber && memcmp(kStartCode, &data[startCodePos], 4)) { 877cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ++startCodePos; 878cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 879cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 880cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_LT(startCodePos + 3, size); 881cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 882cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber encodeBase64(data, startCodePos, &mSeqParamSet); 883cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 884cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber encodeBase64(&data[startCodePos + 4], size - startCodePos - 4, 885cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber &mPicParamSet); 886cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 887cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#endif 888cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 889cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber void addSR(const sp<ABuffer> &buffer) { 890cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint8_t *data = buffer->data() + buffer->size(); 891cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 892cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[0] = 0x80 | 0; 893cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[1] = 200; // SR 894cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[2] = 0; 895cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[3] = 6; 896cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[4] = mSourceID >> 24; 897cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[5] = (mSourceID >> 16) & 0xff; 898cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[6] = (mSourceID >> 8) & 0xff; 899cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[7] = mSourceID & 0xff; 900cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 901cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[8] = mLastNTPTime >> (64 - 8); 902cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[9] = (mLastNTPTime >> (64 - 16)) & 0xff; 903cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[10] = (mLastNTPTime >> (64 - 24)) & 0xff; 904cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[11] = (mLastNTPTime >> 32) & 0xff; 905cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[12] = (mLastNTPTime >> 24) & 0xff; 906cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[13] = (mLastNTPTime >> 16) & 0xff; 907cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[14] = (mLastNTPTime >> 8) & 0xff; 908cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[15] = mLastNTPTime & 0xff; 909cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 910cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[16] = (mLastRTPTime >> 24) & 0xff; 911cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[17] = (mLastRTPTime >> 16) & 0xff; 912cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[18] = (mLastRTPTime >> 8) & 0xff; 913cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[19] = mLastRTPTime & 0xff; 914cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 915cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[20] = mNumRTPSent >> 24; 916cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[21] = (mNumRTPSent >> 16) & 0xff; 917cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[22] = (mNumRTPSent >> 8) & 0xff; 918cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[23] = mNumRTPSent & 0xff; 919cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 920cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[24] = mNumRTPOctetsSent >> 24; 921cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[25] = (mNumRTPOctetsSent >> 16) & 0xff; 922cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[26] = (mNumRTPOctetsSent >> 8) & 0xff; 923cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[27] = mNumRTPOctetsSent & 0xff; 924cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 925cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber buffer->setRange(buffer->offset(), buffer->size() + 28); 926cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 927cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 928cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber void addSDES(const sp<ABuffer> &buffer) { 929cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint8_t *data = buffer->data() + buffer->size(); 930cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[0] = 0x80 | 1; 931cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[1] = 202; // SDES 932cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[4] = mSourceID >> 24; 933cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[5] = (mSourceID >> 16) & 0xff; 934cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[6] = (mSourceID >> 8) & 0xff; 935cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[7] = mSourceID & 0xff; 936cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 937cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t offset = 8; 938cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 939cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[offset++] = 1; // CNAME 940cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 941cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static const char *kCNAME = "andih@laptop"; 942cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[offset++] = strlen(kCNAME); 943cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 944cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber memcpy(&data[offset], kCNAME, strlen(kCNAME)); 945cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber offset += strlen(kCNAME); 946cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 947cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[offset++] = 7; // NOTE 948cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 949cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static const char *kNOTE = "Hell's frozen over."; 950cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[offset++] = strlen(kNOTE); 951cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 952cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber memcpy(&data[offset], kNOTE, strlen(kNOTE)); 953cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber offset += strlen(kNOTE); 954cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 955cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[offset++] = 0; 956cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 957cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if ((offset % 4) > 0) { 958cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t count = 4 - (offset % 4); 959cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber switch (count) { 960cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 3: 961cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[offset++] = 0; 962cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 2: 963cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[offset++] = 0; 964cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 1: 965cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[offset++] = 0; 966cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 967cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 968cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 969cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t numWords = (offset / 4) - 1; 970cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[2] = numWords >> 8; 971cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber data[3] = numWords & 0xff; 972cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 973cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber buffer->setRange(buffer->offset(), buffer->size() + offset); 974cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 975cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 976cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber DISALLOW_EVIL_CONSTRUCTORS(MyTransmitter); 977cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}; 978cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 979cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber} // namespace android 980cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 981cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#endif // MY_TRANSMITTER_H_ 982