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