-
Notifications
You must be signed in to change notification settings - Fork 144
/
Copy pathClientSession.h
340 lines (287 loc) · 14.6 KB
/
ClientSession.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
/*
*
* @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<UInt32> 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<TrackStats> 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__