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