/* * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2008 Apple Inc. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ * */ /* File: ClientSession.h */ #ifndef __CLIENT_SESSION__ #define __CLIENT_SESSION__ #include "Task.h" #include "TimeoutTask.h" #include "SVector.h" #include "RTSPClient.h" #include "ClientSocket.h" #include "SDPSourceInfo.h" #include "UDPSocket.h" #include "PlayerSimulator.h" class ClientSession : public Task { public: enum { kRTSPUDPClientType = 0, kRTSPTCPClientType = 1, kRTSPHTTPClientType = 2, kRTSPHTTPDropPostClientType = 3, kRTSPReliableUDPClientType = 4 }; typedef UInt32 ClientType; //The constructor will signal itself with Task::kStartEvent ClientSession( UInt32 inAddr, UInt16 inPort, char* inURL, ClientType inClientType, UInt32 inDurationInSec, UInt32 inStartPlayTimeInSec, UInt32 inRTCPIntervalInMS, UInt32 inOptionsIntervalInSec, UInt32 inHTTPCookie, Bool16 inAppendJunkData, UInt32 inReadInterval, UInt32 inSockRcvBufSize, Float32 inLateTolerance, char* inMetaInfoFields, Float32 inSpeed, UInt32 verboseLevel, char* inPacketRangePlayHeader, UInt32 inOverbufferWindowSizeInK, Bool16 sendOptions, Bool16 requestRandomData, SInt32 randomDataSize, Bool16 enable3GPP, UInt32 GBW = 0, UInt32 MBW = 0, UInt32 MTD = 0, Bool16 enableForcePlayoutDelay = false, UInt32 playoutDelay = 0, UInt32 bandwidth = 0, UInt32 bufferSpace = 0, UInt32 delayTime = 0, UInt32 startPlayDelay = 0, char *controlID = NULL, char *name = NULL, char *password = NULL); virtual ~ClientSession(); // // Signals. // // Send a kKillEvent to delete this object. // Send a kTeardownEvent to tell the object to send a TEARDOWN and abort enum { kTeardownEvent = 0x00000100 }; virtual SInt64 Run(); // // States. Find out what the object is currently doing enum { kSendingOptions = 0, kSendingDescribe = 1, kSendingSetup = 2, kSendingPlay = 3, kPlaying = 4, kSendingTeardown = 5, kDone = 6 }; // // Why did this session die? enum { kDiedNormally = 0, // Session went fine kTeardownFailed = 1, // Teardown failed, but session stats are all valid kRequestFailed = 2, // Session couldn't be setup because the server returned an error kBadSDP = 3, // Server sent back some bad SDP kSessionTimedout = 4, // Server not responding kConnectionFailed = 5, // Couldn't connect at all. kDiedWhilePlaying = 6 // Connection was forceably closed while playing the movie }; // // Once this client session is completely done with the TEARDOWN and ready to be // destructed, this will return true. Until it returns true, this object should not // be deleted. When it does return true, this object should be deleted. Bool16 IsDone() { return fState == kDone; } // // ACCESSORS RTSPClient* GetClient() { return fClient; } ClientSocket* GetSocket() { return fSocket; } SDPSourceInfo* GetSDPInfo() { return &fSDPParser; } UInt32 GetState() { return fState; } // When this object is in the kDone state, this will tell you why the session died. UInt32 GetReasonForDying() { return fDeathReason; } UInt32 GetRequestStatus() { return fClient->GetStatus(); } // Tells you the total time we were receiving packets. You can use this // for computing bit rate SInt64 GetTotalPlayTimeInMsec() { return fTotalPlayTime; } QTSS_RTPPayloadType GetTrackType(UInt32 inTrackIndex) { return fSDPParser.GetStreamInfo(inTrackIndex)->fPayloadType; } UInt32 GetNumPacketsReceived(UInt32 inTrackIndex) { return fStats[inTrackIndex].fNumPacketsReceived; } UInt32 GetNumBytesReceived(UInt32 inTrackIndex) { return fStats[inTrackIndex].fNumBytesReceived; } UInt32 GetNumPacketsOutOfOrder(UInt32 inTrackIndex) { return fStats[inTrackIndex].fNumOutOfOrderPackets; } UInt32 GetNumOutOfBoundPackets(UInt32 inTrackIndex) { return fStats[inTrackIndex].fNumOutOfBoundPackets; } UInt32 GetNumAcks(UInt32 inTrackIndex) { return fStats[inTrackIndex].fNumAcks; } UInt32 Get3gNumPacketsLost(UInt32 inTrackIndex) { return fPlayerSimulator.GetNumPacketsLost(inTrackIndex); } UInt32 Get3gNumDuplicates(UInt32 inTrackIndex) { return fPlayerSimulator.GetNumDuplicates(inTrackIndex); } UInt32 Get3gNumLatePackets(UInt32 inTrackIndex) { return fPlayerSimulator.GetNumLatePackets(inTrackIndex); } UInt32 Get3gNumBufferOverflowedPackets(UInt32 inTrackIndex) { return fPlayerSimulator.GetNumBufferOverflowedPackets(inTrackIndex); } //include packets with bad SSRC UInt32 GetNumMalformedPackets(UInt32 inTrackIndex) { return fStats[inTrackIndex].fNumMalformedPackets; } //Will reset the counter everytime it is called UInt32 GetSessionPacketsReceived() { UInt32 result = fNumPacketsReceived; fNumPacketsReceived = 0; return result; } // // Global stats static UInt32 GetActiveConnections() { return sActiveConnections; } static UInt32 GetPlayingConnections() { return sPlayingConnections; } static UInt32 GetConnectionAttempts() { return sTotalConnectionAttempts; } //The following two functions will reset the global counter every time it is called static UInt32 GetConnectionBytesReceived() { UInt32 result = sBytesReceived; sBytesReceived = 0; return result; } static UInt32 GetConnectionPacketsReceived() { UInt32 result = sPacketsReceived; sPacketsReceived = 0; return result; } private: enum { kRawRTSPControlType = 0, kRTSPHTTPControlType = 1, kRTSPHTTPDropPostControlType= 2 }; typedef UInt32 ControlType; enum { kUDPTransportType = 0, kReliableUDPTransportType = 1, kTCPTransportType = 2 }; typedef UInt32 TransportType; //Returns kUInt32_Max if there is no track with such trackID UInt32 TrackID2TrackIndex(UInt32 trackID) { for (UInt32 trackIndex = 0; trackIndex < fSDPParser.GetNumStreams(); trackIndex++) { if (fSDPParser.GetStreamInfo(trackIndex)->fTrackID == trackID) return trackIndex; } return kUInt32_Max; } ClientSocket* fSocket; // Connection object RTSPClient* fClient; // Manages the client connection SDPSourceInfo fSDPParser; // Parses the SDP in the DESCRIBE response TimeoutTask fTimeoutTask; // Kills this connection in the event the server isn't responding ControlType fControlType; TransportType fTransportType; UInt32 fDurationInSec; UInt32 fStartPlayTimeInSec; UInt32 fRTCPIntervalInMs; UInt32 fOptionsIntervalInSec; Bool16 fOptions; Bool16 fOptionsRequestRandomData; SInt32 fOptionsRandomDataSize; SInt64 fTransactionStartTimeMilli; UInt32 fState; // For managing the state machine UInt32 fDeathReason; UInt32 fNumSetups; UDPSocket** fUDPSocketArray; //these values starts as soon as the RTSP Play is completed; does not corresonds to actual media play time SInt64 fPlayTime; SInt64 fTotalPlayTime; SInt64 fLastRTCPTime; Bool16 fTeardownImmediately; Bool16 fAppendJunk; UInt32 fReadInterval; UInt32 fSockRcvBufSize; Float32 fSpeed; char* fPacketRangePlayHeader; //These values are for the wireless links only -- not end-to-end //Units are in kbps, milliseconds, and bytes UInt32 fGuarenteedBitRate; UInt32 fMaxBitRate; UInt32 fMaxTransferDelay; Bool16 fEnableForcePlayoutDelay; UInt32 fPlayoutDelay; UInt32 fBandwidth; //bps //the buffer space is per stream, not total space UInt32 fBufferSpace; UInt32 fDelayTime; //target buffering delay UInt32 fStartPlayDelay; //how much buffer should we keep before we start playing? in milliseconds Bool16 fEnable3GPP; // Client stats struct TrackStats { //Modified by ClientSession UInt32 fNumPacketsReceived; //track only good packets(but include late and duplicates) UInt32 fNumBytesReceived; //includes RTP header UInt32 fNumOutOfOrderPackets; //excludes duplicates UInt32 fNumOutOfBoundPackets; UInt32 fNumMalformedPackets; //include packets with bad SSRC UInt32 fNumAcks; //cumulative; counts ACK packets with masks as 1 ACK UInt16 fDestRTCPPort; UInt32 fServerSSRC; //0 for not available UInt32 fClientSSRC; //Used for the DLSR and LSR field of the RTCP SInt64 fLastSenderReportNTPTime; SInt64 fLastSenderReportLocalTime; //These values are used to calculate the fraction lost and cumulative number of packets lost field in the RTCP RR packet. //See RFC 3550 6.4.1 and A.3 //fHighestSeqNum is the highest valid sequence number received; note that this is 32 bits so that it never overflows. //An initial value of kUInt32_Max is used as an invalid marker(such that no valid sequence number has been received yet). UInt32 fHighestSeqNum; UInt32 fBaseSeqNum; UInt32 fExpectedPrior; UInt32 fReceivedPrior; SVector fPacketsToAck; TrackStats() : fNumPacketsReceived(0), fNumBytesReceived(0), fNumOutOfOrderPackets(0), fNumOutOfBoundPackets(0), fNumMalformedPackets(0), fNumAcks(0), fDestRTCPPort(0), fServerSSRC(0), fClientSSRC(0), fLastSenderReportNTPTime(0), fLastSenderReportLocalTime(0), fHighestSeqNum(kUInt32_Max), fBaseSeqNum(0), fExpectedPrior(0), fReceivedPrior(0) { } }; /* Client stats struct TrackStats { enum { kSeqNumMapSize = 100, kHalfSeqNumMap = 50 }; UInt16 fDestRTCPPort; UInt32 fNumPacketsReceived; UInt32 fNumBytesReceived; UInt32 fNumLostPackets; UInt32 fNumOutOfOrderPackets; UInt32 fNumThrownAwayPackets; UInt8 fSequenceNumberMap[kSeqNumMapSize]; UInt16 fWrapSeqNum; UInt32 fSSRC; Bool16 fIsSSRCValid; UInt16 fHighestSeqNum; UInt16 fLastAckedSeqNum; Bool16 fHighestSeqNumValid; UInt32 fNumAcks; UInt32 fNumDuplicates; }; */ UInt32 fOverbufferWindowSizeInK; UInt32 fCurRTCPTrack; //track index not track id UInt32 fNumPacketsReceived; //track only good packets(but include late and duplicates; see RFC3550 6.4.1) UInt32 fNumBytesReceived; //includes RTP header UInt32 fVerboseLevel; SVector fStats; //the index of this vector is the same as fSDPParser.GetStreamInfo PlayerSimulator fPlayerSimulator; //TrackStats* fStats; // // Global stats static UInt32 sActiveConnections; static UInt32 sPlayingConnections; static UInt32 sTotalConnectionAttempts; static UInt32 sBytesReceived; static UInt32 sPacketsReceived; // // Helper functions for Run() void SetupUDPSockets(); void ProcessRTPPacket(char* inPacket, UInt32 inLength, UInt32 inTrackID); void ProcessRTCPPacket(char* inPacket, UInt32 inLength, UInt32 inTrackID); OS_Error ReadMediaData(); OS_Error SendRTCPPackets(UInt32 trackIndex); void SendAckPackets(UInt32 inTrackIndex); //Calculates the RTCP RR's fraction lost and cumulative number of packets lost field info. void CalcRTCPRRPacketsLost(UInt32 trackIndex, UInt8 &outFracLost, SInt32 &outCumLostPackets); //Returns kUInt32_Max if newSeqNum is out of bound, otherwise returns the corresponding 32 bit sequence number. static UInt32 CalcSeqNum(UInt32 referenceSeqNum, UInt16 newSeqNum); }; #endif //__CLIENT_SESSION__