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> ¬ify) 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