/* * Copyright 2012, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SENDER_H_ #define SENDER_H_ #include namespace android { #define LOG_TRANSPORT_STREAM 0 #define TRACK_BANDWIDTH 0 #define ENABLE_RETRANSMISSION 1 // If retransmission is enabled the following define determines what // kind we support, if RETRANSMISSION_ACCORDING_TO_RFC_XXXX is 0 // we'll send NACKs on the original RTCP channel and retransmit packets // on the original RTP channel, otherwise a separate channel pair is used // for this purpose. #define RETRANSMISSION_ACCORDING_TO_RFC_XXXX 0 struct ABuffer; struct ANetworkSession; struct Sender : public AHandler { Sender(const sp &netSession, const sp ¬ify); enum { kWhatInitDone, kWhatSessionDead, kWhatBinaryData, }; enum TransportMode { TRANSPORT_UDP, TRANSPORT_TCP_INTERLEAVED, TRANSPORT_TCP, }; status_t init( const char *clientIP, int32_t clientRtp, int32_t clientRtcp, TransportMode transportMode); status_t finishInit(); int32_t getRTPPort() const; void queuePackets(int64_t timeUs, const sp &tsPackets); void scheduleSendSR(); protected: virtual ~Sender(); virtual void onMessageReceived(const sp &msg); private: enum { kWhatDrainQueue, kWhatSendSR, kWhatRTPNotify, kWhatRTCPNotify, #if ENABLE_RETRANSMISSION && RETRANSMISSION_ACCORDING_TO_RFC_XXXX kWhatRTPRetransmissionNotify, kWhatRTCPRetransmissionNotify, #endif }; static const int64_t kSendSRIntervalUs = 10000000ll; static const uint32_t kSourceID = 0xdeadbeef; static const size_t kMaxHistoryLength = 128; #if ENABLE_RETRANSMISSION && RETRANSMISSION_ACCORDING_TO_RFC_XXXX static const size_t kRetransmissionPortOffset = 120; #endif sp mNetSession; sp mNotify; TransportMode mTransportMode; AString mClientIP; // in TCP mode int32_t mRTPChannel; int32_t mRTCPChannel; // in UDP mode int32_t mRTPPort; int32_t mRTPSessionID; int32_t mRTCPSessionID; #if ENABLE_RETRANSMISSION && RETRANSMISSION_ACCORDING_TO_RFC_XXXX int32_t mRTPRetransmissionSessionID; int32_t mRTCPRetransmissionSessionID; #endif int32_t mClientRTPPort; int32_t mClientRTCPPort; bool mRTPConnected; bool mRTCPConnected; int64_t mFirstOutputBufferReadyTimeUs; int64_t mFirstOutputBufferSentTimeUs; uint32_t mRTPSeqNo; #if ENABLE_RETRANSMISSION && RETRANSMISSION_ACCORDING_TO_RFC_XXXX uint32_t mRTPRetransmissionSeqNo; #endif uint64_t mLastNTPTime; uint32_t mLastRTPTime; uint32_t mNumRTPSent; uint32_t mNumRTPOctetsSent; uint32_t mNumSRsSent; bool mSendSRPending; #if ENABLE_RETRANSMISSION List > mHistory; size_t mHistoryLength; #endif #if TRACK_BANDWIDTH int64_t mFirstPacketTimeUs; uint64_t mTotalBytesSent; #endif #if LOG_TRANSPORT_STREAM FILE *mLogFile; #endif void onSendSR(); void addSR(const sp &buffer); void addSDES(const sp &buffer); static uint64_t GetNowNTP(); #if ENABLE_RETRANSMISSION status_t parseTSFB(const uint8_t *data, size_t size); void addToHistory(const uint8_t *rtp, size_t rtpPacketSize); #endif status_t parseRTCP(const sp &buffer); status_t sendPacket(int32_t sessionID, const void *data, size_t size); void notifyInitDone(); void notifySessionDead(); void onDrainQueue(const sp &udpPackets); DISALLOW_EVIL_CONSTRUCTORS(Sender); }; } // namespace android #endif // SENDER_H_