/* * * @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: ReflectorSession.h Contains: This object supports reflecting an RTP multicast stream to N RTPStreams. It spaces out the packet send times in order to maximize the randomness of the sending pattern and smooth the stream. */ #include "QTSS.h" #include "OSRef.h" #include "StrPtrLen.h" #include "ResizeableStringFormatter.h" #include "MyAssert.h" #include "ReflectorStream.h" #include "SourceInfo.h" #include "OSArrayObjectDeleter.h" #ifndef _FILE_DELETER_ #define _FILE_DELETER_ class FileDeleter { public: FileDeleter(StrPtrLen* inSDPPath); ~FileDeleter(); private: StrPtrLen fFilePath; }; #endif #ifndef __REFLECTOR_SESSION__ #define __REFLECTOR_SESSION__ class ReflectorSession { public: // Public interface to generic RTP packet forwarding engine // // Initialize // // Call initialize before calling any other function in this class static void Initialize(); // Create one of these ReflectorSessions per source broadcast. For mapping purposes, // the object can be constructred using an optional source ID. // // Caller may also provide a SourceInfo object, though it is not needed and // will also need to be provided to SetupReflectorSession when that is called. ReflectorSession(StrPtrLen* inSourceID, SourceInfo* inInfo = NULL); virtual ~ReflectorSession(); // // MODIFIERS // Call this to initialize and setup the source sockets. Once this function // completes sucessfully, Outputs may be added through the function calls below. // // The SourceInfo object passed in here will be owned by the ReflectorSession. Do not // delete it. enum { kMarkSetup = 0, //After SetupReflectorSession is called, IsSetup returns true kDontMarkSetup = 1, //After SetupReflectorSession is called, IsSetup returns false kIsPushSession = 2 // When setting up streams handle port conflicts by allocating. }; QTSS_Error SetupReflectorSession(SourceInfo* inInfo, QTSS_StandardRTSP_Params* inParams, UInt32 inFlags = kMarkSetup, Bool16 filterState = true, UInt32 filterTimeout = 30); // Packets get forwarded by attaching ReflectorOutput objects to a ReflectorSession. void AddOutput(ReflectorOutput* inOutput, Bool16 isClient); void RemoveOutput(ReflectorOutput* inOutput, Bool16 isClient); void TearDownAllOutputs(); void RemoveSessionFromOutput(QTSS_ClientSessionObject inSession); void ManuallyMarkSetup() { fIsSetup = true; } // For the Relay's status, a ReflectorSession can format an informative bit of // HTML to describe the source. This must be called after the ReflectorSession // is all setup. void FormatHTML(StrPtrLen* inURL); // // ACCESSORS OSRef* GetRef() { return &fRef; } OSQueueElem* GetQueueElem() { return &fQueueElem; } UInt32 GetNumOutputs() { return fNumOutputs; } UInt32 GetNumStreams() { return fSourceInfo->GetNumStreams(); } StrPtrLen* GetSourceInfoHTML() { return &fSourceInfoHTML; } SourceInfo* GetSourceInfo() { return fSourceInfo; } StrPtrLen* GetLocalSDP() { return &fLocalSDP; } StrPtrLen* GetSourcePath() { return &fSourceID; } Bool16 IsSetup() { return fIsSetup; } ReflectorStream*GetStreamByIndex(UInt32 inIndex) { return fStreamArray[inIndex]; } void AddBroadcasterClientSession(QTSS_StandardRTSP_Params* inParams); QTSS_ClientSessionObject GetBroadcasterSession() { return fBroadcasterSession;} // For the QTSSSplitterModule, this object can cache a QTSS_StreamRef void SetSocketStream(QTSS_StreamRef inStream) { fSocketStream = inStream; } QTSS_StreamRef GetSocketStream() { return fSocketStream; } // A ReflectorSession keeps track of the aggregate bit rate each // stream is reflecting (RTP only). Initially, this will return 0 // until enough time passes to compute an accurate average. UInt32 GetBitRate(); // Returns true if this SourceInfo structure is equivalent to this // ReflectorSession. Bool16 Equal(SourceInfo* inInfo); // Each stream has a cookie associated with it. When the stream writes a packet // to an output, this cookie is used to identify which stream is writing the packet. // The below function is useful so outputs can get the cookie value for a stream ID, // and therefore mux the cookie to the right output stream. void* GetStreamCookie(UInt32 inStreamID); //Reflector quality levels: enum { kMaxHTMLSize = 128, kAudioOnlyQuality = 1, //UInt32 kNormalQuality = 0, //UInt32 kNumQualityLevels = 2 //UInt32 }; SInt64 GetInitTimeMS() { return fInitTimeMS; } void SetHasBufferedStreams(Bool16 enableBuffer) { fHasBufferedStreams = enableBuffer; } private: // Is this session setup? Bool16 fIsSetup; // For storage in the session map OSRef fRef; StrPtrLen fSourceID; OSQueueElem fQueueElem; // Relay uses this. unsigned int fNumOutputs; ReflectorStream** fStreamArray; char fHTMLBuf[kMaxHTMLSize]; StrPtrLen fSourceInfoHTML; ResizeableStringFormatter fFormatter; // The reflector session needs to hang onto the source info object // for it's entire lifetime. Right now, this is used for reflector-as-client. SourceInfo* fSourceInfo; StrPtrLen fLocalSDP; // For the QTSSSplitterModule, this object can cache a QTSS_StreamRef QTSS_StreamRef fSocketStream; QTSS_ClientSessionObject fBroadcasterSession; SInt64 fInitTimeMS; Bool16 fHasBufferedStreams; }; #endif