1a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber/*
2a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber * Copyright 2013, The Android Open Source Project
3a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber *
4a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber * you may not use this file except in compliance with the License.
6a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber * You may obtain a copy of the License at
7a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber *
8a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber *     http://www.apache.org/licenses/LICENSE-2.0
9a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber *
10a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber * Unless required by applicable law or agreed to in writing, software
11a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber * See the License for the specific language governing permissions and
14a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber * limitations under the License.
15a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber */
16a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
17a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber//#define LOG_NDEBUG 0
18a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber#define LOG_TAG "RTPSender"
19a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber#include <utils/Log.h>
20a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
21a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber#include "RTPSender.h"
22a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
23a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber#include <media/stagefright/foundation/ABuffer.h>
24a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber#include <media/stagefright/foundation/ADebug.h>
25a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber#include <media/stagefright/foundation/AMessage.h>
268060060217ff16cd67c8f6a15c649f44c343acf0Andreas Huber#include <media/stagefright/foundation/ANetworkSession.h>
27a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber#include <media/stagefright/foundation/hexdump.h>
28a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber#include <media/stagefright/MediaErrors.h>
29a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber#include <media/stagefright/Utils.h>
30a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
31a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber#include "include/avc_utils.h"
32a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
33a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Hubernamespace android {
34a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
35a556c4822fc205db0d27834ba5b637c351d73ffaAndreas HuberRTPSender::RTPSender(
36a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        const sp<ANetworkSession> &netSession,
37a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        const sp<AMessage> &notify)
38a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    : mNetSession(netSession),
39a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber      mNotify(notify),
406e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber      mRTPMode(TRANSPORT_UNDEFINED),
416e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber      mRTCPMode(TRANSPORT_UNDEFINED),
42a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber      mRTPSessionID(0),
43a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber      mRTCPSessionID(0),
44a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber      mRTPConnected(false),
45a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber      mRTCPConnected(false),
46a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber      mLastNTPTime(0),
47a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber      mLastRTPTime(0),
48a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber      mNumRTPSent(0),
49a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber      mNumRTPOctetsSent(0),
50a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber      mNumSRsSent(0),
51a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber      mRTPSeqNo(0),
52a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber      mHistorySize(0) {
53a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber}
54a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
55a556c4822fc205db0d27834ba5b637c351d73ffaAndreas HuberRTPSender::~RTPSender() {
56a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    if (mRTCPSessionID != 0) {
57a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        mNetSession->destroySession(mRTCPSessionID);
58a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        mRTCPSessionID = 0;
59a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    }
60a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
61a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    if (mRTPSessionID != 0) {
62a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        mNetSession->destroySession(mRTPSessionID);
63a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        mRTPSessionID = 0;
64a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    }
65a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber}
66a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
67a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber// static
68a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huberint32_t RTPBase::PickRandomRTPPort() {
69a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    // Pick an even integer in range [1024, 65534)
70a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
71a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    static const size_t kRange = (65534 - 1024) / 2;
72a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
73a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    return (int32_t)(((float)(kRange + 1) * rand()) / RAND_MAX) * 2 + 1024;
74a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber}
75a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
76a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huberstatus_t RTPSender::initAsync(
77a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        const char *remoteHost,
78a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        int32_t remoteRTPPort,
796e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber        TransportMode rtpMode,
80a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        int32_t remoteRTCPPort,
816e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber        TransportMode rtcpMode,
82a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        int32_t *outLocalRTPPort) {
836e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber    if (mRTPMode != TRANSPORT_UNDEFINED
846e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber            || rtpMode == TRANSPORT_UNDEFINED
856e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber            || rtpMode == TRANSPORT_NONE
866e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber            || rtcpMode == TRANSPORT_UNDEFINED) {
87a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        return INVALID_OPERATION;
88a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    }
89a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
906e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber    CHECK_NE(rtpMode, TRANSPORT_TCP_INTERLEAVED);
916e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber    CHECK_NE(rtcpMode, TRANSPORT_TCP_INTERLEAVED);
92a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
932aea9552aeba92bbaf9e56c666049ea2d14057b5Andreas Huber    if ((rtcpMode == TRANSPORT_NONE && remoteRTCPPort >= 0)
942aea9552aeba92bbaf9e56c666049ea2d14057b5Andreas Huber            || (rtcpMode != TRANSPORT_NONE && remoteRTCPPort < 0)) {
95a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        return INVALID_OPERATION;
96a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    }
97a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
981d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> rtpNotify = new AMessage(kWhatRTPNotify, this);
99a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
100a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    sp<AMessage> rtcpNotify;
101a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    if (remoteRTCPPort >= 0) {
1021d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        rtcpNotify = new AMessage(kWhatRTCPNotify, this);
103a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    }
104a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
105a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    CHECK_EQ(mRTPSessionID, 0);
106a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    CHECK_EQ(mRTCPSessionID, 0);
107a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
108a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    int32_t localRTPPort;
109a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
110a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    for (;;) {
111a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        localRTPPort = PickRandomRTPPort();
112a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
113a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        status_t err;
1146e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber        if (rtpMode == TRANSPORT_UDP) {
115a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            err = mNetSession->createUDPSession(
116a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    localRTPPort,
117a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    remoteHost,
118a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    remoteRTPPort,
119a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    rtpNotify,
120a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    &mRTPSessionID);
121a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        } else {
1226e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber            CHECK_EQ(rtpMode, TRANSPORT_TCP);
123a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            err = mNetSession->createTCPDatagramSession(
124a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    localRTPPort,
125a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    remoteHost,
126a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    remoteRTPPort,
127a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    rtpNotify,
128a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    &mRTPSessionID);
129a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
130a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
131a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        if (err != OK) {
132a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            continue;
133a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
134a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
135a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        if (remoteRTCPPort < 0) {
136a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            break;
137a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
138a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
1396e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber        if (rtcpMode == TRANSPORT_UDP) {
140a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            err = mNetSession->createUDPSession(
141a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    localRTPPort + 1,
142a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    remoteHost,
143a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    remoteRTCPPort,
144a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    rtcpNotify,
145a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    &mRTCPSessionID);
146a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        } else {
1476e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber            CHECK_EQ(rtcpMode, TRANSPORT_TCP);
148a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            err = mNetSession->createTCPDatagramSession(
149a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    localRTPPort + 1,
150a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    remoteHost,
151a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    remoteRTCPPort,
152a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    rtcpNotify,
153a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    &mRTCPSessionID);
154a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
155a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
156a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        if (err == OK) {
157a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            break;
158a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
159a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
160a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        mNetSession->destroySession(mRTPSessionID);
161a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        mRTPSessionID = 0;
162a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    }
163a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
1646e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber    if (rtpMode == TRANSPORT_UDP) {
165a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        mRTPConnected = true;
1666e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber    }
1676e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber
1686e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber    if (rtcpMode == TRANSPORT_UDP) {
169a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        mRTCPConnected = true;
170a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    }
171a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
1726e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber    mRTPMode = rtpMode;
1736e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber    mRTCPMode = rtcpMode;
174a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    *outLocalRTPPort = localRTPPort;
175a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
1766e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber    if (mRTPMode == TRANSPORT_UDP
1776e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber            && (mRTCPMode == TRANSPORT_UDP || mRTCPMode == TRANSPORT_NONE)) {
178a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        notifyInitDone(OK);
179a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    }
180a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
181a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    return OK;
182a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber}
183a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
184a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huberstatus_t RTPSender::queueBuffer(
185a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        const sp<ABuffer> &buffer, uint8_t packetType, PacketizationMode mode) {
186a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    status_t err;
187a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
188a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    switch (mode) {
1898f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber        case PACKETIZATION_NONE:
1908f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber            err = queueRawPacket(buffer, packetType);
1918f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber            break;
1928f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber
193a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        case PACKETIZATION_TRANSPORT_STREAM:
194a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            err = queueTSPackets(buffer, packetType);
195a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            break;
196a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
197a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        case PACKETIZATION_H264:
198a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            err  = queueAVCBuffer(buffer, packetType);
199a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            break;
200a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
201a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        default:
202a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            TRESPASS();
203a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    }
204a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
205a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    return err;
206a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber}
207a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
2088f1f6a4814403dd78539250c845f8326f6137a61Andreas Huberstatus_t RTPSender::queueRawPacket(
2098f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber        const sp<ABuffer> &packet, uint8_t packetType) {
2108f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    CHECK_LE(packet->size(), kMaxUDPPacketSize - 12);
2118f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber
2128f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    int64_t timeUs;
2138f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    CHECK(packet->meta()->findInt64("timeUs", &timeUs));
2148f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber
2158f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    sp<ABuffer> udpPacket = new ABuffer(12 + packet->size());
2168f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber
2178f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    udpPacket->setInt32Data(mRTPSeqNo);
2188f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber
2198f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    uint8_t *rtp = udpPacket->data();
2208f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    rtp[0] = 0x80;
2218f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    rtp[1] = packetType;
2228f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber
2238f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    rtp[2] = (mRTPSeqNo >> 8) & 0xff;
2248f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    rtp[3] = mRTPSeqNo & 0xff;
2258f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    ++mRTPSeqNo;
2268f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber
2278f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    uint32_t rtpTime = (timeUs * 9) / 100ll;
2288f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber
2298f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    rtp[4] = rtpTime >> 24;
2308f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    rtp[5] = (rtpTime >> 16) & 0xff;
2318f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    rtp[6] = (rtpTime >> 8) & 0xff;
2328f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    rtp[7] = rtpTime & 0xff;
2338f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber
2348f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    rtp[8] = kSourceID >> 24;
2358f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    rtp[9] = (kSourceID >> 16) & 0xff;
2368f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    rtp[10] = (kSourceID >> 8) & 0xff;
2378f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    rtp[11] = kSourceID & 0xff;
2388f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber
2398f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    memcpy(&rtp[12], packet->data(), packet->size());
2408f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber
2418f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber    return sendRTPPacket(
2428f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber            udpPacket,
2438f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber            true /* storeInHistory */,
2448f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber            true /* timeValid */,
2454eac4e624f6930966d208d8e1ee99eefee077b50Andreas Huber            ALooper::GetNowUs());
2468f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber}
2478f1f6a4814403dd78539250c845f8326f6137a61Andreas Huber
248a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huberstatus_t RTPSender::queueTSPackets(
249a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        const sp<ABuffer> &tsPackets, uint8_t packetType) {
250a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    CHECK_EQ(0, tsPackets->size() % 188);
251a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
252a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber    int64_t timeUs;
253a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber    CHECK(tsPackets->meta()->findInt64("timeUs", &timeUs));
254a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber
255a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    size_t srcOffset = 0;
256a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    while (srcOffset < tsPackets->size()) {
257a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        sp<ABuffer> udpPacket =
258a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            new ABuffer(12 + kMaxNumTSPacketsPerRTPPacket * 188);
259a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
260a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        udpPacket->setInt32Data(mRTPSeqNo);
261a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
262a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        uint8_t *rtp = udpPacket->data();
263a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        rtp[0] = 0x80;
264a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        rtp[1] = packetType;
265a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
266a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        rtp[2] = (mRTPSeqNo >> 8) & 0xff;
267a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        rtp[3] = mRTPSeqNo & 0xff;
268a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        ++mRTPSeqNo;
269a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
270a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        int64_t nowUs = ALooper::GetNowUs();
271a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        uint32_t rtpTime = (nowUs * 9) / 100ll;
272a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
273a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        rtp[4] = rtpTime >> 24;
274a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        rtp[5] = (rtpTime >> 16) & 0xff;
275a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        rtp[6] = (rtpTime >> 8) & 0xff;
276a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        rtp[7] = rtpTime & 0xff;
277a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
278a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        rtp[8] = kSourceID >> 24;
279a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        rtp[9] = (kSourceID >> 16) & 0xff;
280a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        rtp[10] = (kSourceID >> 8) & 0xff;
281a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        rtp[11] = kSourceID & 0xff;
282a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
283a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        size_t numTSPackets = (tsPackets->size() - srcOffset) / 188;
284a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        if (numTSPackets > kMaxNumTSPacketsPerRTPPacket) {
285a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            numTSPackets = kMaxNumTSPacketsPerRTPPacket;
286a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
287a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
288a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        memcpy(&rtp[12], tsPackets->data() + srcOffset, numTSPackets * 188);
289a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
290a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        udpPacket->setRange(0, 12 + numTSPackets * 188);
291a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber
292a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber        srcOffset += numTSPackets * 188;
293a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber        bool isLastPacket = (srcOffset == tsPackets->size());
294a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber
295a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber        status_t err = sendRTPPacket(
296a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber                udpPacket,
297a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber                true /* storeInHistory */,
298a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber                isLastPacket /* timeValid */,
299a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber                timeUs);
300a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
301a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        if (err != OK) {
302a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            return err;
303a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
304a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    }
305a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
306a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    return OK;
307a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber}
308a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
309a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huberstatus_t RTPSender::queueAVCBuffer(
310a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        const sp<ABuffer> &accessUnit, uint8_t packetType) {
311a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    int64_t timeUs;
312a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
313a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
314a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    uint32_t rtpTime = (timeUs * 9 / 100ll);
315a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
316a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    List<sp<ABuffer> > packets;
317a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
318a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    sp<ABuffer> out = new ABuffer(kMaxUDPPacketSize);
319a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    size_t outBytesUsed = 12;  // Placeholder for RTP header.
320a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
321a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    const uint8_t *data = accessUnit->data();
322a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    size_t size = accessUnit->size();
323a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    const uint8_t *nalStart;
324a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    size_t nalSize;
325a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    while (getNextNALUnit(
326a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                &data, &size, &nalStart, &nalSize,
327a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                true /* startCodeFollows */) == OK) {
328a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        size_t bytesNeeded = nalSize + 2;
329a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        if (outBytesUsed == 12) {
330a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            ++bytesNeeded;
331a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
332a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
333a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        if (outBytesUsed + bytesNeeded > out->capacity()) {
334a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            bool emitSingleNALPacket = false;
335a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
336a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            if (outBytesUsed == 12
337a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    && outBytesUsed + nalSize <= out->capacity()) {
338a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                // We haven't emitted anything into the current packet yet and
339a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                // this NAL unit fits into a single-NAL-unit-packet while
340a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                // it wouldn't have fit as part of a STAP-A packet.
341a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
342a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                memcpy(out->data() + outBytesUsed, nalStart, nalSize);
343a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                outBytesUsed += nalSize;
344a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
345a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                emitSingleNALPacket = true;
346a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            }
347a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
348a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            if (outBytesUsed > 12) {
349a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                out->setRange(0, outBytesUsed);
350a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                packets.push_back(out);
351a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                out = new ABuffer(kMaxUDPPacketSize);
352a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                outBytesUsed = 12;  // Placeholder for RTP header
353a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            }
354a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
355a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            if (emitSingleNALPacket) {
356a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                continue;
357a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            }
358a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
359a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
360a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        if (outBytesUsed + bytesNeeded <= out->capacity()) {
361a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            uint8_t *dst = out->data() + outBytesUsed;
362a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
363a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            if (outBytesUsed == 12) {
364a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                *dst++ = 24;  // STAP-A header
365a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            }
366a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
367a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            *dst++ = (nalSize >> 8) & 0xff;
368a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            *dst++ = nalSize & 0xff;
369a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            memcpy(dst, nalStart, nalSize);
370a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
371a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            outBytesUsed += bytesNeeded;
372a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            continue;
373a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
374a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
375a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        // This single NAL unit does not fit into a single RTP packet,
376a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        // we need to emit an FU-A.
377a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
378a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        CHECK_EQ(outBytesUsed, 12u);
379a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
380a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        uint8_t nalType = nalStart[0] & 0x1f;
381a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        uint8_t nri = (nalStart[0] >> 5) & 3;
382a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
383a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        size_t srcOffset = 1;
384a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        while (srcOffset < nalSize) {
385a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            size_t copy = out->capacity() - outBytesUsed - 2;
386a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            if (copy > nalSize - srcOffset) {
387a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                copy = nalSize - srcOffset;
388a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            }
389a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
390a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            uint8_t *dst = out->data() + outBytesUsed;
391a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            dst[0] = (nri << 5) | 28;
392a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
393a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            dst[1] = nalType;
394a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
395a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            if (srcOffset == 1) {
396a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                dst[1] |= 0x80;
397a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            }
398a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
399a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            if (srcOffset + copy == nalSize) {
400a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                dst[1] |= 0x40;
401a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            }
402a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
403a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            memcpy(&dst[2], nalStart + srcOffset, copy);
404a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            srcOffset += copy;
405a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
406a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            out->setRange(0, outBytesUsed + copy + 2);
407a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
408a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            packets.push_back(out);
409a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            out = new ABuffer(kMaxUDPPacketSize);
410a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            outBytesUsed = 12;  // Placeholder for RTP header
411a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
412a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    }
413a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
414a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    if (outBytesUsed > 12) {
415a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        out->setRange(0, outBytesUsed);
416a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        packets.push_back(out);
417a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    }
418a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
419a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    while (!packets.empty()) {
420a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        sp<ABuffer> out = *packets.begin();
421a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        packets.erase(packets.begin());
422a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
423a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        out->setInt32Data(mRTPSeqNo);
424a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
425a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        bool last = packets.empty();
426a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
427a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        uint8_t *dst = out->data();
428a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
429a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        dst[0] = 0x80;
430a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
431a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        dst[1] = packetType;
432a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        if (last) {
433a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            dst[1] |= 1 << 7;  // M-bit
434a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
435a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
436a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        dst[2] = (mRTPSeqNo >> 8) & 0xff;
437a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        dst[3] = mRTPSeqNo & 0xff;
438a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        ++mRTPSeqNo;
439a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
440a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        dst[4] = rtpTime >> 24;
441a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        dst[5] = (rtpTime >> 16) & 0xff;
442a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        dst[6] = (rtpTime >> 8) & 0xff;
443a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        dst[7] = rtpTime & 0xff;
444a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        dst[8] = kSourceID >> 24;
445a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        dst[9] = (kSourceID >> 16) & 0xff;
446a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        dst[10] = (kSourceID >> 8) & 0xff;
447a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        dst[11] = kSourceID & 0xff;
448a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
449a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        status_t err = sendRTPPacket(out, true /* storeInHistory */);
450a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
451a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        if (err != OK) {
452a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            return err;
453a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
454a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    }
455a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
456a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    return OK;
457a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber}
458a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
459a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huberstatus_t RTPSender::sendRTPPacket(
460a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber        const sp<ABuffer> &buffer, bool storeInHistory,
461a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber        bool timeValid, int64_t timeUs) {
462a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    CHECK(mRTPConnected);
463a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
464a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    status_t err = mNetSession->sendRequest(
465a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber            mRTPSessionID, buffer->data(), buffer->size(),
466a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber            timeValid, timeUs);
467a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
468a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    if (err != OK) {
469a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        return err;
470a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    }
471a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
472a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    mLastNTPTime = GetNowNTP();
473a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    mLastRTPTime = U32_AT(buffer->data() + 4);
474a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
475a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    ++mNumRTPSent;
476a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    mNumRTPOctetsSent += buffer->size() - 12;
477a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
478a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    if (storeInHistory) {
479a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        if (mHistorySize == kMaxHistorySize) {
480a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            mHistory.erase(mHistory.begin());
481a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        } else {
482a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            ++mHistorySize;
483a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
484a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        mHistory.push_back(buffer);
485a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    }
486a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
487a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    return OK;
488a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber}
489a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
490a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber// static
491a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huberuint64_t RTPSender::GetNowNTP() {
492a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    struct timeval tv;
493a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    gettimeofday(&tv, NULL /* timezone */);
494a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
495a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    uint64_t nowUs = tv.tv_sec * 1000000ll + tv.tv_usec;
496a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
497a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    nowUs += ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll;
498a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
499a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    uint64_t hi = nowUs / 1000000ll;
500a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    uint64_t lo = ((1ll << 32) * (nowUs % 1000000ll)) / 1000000ll;
501a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
502a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    return (hi << 32) | lo;
503a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber}
504a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
505a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Hubervoid RTPSender::onMessageReceived(const sp<AMessage> &msg) {
506a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    switch (msg->what()) {
507a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        case kWhatRTPNotify:
508a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        case kWhatRTCPNotify:
509a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            onNetNotify(msg->what() == kWhatRTPNotify, msg);
510a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            break;
511a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
512a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        default:
513a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            TRESPASS();
514a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    }
515a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber}
516a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
517a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Hubervoid RTPSender::onNetNotify(bool isRTP, const sp<AMessage> &msg) {
518a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    int32_t reason;
519a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    CHECK(msg->findInt32("reason", &reason));
520a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
521a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    switch (reason) {
522a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        case ANetworkSession::kWhatError:
523a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        {
524a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            int32_t sessionID;
525a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            CHECK(msg->findInt32("sessionID", &sessionID));
526a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
527a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            int32_t err;
528a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            CHECK(msg->findInt32("err", &err));
529a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
530a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            int32_t errorOccuredDuringSend;
531a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            CHECK(msg->findInt32("send", &errorOccuredDuringSend));
532a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
533a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            AString detail;
534a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            CHECK(msg->findString("detail", &detail));
535a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
536a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            ALOGE("An error occurred during %s in session %d "
537a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                  "(%d, '%s' (%s)).",
538a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                  errorOccuredDuringSend ? "send" : "receive",
539a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                  sessionID,
540a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                  err,
541a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                  detail.c_str(),
542a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                  strerror(-err));
543a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
544a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            mNetSession->destroySession(sessionID);
545a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
546a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            if (sessionID == mRTPSessionID) {
547a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                mRTPSessionID = 0;
548a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            } else if (sessionID == mRTCPSessionID) {
549a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                mRTCPSessionID = 0;
550a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            }
551a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
5526e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber            if (!mRTPConnected
5536e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber                    || (mRTPMode != TRANSPORT_NONE && !mRTCPConnected)) {
5546e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber                // We haven't completed initialization, attach the error
5556e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber                // to the notification instead.
5566e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber                notifyInitDone(err);
5576e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber                break;
558a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            }
559a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
560a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            notifyError(err);
561a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            break;
562a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
563a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
564a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        case ANetworkSession::kWhatDatagram:
565a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        {
566a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            sp<ABuffer> data;
567a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            CHECK(msg->findBuffer("data", &data));
568a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
569a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            if (isRTP) {
570a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                ALOGW("Huh? Received data on RTP connection...");
571a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            } else {
572a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                onRTCPData(data);
573a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            }
574a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            break;
575a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
576a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
577a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        case ANetworkSession::kWhatConnected:
578a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        {
579a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            int32_t sessionID;
580a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            CHECK(msg->findInt32("sessionID", &sessionID));
581a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
582a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            if  (isRTP) {
5836e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber                CHECK_EQ(mRTPMode, TRANSPORT_TCP);
584a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                CHECK_EQ(sessionID, mRTPSessionID);
585a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                mRTPConnected = true;
586a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            } else {
5876e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber                CHECK_EQ(mRTCPMode, TRANSPORT_TCP);
588a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                CHECK_EQ(sessionID, mRTCPSessionID);
589a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                mRTCPConnected = true;
590a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            }
591a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
5926e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber            if (mRTPConnected
5936e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber                    && (mRTCPMode == TRANSPORT_NONE || mRTCPConnected)) {
594a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                notifyInitDone(OK);
595a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            }
596a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            break;
597a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
598126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber
599126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber        case ANetworkSession::kWhatNetworkStall:
600126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber        {
601126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber            size_t numBytesQueued;
602126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber            CHECK(msg->findSize("numBytesQueued", &numBytesQueued));
603126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber
604126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber            notifyNetworkStall(numBytesQueued);
605126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber            break;
606126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber        }
607126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber
608126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber        default:
609126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber            TRESPASS();
610a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    }
611a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber}
612a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
613a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huberstatus_t RTPSender::onRTCPData(const sp<ABuffer> &buffer) {
614a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    const uint8_t *data = buffer->data();
615a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    size_t size = buffer->size();
616a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
617a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    while (size > 0) {
618a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        if (size < 8) {
619a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            // Too short to be a valid RTCP header
620a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            return ERROR_MALFORMED;
621a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
622a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
623a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        if ((data[0] >> 6) != 2) {
624a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            // Unsupported version.
625a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            return ERROR_UNSUPPORTED;
626a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
627a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
628a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        if (data[0] & 0x20) {
629a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            // Padding present.
630a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
631a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            size_t paddingLength = data[size - 1];
632a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
633a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            if (paddingLength + 12 > size) {
634a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                // If we removed this much padding we'd end up with something
635a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                // that's too short to be a valid RTP header.
636a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                return ERROR_MALFORMED;
637a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            }
638a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
639a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            size -= paddingLength;
640a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
641a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
642a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        size_t headerLength = 4 * (data[2] << 8 | data[3]) + 4;
643a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
644a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        if (size < headerLength) {
645a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            // Only received a partial packet?
646a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            return ERROR_MALFORMED;
647a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
648a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
649a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        switch (data[1]) {
650a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            case 200:
651a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            case 201:  // RR
652a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                parseReceiverReport(data, headerLength);
653a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                break;
654a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
655a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            case 202:  // SDES
656a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            case 203:
657d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber                break;
658d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber
659a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            case 204:  // APP
6602aea9552aeba92bbaf9e56c666049ea2d14057b5Andreas Huber                parseAPP(data, headerLength);
661a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                break;
662a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
663a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            case 205:  // TSFB (transport layer specific feedback)
664a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                parseTSFB(data, headerLength);
665a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                break;
666a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
667a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            case 206:  // PSFB (payload specific feedback)
668a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                // hexdump(data, headerLength);
669a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                break;
670a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
671a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            default:
672a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            {
673ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar                ALOGW("Unknown RTCP packet type %u of size %zu",
674ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar                        (unsigned)data[1], headerLength);
675a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                break;
676a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            }
677a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
678a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
679a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        data += headerLength;
680a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        size -= headerLength;
681a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    }
682a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
683a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    return OK;
684a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber}
685a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
68684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t RTPSender::parseReceiverReport(
68784333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        const uint8_t *data, size_t /* size */) {
688a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    float fractionLost = data[12] / 256.0f;
689a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
690a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    ALOGI("lost %.2f %% of packets during report interval.",
691a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber          100.0f * fractionLost);
692a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
693a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    return OK;
694a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber}
695a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
696a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huberstatus_t RTPSender::parseTSFB(const uint8_t *data, size_t size) {
697a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    if ((data[0] & 0x1f) != 1) {
698a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        return ERROR_UNSUPPORTED;  // We only support NACK for now.
699a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    }
700a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
701a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    uint32_t srcId = U32_AT(&data[8]);
702a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    if (srcId != kSourceID) {
703a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        return ERROR_MALFORMED;
704a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    }
705a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
706a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    for (size_t i = 12; i < size; i += 4) {
707a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        uint16_t seqNo = U16_AT(&data[i]);
708a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        uint16_t blp = U16_AT(&data[i + 2]);
709a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
710a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        List<sp<ABuffer> >::iterator it = mHistory.begin();
711a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        bool foundSeqNo = false;
712a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        while (it != mHistory.end()) {
713a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            const sp<ABuffer> &buffer = *it;
714a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
715a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            uint16_t bufferSeqNo = buffer->int32Data() & 0xffff;
716a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
717a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            bool retransmit = false;
718a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            if (bufferSeqNo == seqNo) {
719a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                retransmit = true;
720a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            } else if (blp != 0) {
721a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                for (size_t i = 0; i < 16; ++i) {
722a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    if ((blp & (1 << i))
723a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                        && (bufferSeqNo == ((seqNo + i + 1) & 0xffff))) {
724a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                        blp &= ~(1 << i);
725a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                        retransmit = true;
726a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    }
727a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                }
728a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            }
729a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
730a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            if (retransmit) {
731a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                ALOGV("retransmitting seqNo %d", bufferSeqNo);
732a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
733a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                CHECK_EQ((status_t)OK,
734a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                         sendRTPPacket(buffer, false /* storeInHistory */));
735a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
736a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                if (bufferSeqNo == seqNo) {
737a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    foundSeqNo = true;
738a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                }
739a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
740a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                if (foundSeqNo && blp == 0) {
741a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                    break;
742a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                }
743a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            }
744a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
745a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            ++it;
746a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
747a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
748a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        if (!foundSeqNo || blp != 0) {
749a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            ALOGI("Some sequence numbers were no longer available for "
750a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                  "retransmission (seqNo = %d, foundSeqNo = %d, blp = 0x%04x)",
751a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                  seqNo, foundSeqNo, blp);
752a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
753a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            if (!mHistory.empty()) {
754a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                int32_t earliest = (*mHistory.begin())->int32Data() & 0xffff;
755a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                int32_t latest = (*--mHistory.end())->int32Data() & 0xffff;
756a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
757a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber                ALOGI("have seq numbers from %d - %d", earliest, latest);
758a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber            }
759a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber        }
760a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    }
761a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
762a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    return OK;
763a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber}
764a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
765ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnarstatus_t RTPSender::parseAPP(const uint8_t *data, size_t size __unused) {
766c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber    if (!memcmp("late", &data[8], 4)) {
767c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber        int64_t avgLatencyUs = (int64_t)U64_AT(&data[12]);
768c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber        int64_t maxLatencyUs = (int64_t)U64_AT(&data[20]);
769c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber
770c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber        sp<AMessage> notify = mNotify->dup();
771c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber        notify->setInt32("what", kWhatInformSender);
772c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber        notify->setInt64("avgLatencyUs", avgLatencyUs);
773c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber        notify->setInt64("maxLatencyUs", maxLatencyUs);
774c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber        notify->post();
775c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber    }
776c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber
7772aea9552aeba92bbaf9e56c666049ea2d14057b5Andreas Huber    return OK;
7782aea9552aeba92bbaf9e56c666049ea2d14057b5Andreas Huber}
7792aea9552aeba92bbaf9e56c666049ea2d14057b5Andreas Huber
780a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Hubervoid RTPSender::notifyInitDone(status_t err) {
781a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    sp<AMessage> notify = mNotify->dup();
782a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    notify->setInt32("what", kWhatInitDone);
783a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    notify->setInt32("err", err);
784a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    notify->post();
785a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber}
786a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
787a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Hubervoid RTPSender::notifyError(status_t err) {
788a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    sp<AMessage> notify = mNotify->dup();
789a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    notify->setInt32("what", kWhatError);
790a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    notify->setInt32("err", err);
791a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber    notify->post();
792a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber}
793a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
794126568c7aeeb5570789e70a310477f44dbdbd885Andreas Hubervoid RTPSender::notifyNetworkStall(size_t numBytesQueued) {
795126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber    sp<AMessage> notify = mNotify->dup();
796126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber    notify->setInt32("what", kWhatNetworkStall);
797126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber    notify->setSize("numBytesQueued", numBytesQueued);
798126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber    notify->post();
799126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber}
800126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber
801a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber}  // namespace android
802a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber
803