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 98a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber sp<AMessage> rtpNotify = new AMessage(kWhatRTPNotify, id()); 99a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 100a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber sp<AMessage> rtcpNotify; 101a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (remoteRTCPPort >= 0) { 102a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber rtcpNotify = new AMessage(kWhatRTCPNotify, id()); 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 const size_t numTSPackets = tsPackets->size() / 188; 256a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 257a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber size_t srcOffset = 0; 258a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber while (srcOffset < tsPackets->size()) { 259a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber sp<ABuffer> udpPacket = 260a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber new ABuffer(12 + kMaxNumTSPacketsPerRTPPacket * 188); 261a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 262a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber udpPacket->setInt32Data(mRTPSeqNo); 263a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 264a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber uint8_t *rtp = udpPacket->data(); 265a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber rtp[0] = 0x80; 266a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber rtp[1] = packetType; 267a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 268a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber rtp[2] = (mRTPSeqNo >> 8) & 0xff; 269a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber rtp[3] = mRTPSeqNo & 0xff; 270a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber ++mRTPSeqNo; 271a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 272a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber int64_t nowUs = ALooper::GetNowUs(); 273a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber uint32_t rtpTime = (nowUs * 9) / 100ll; 274a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 275a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber rtp[4] = rtpTime >> 24; 276a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber rtp[5] = (rtpTime >> 16) & 0xff; 277a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber rtp[6] = (rtpTime >> 8) & 0xff; 278a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber rtp[7] = rtpTime & 0xff; 279a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 280a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber rtp[8] = kSourceID >> 24; 281a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber rtp[9] = (kSourceID >> 16) & 0xff; 282a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber rtp[10] = (kSourceID >> 8) & 0xff; 283a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber rtp[11] = kSourceID & 0xff; 284a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 285a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber size_t numTSPackets = (tsPackets->size() - srcOffset) / 188; 286a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (numTSPackets > kMaxNumTSPacketsPerRTPPacket) { 287a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber numTSPackets = kMaxNumTSPacketsPerRTPPacket; 288a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 289a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 290a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber memcpy(&rtp[12], tsPackets->data() + srcOffset, numTSPackets * 188); 291a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 292a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber udpPacket->setRange(0, 12 + numTSPackets * 188); 293a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber 294a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber srcOffset += numTSPackets * 188; 295a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber bool isLastPacket = (srcOffset == tsPackets->size()); 296a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber 297a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber status_t err = sendRTPPacket( 298a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber udpPacket, 299a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber true /* storeInHistory */, 300a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber isLastPacket /* timeValid */, 301a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber timeUs); 302a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 303a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (err != OK) { 304a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber return err; 305a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 306a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 307a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 308a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber return OK; 309a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber} 310a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 311a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huberstatus_t RTPSender::queueAVCBuffer( 312a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber const sp<ABuffer> &accessUnit, uint8_t packetType) { 313a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber int64_t timeUs; 314a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs)); 315a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 316a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber uint32_t rtpTime = (timeUs * 9 / 100ll); 317a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 318a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber List<sp<ABuffer> > packets; 319a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 320a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber sp<ABuffer> out = new ABuffer(kMaxUDPPacketSize); 321a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber size_t outBytesUsed = 12; // Placeholder for RTP header. 322a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 323a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber const uint8_t *data = accessUnit->data(); 324a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber size_t size = accessUnit->size(); 325a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber const uint8_t *nalStart; 326a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber size_t nalSize; 327a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber while (getNextNALUnit( 328a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber &data, &size, &nalStart, &nalSize, 329a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber true /* startCodeFollows */) == OK) { 330a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber size_t bytesNeeded = nalSize + 2; 331a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (outBytesUsed == 12) { 332a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber ++bytesNeeded; 333a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 334a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 335a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (outBytesUsed + bytesNeeded > out->capacity()) { 336a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber bool emitSingleNALPacket = false; 337a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 338a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (outBytesUsed == 12 339a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber && outBytesUsed + nalSize <= out->capacity()) { 340a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber // We haven't emitted anything into the current packet yet and 341a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber // this NAL unit fits into a single-NAL-unit-packet while 342a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber // it wouldn't have fit as part of a STAP-A packet. 343a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 344a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber memcpy(out->data() + outBytesUsed, nalStart, nalSize); 345a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber outBytesUsed += nalSize; 346a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 347a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber emitSingleNALPacket = true; 348a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 349a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 350a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (outBytesUsed > 12) { 351a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber out->setRange(0, outBytesUsed); 352a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber packets.push_back(out); 353a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber out = new ABuffer(kMaxUDPPacketSize); 354a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber outBytesUsed = 12; // Placeholder for RTP header 355a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 356a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 357a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (emitSingleNALPacket) { 358a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber continue; 359a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 360a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 361a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 362a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (outBytesUsed + bytesNeeded <= out->capacity()) { 363a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber uint8_t *dst = out->data() + outBytesUsed; 364a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 365a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (outBytesUsed == 12) { 366a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber *dst++ = 24; // STAP-A header 367a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 368a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 369a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber *dst++ = (nalSize >> 8) & 0xff; 370a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber *dst++ = nalSize & 0xff; 371a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber memcpy(dst, nalStart, nalSize); 372a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 373a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber outBytesUsed += bytesNeeded; 374a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber continue; 375a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 376a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 377a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber // This single NAL unit does not fit into a single RTP packet, 378a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber // we need to emit an FU-A. 379a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 380a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber CHECK_EQ(outBytesUsed, 12u); 381a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 382a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber uint8_t nalType = nalStart[0] & 0x1f; 383a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber uint8_t nri = (nalStart[0] >> 5) & 3; 384a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 385a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber size_t srcOffset = 1; 386a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber while (srcOffset < nalSize) { 387a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber size_t copy = out->capacity() - outBytesUsed - 2; 388a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (copy > nalSize - srcOffset) { 389a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber copy = nalSize - srcOffset; 390a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 391a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 392a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber uint8_t *dst = out->data() + outBytesUsed; 393a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber dst[0] = (nri << 5) | 28; 394a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 395a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber dst[1] = nalType; 396a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 397a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (srcOffset == 1) { 398a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber dst[1] |= 0x80; 399a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 400a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 401a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (srcOffset + copy == nalSize) { 402a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber dst[1] |= 0x40; 403a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 404a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 405a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber memcpy(&dst[2], nalStart + srcOffset, copy); 406a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber srcOffset += copy; 407a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 408a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber out->setRange(0, outBytesUsed + copy + 2); 409a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 410a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber packets.push_back(out); 411a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber out = new ABuffer(kMaxUDPPacketSize); 412a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber outBytesUsed = 12; // Placeholder for RTP header 413a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 414a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 415a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 416a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (outBytesUsed > 12) { 417a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber out->setRange(0, outBytesUsed); 418a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber packets.push_back(out); 419a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 420a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 421a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber while (!packets.empty()) { 422a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber sp<ABuffer> out = *packets.begin(); 423a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber packets.erase(packets.begin()); 424a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 425a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber out->setInt32Data(mRTPSeqNo); 426a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 427a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber bool last = packets.empty(); 428a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 429a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber uint8_t *dst = out->data(); 430a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 431a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber dst[0] = 0x80; 432a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 433a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber dst[1] = packetType; 434a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (last) { 435a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber dst[1] |= 1 << 7; // M-bit 436a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 437a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 438a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber dst[2] = (mRTPSeqNo >> 8) & 0xff; 439a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber dst[3] = mRTPSeqNo & 0xff; 440a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber ++mRTPSeqNo; 441a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 442a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber dst[4] = rtpTime >> 24; 443a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber dst[5] = (rtpTime >> 16) & 0xff; 444a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber dst[6] = (rtpTime >> 8) & 0xff; 445a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber dst[7] = rtpTime & 0xff; 446a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber dst[8] = kSourceID >> 24; 447a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber dst[9] = (kSourceID >> 16) & 0xff; 448a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber dst[10] = (kSourceID >> 8) & 0xff; 449a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber dst[11] = kSourceID & 0xff; 450a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 451a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber status_t err = sendRTPPacket(out, true /* storeInHistory */); 452a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 453a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (err != OK) { 454a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber return err; 455a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 456a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 457a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 458a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber return OK; 459a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber} 460a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 461a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huberstatus_t RTPSender::sendRTPPacket( 462a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber const sp<ABuffer> &buffer, bool storeInHistory, 463a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber bool timeValid, int64_t timeUs) { 464a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber CHECK(mRTPConnected); 465a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 466a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber status_t err = mNetSession->sendRequest( 467a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber mRTPSessionID, buffer->data(), buffer->size(), 468a239dd722e760fe4fd7379b454d7722e1f312928Andreas Huber timeValid, timeUs); 469a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 470a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (err != OK) { 471a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber return err; 472a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 473a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 474a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber mLastNTPTime = GetNowNTP(); 475a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber mLastRTPTime = U32_AT(buffer->data() + 4); 476a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 477a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber ++mNumRTPSent; 478a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber mNumRTPOctetsSent += buffer->size() - 12; 479a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 480a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (storeInHistory) { 481a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (mHistorySize == kMaxHistorySize) { 482a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber mHistory.erase(mHistory.begin()); 483a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } else { 484a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber ++mHistorySize; 485a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 486a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber mHistory.push_back(buffer); 487a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 488a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 489a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber return OK; 490a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber} 491a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 492a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber// static 493a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huberuint64_t RTPSender::GetNowNTP() { 494a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber struct timeval tv; 495a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber gettimeofday(&tv, NULL /* timezone */); 496a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 497a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber uint64_t nowUs = tv.tv_sec * 1000000ll + tv.tv_usec; 498a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 499a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber nowUs += ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll; 500a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 501a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber uint64_t hi = nowUs / 1000000ll; 502a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber uint64_t lo = ((1ll << 32) * (nowUs % 1000000ll)) / 1000000ll; 503a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 504a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber return (hi << 32) | lo; 505a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber} 506a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 507a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Hubervoid RTPSender::onMessageReceived(const sp<AMessage> &msg) { 508a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber switch (msg->what()) { 509a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber case kWhatRTPNotify: 510a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber case kWhatRTCPNotify: 511a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber onNetNotify(msg->what() == kWhatRTPNotify, msg); 512a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber break; 513a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 514a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber default: 515a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber TRESPASS(); 516a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 517a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber} 518a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 519a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Hubervoid RTPSender::onNetNotify(bool isRTP, const sp<AMessage> &msg) { 520a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber int32_t reason; 521a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber CHECK(msg->findInt32("reason", &reason)); 522a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 523a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber switch (reason) { 524a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber case ANetworkSession::kWhatError: 525a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber { 526a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber int32_t sessionID; 527a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber CHECK(msg->findInt32("sessionID", &sessionID)); 528a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 529a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber int32_t err; 530a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber CHECK(msg->findInt32("err", &err)); 531a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 532a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber int32_t errorOccuredDuringSend; 533a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber CHECK(msg->findInt32("send", &errorOccuredDuringSend)); 534a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 535a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber AString detail; 536a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber CHECK(msg->findString("detail", &detail)); 537a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 538a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber ALOGE("An error occurred during %s in session %d " 539a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber "(%d, '%s' (%s)).", 540a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber errorOccuredDuringSend ? "send" : "receive", 541a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber sessionID, 542a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber err, 543a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber detail.c_str(), 544a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber strerror(-err)); 545a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 546a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber mNetSession->destroySession(sessionID); 547a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 548a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (sessionID == mRTPSessionID) { 549a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber mRTPSessionID = 0; 550a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } else if (sessionID == mRTCPSessionID) { 551a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber mRTCPSessionID = 0; 552a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 553a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 5546e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber if (!mRTPConnected 5556e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber || (mRTPMode != TRANSPORT_NONE && !mRTCPConnected)) { 5566e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber // We haven't completed initialization, attach the error 5576e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber // to the notification instead. 5586e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber notifyInitDone(err); 5596e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber break; 560a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 561a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 562a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber notifyError(err); 563a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber break; 564a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 565a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 566a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber case ANetworkSession::kWhatDatagram: 567a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber { 568a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber sp<ABuffer> data; 569a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber CHECK(msg->findBuffer("data", &data)); 570a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 571a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (isRTP) { 572a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber ALOGW("Huh? Received data on RTP connection..."); 573a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } else { 574a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber onRTCPData(data); 575a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 576a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber break; 577a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 578a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 579a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber case ANetworkSession::kWhatConnected: 580a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber { 581a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber int32_t sessionID; 582a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber CHECK(msg->findInt32("sessionID", &sessionID)); 583a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 584a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (isRTP) { 5856e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber CHECK_EQ(mRTPMode, TRANSPORT_TCP); 586a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber CHECK_EQ(sessionID, mRTPSessionID); 587a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber mRTPConnected = true; 588a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } else { 5896e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber CHECK_EQ(mRTCPMode, TRANSPORT_TCP); 590a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber CHECK_EQ(sessionID, mRTCPSessionID); 591a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber mRTCPConnected = true; 592a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 593a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 5946e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber if (mRTPConnected 5956e98aba4d23d00cab236d993d895f57ea76ea0e5Andreas Huber && (mRTCPMode == TRANSPORT_NONE || mRTCPConnected)) { 596a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber notifyInitDone(OK); 597a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 598a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber break; 599a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 600126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber 601126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber case ANetworkSession::kWhatNetworkStall: 602126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber { 603126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber size_t numBytesQueued; 604126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber CHECK(msg->findSize("numBytesQueued", &numBytesQueued)); 605126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber 606126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber notifyNetworkStall(numBytesQueued); 607126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber break; 608126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber } 609126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber 610126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber default: 611126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber TRESPASS(); 612a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 613a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber} 614a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 615a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huberstatus_t RTPSender::onRTCPData(const sp<ABuffer> &buffer) { 616a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber const uint8_t *data = buffer->data(); 617a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber size_t size = buffer->size(); 618a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 619a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber while (size > 0) { 620a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (size < 8) { 621a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber // Too short to be a valid RTCP header 622a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber return ERROR_MALFORMED; 623a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 624a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 625a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if ((data[0] >> 6) != 2) { 626a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber // Unsupported version. 627a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber return ERROR_UNSUPPORTED; 628a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 629a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 630a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (data[0] & 0x20) { 631a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber // Padding present. 632a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 633a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber size_t paddingLength = data[size - 1]; 634a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 635a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (paddingLength + 12 > size) { 636a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber // If we removed this much padding we'd end up with something 637a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber // that's too short to be a valid RTP header. 638a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber return ERROR_MALFORMED; 639a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 640a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 641a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber size -= paddingLength; 642a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 643a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 644a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber size_t headerLength = 4 * (data[2] << 8 | data[3]) + 4; 645a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 646a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (size < headerLength) { 647a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber // Only received a partial packet? 648a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber return ERROR_MALFORMED; 649a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 650a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 651a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber switch (data[1]) { 652a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber case 200: 653a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber case 201: // RR 654a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber parseReceiverReport(data, headerLength); 655a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber break; 656a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 657a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber case 202: // SDES 658a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber case 203: 659d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber break; 660d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber 661a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber case 204: // APP 6622aea9552aeba92bbaf9e56c666049ea2d14057b5Andreas Huber parseAPP(data, headerLength); 663a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber break; 664a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 665a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber case 205: // TSFB (transport layer specific feedback) 666a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber parseTSFB(data, headerLength); 667a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber break; 668a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 669a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber case 206: // PSFB (payload specific feedback) 670a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber // hexdump(data, headerLength); 671a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber break; 672a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 673a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber default: 674a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber { 675a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber ALOGW("Unknown RTCP packet type %u of size %d", 676a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber (unsigned)data[1], headerLength); 677a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber break; 678a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 679a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 680a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 681a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber data += headerLength; 682a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber size -= headerLength; 683a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 684a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 685a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber return OK; 686a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber} 687a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 688a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huberstatus_t RTPSender::parseReceiverReport(const uint8_t *data, size_t size) { 689a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber // hexdump(data, size); 690a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 691a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber float fractionLost = data[12] / 256.0f; 692a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 693a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber ALOGI("lost %.2f %% of packets during report interval.", 694a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 100.0f * fractionLost); 695a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 696a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber return OK; 697a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber} 698a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 699a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huberstatus_t RTPSender::parseTSFB(const uint8_t *data, size_t size) { 700a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if ((data[0] & 0x1f) != 1) { 701a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber return ERROR_UNSUPPORTED; // We only support NACK for now. 702a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 703a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 704a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber uint32_t srcId = U32_AT(&data[8]); 705a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (srcId != kSourceID) { 706a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber return ERROR_MALFORMED; 707a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 708a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 709a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber for (size_t i = 12; i < size; i += 4) { 710a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber uint16_t seqNo = U16_AT(&data[i]); 711a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber uint16_t blp = U16_AT(&data[i + 2]); 712a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 713a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber List<sp<ABuffer> >::iterator it = mHistory.begin(); 714a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber bool foundSeqNo = false; 715a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber while (it != mHistory.end()) { 716a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber const sp<ABuffer> &buffer = *it; 717a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 718a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber uint16_t bufferSeqNo = buffer->int32Data() & 0xffff; 719a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 720a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber bool retransmit = false; 721a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (bufferSeqNo == seqNo) { 722a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber retransmit = true; 723a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } else if (blp != 0) { 724a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber for (size_t i = 0; i < 16; ++i) { 725a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if ((blp & (1 << i)) 726a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber && (bufferSeqNo == ((seqNo + i + 1) & 0xffff))) { 727a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber blp &= ~(1 << i); 728a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber retransmit = true; 729a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 730a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 731a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 732a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 733a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (retransmit) { 734a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber ALOGV("retransmitting seqNo %d", bufferSeqNo); 735a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 736a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber CHECK_EQ((status_t)OK, 737a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber sendRTPPacket(buffer, false /* storeInHistory */)); 738a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 739a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (bufferSeqNo == seqNo) { 740a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber foundSeqNo = true; 741a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 742a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 743a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (foundSeqNo && blp == 0) { 744a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber break; 745a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 746a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 747a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 748a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber ++it; 749a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 750a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 751a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (!foundSeqNo || blp != 0) { 752a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber ALOGI("Some sequence numbers were no longer available for " 753a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber "retransmission (seqNo = %d, foundSeqNo = %d, blp = 0x%04x)", 754a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber seqNo, foundSeqNo, blp); 755a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 756a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber if (!mHistory.empty()) { 757a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber int32_t earliest = (*mHistory.begin())->int32Data() & 0xffff; 758a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber int32_t latest = (*--mHistory.end())->int32Data() & 0xffff; 759a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 760a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber ALOGI("have seq numbers from %d - %d", earliest, latest); 761a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 762a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 763a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber } 764a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 765a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber return OK; 766a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber} 767a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 7682aea9552aeba92bbaf9e56c666049ea2d14057b5Andreas Huberstatus_t RTPSender::parseAPP(const uint8_t *data, size_t size) { 769c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber if (!memcmp("late", &data[8], 4)) { 770c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber int64_t avgLatencyUs = (int64_t)U64_AT(&data[12]); 771c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber int64_t maxLatencyUs = (int64_t)U64_AT(&data[20]); 772c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber 773c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber sp<AMessage> notify = mNotify->dup(); 774c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber notify->setInt32("what", kWhatInformSender); 775c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber notify->setInt64("avgLatencyUs", avgLatencyUs); 776c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber notify->setInt64("maxLatencyUs", maxLatencyUs); 777c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber notify->post(); 778c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber } 779c86ef45279185b474bd6af0a7ae407f8ab577f13Andreas Huber 7802aea9552aeba92bbaf9e56c666049ea2d14057b5Andreas Huber return OK; 7812aea9552aeba92bbaf9e56c666049ea2d14057b5Andreas Huber} 7822aea9552aeba92bbaf9e56c666049ea2d14057b5Andreas Huber 783a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Hubervoid RTPSender::notifyInitDone(status_t err) { 784a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber sp<AMessage> notify = mNotify->dup(); 785a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber notify->setInt32("what", kWhatInitDone); 786a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber notify->setInt32("err", err); 787a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber notify->post(); 788a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber} 789a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 790a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Hubervoid RTPSender::notifyError(status_t err) { 791a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber sp<AMessage> notify = mNotify->dup(); 792a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber notify->setInt32("what", kWhatError); 793a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber notify->setInt32("err", err); 794a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber notify->post(); 795a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber} 796a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 797126568c7aeeb5570789e70a310477f44dbdbd885Andreas Hubervoid RTPSender::notifyNetworkStall(size_t numBytesQueued) { 798126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber sp<AMessage> notify = mNotify->dup(); 799126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber notify->setInt32("what", kWhatNetworkStall); 800126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber notify->setSize("numBytesQueued", numBytesQueued); 801126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber notify->post(); 802126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber} 803126568c7aeeb5570789e70a310477f44dbdbd885Andreas Huber 804a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber} // namespace android 805a556c4822fc205db0d27834ba5b637c351d73ffaAndreas Huber 806