Add even more of the source
This should be about everything needed to build so far?
This commit is contained in:
parent
af3619d4fa
commit
849723c9cf
547 changed files with 149239 additions and 0 deletions
580
APIModules/QTSSReflectorModule/RelayOutput.cpp
Normal file
580
APIModules/QTSSReflectorModule/RelayOutput.cpp
Normal file
|
@ -0,0 +1,580 @@
|
|||
/*
|
||||
*
|
||||
* @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: RelayOutput.cpp
|
||||
|
||||
Contains: Implementation of object described in .h file
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "RelayOutput.h"
|
||||
|
||||
#include "OSMemory.h"
|
||||
#include "SocketUtils.h"
|
||||
#include "RTSPSourceInfo.h"
|
||||
|
||||
static StrPtrLen sUDPDestStr("udp_destination");
|
||||
static StrPtrLen sAnnouncedDestStr("announced_destination");
|
||||
|
||||
// STATIC DATA
|
||||
OSQueue RelayOutput::sRelayOutputQueue;
|
||||
OSMutex RelayOutput::sQueueMutex;
|
||||
|
||||
QTSS_ObjectType RelayOutput::qtssRelayOutputObjectType;
|
||||
|
||||
QTSS_AttributeID RelayOutput::sOutputType = qtssIllegalAttrID;
|
||||
QTSS_AttributeID RelayOutput::sOutputDestAddr = qtssIllegalAttrID;
|
||||
QTSS_AttributeID RelayOutput::sOutputLocalAddr = qtssIllegalAttrID;
|
||||
QTSS_AttributeID RelayOutput::sOutputUDPPorts = qtssIllegalAttrID;
|
||||
QTSS_AttributeID RelayOutput::sOutputRTSPPort = qtssIllegalAttrID;
|
||||
QTSS_AttributeID RelayOutput::sOutputURL = qtssIllegalAttrID;
|
||||
QTSS_AttributeID RelayOutput::sOutputTTL = qtssIllegalAttrID;
|
||||
QTSS_AttributeID RelayOutput::sOutputCurPacketsPerSec = qtssIllegalAttrID;
|
||||
QTSS_AttributeID RelayOutput::sOutputCurBitsPerSec = qtssIllegalAttrID;
|
||||
QTSS_AttributeID RelayOutput::sOutputTotalPacketsSent = qtssIllegalAttrID;
|
||||
QTSS_AttributeID RelayOutput::sOutputTotalBytesSent = qtssIllegalAttrID;
|
||||
|
||||
static char* sOutputTypeName = "output_type";
|
||||
static char* sOutputDestAddrName = "output_dest_addr";
|
||||
static char* sOutputLocalAddrName = "output_local_addr";
|
||||
static char* sOutputUDPPortsName = "output_udp_ports";
|
||||
static char* sOutputRTSPPortName = "output_rtsp_port";
|
||||
static char* sOutputURLName = "output_url";
|
||||
static char* sOutputTTLName = "output_ttl";
|
||||
|
||||
static char* sOutputCurPacketsPerSecName = "output_cur_packetspersec";
|
||||
static char* sOutputCurBitsPerSecName = "output_cur_bitspersec";
|
||||
static char* sOutputTotalPacketsSentName = "output_total_packets_sent";
|
||||
static char* sOutputTotalBytesSentName = "output_total_bytes_sent";
|
||||
|
||||
void RelayOutput::Register()
|
||||
{
|
||||
// Create the relay output object type
|
||||
(void)QTSS_CreateObjectType(&qtssRelayOutputObjectType);
|
||||
|
||||
// Add the static attributes to the qtssRelayOutputObjectType object
|
||||
(void)QTSS_AddStaticAttribute(qtssRelayOutputObjectType, sOutputTypeName, NULL, qtssAttrDataTypeCharArray);
|
||||
(void)QTSS_IDForAttr(qtssRelayOutputObjectType, sOutputTypeName, &sOutputType); // dest type
|
||||
|
||||
(void)QTSS_AddStaticAttribute(qtssRelayOutputObjectType, sOutputDestAddrName, NULL, qtssAttrDataTypeCharArray);
|
||||
(void)QTSS_IDForAttr(qtssRelayOutputObjectType, sOutputDestAddrName, &sOutputDestAddr); // dest addr
|
||||
|
||||
(void)QTSS_AddStaticAttribute(qtssRelayOutputObjectType, sOutputLocalAddrName, NULL, qtssAttrDataTypeCharArray);
|
||||
(void)QTSS_IDForAttr(qtssRelayOutputObjectType, sOutputLocalAddrName, &sOutputLocalAddr); // interface addr
|
||||
|
||||
(void)QTSS_AddStaticAttribute(qtssRelayOutputObjectType, sOutputUDPPortsName, NULL, qtssAttrDataTypeUInt16);
|
||||
(void)QTSS_IDForAttr(qtssRelayOutputObjectType, sOutputUDPPortsName, &sOutputUDPPorts); // udp ports
|
||||
|
||||
(void)QTSS_AddStaticAttribute(qtssRelayOutputObjectType, sOutputRTSPPortName, NULL, qtssAttrDataTypeUInt16);
|
||||
(void)QTSS_IDForAttr(qtssRelayOutputObjectType, sOutputRTSPPortName, &sOutputRTSPPort); // rtsp port
|
||||
|
||||
(void)QTSS_AddStaticAttribute(qtssRelayOutputObjectType, sOutputURLName, NULL, qtssAttrDataTypeCharArray);
|
||||
(void)QTSS_IDForAttr(qtssRelayOutputObjectType, sOutputURLName, &sOutputURL); // url
|
||||
|
||||
(void)QTSS_AddStaticAttribute(qtssRelayOutputObjectType, sOutputTTLName, NULL, qtssAttrDataTypeUInt16);
|
||||
(void)QTSS_IDForAttr(qtssRelayOutputObjectType, sOutputTTLName, &sOutputTTL); // ttl
|
||||
|
||||
(void)QTSS_AddStaticAttribute(qtssRelayOutputObjectType, sOutputCurPacketsPerSecName, NULL, qtssAttrDataTypeUInt32);
|
||||
(void)QTSS_IDForAttr(qtssRelayOutputObjectType, sOutputCurPacketsPerSecName, &sOutputCurPacketsPerSec);// cur packets/sec
|
||||
|
||||
(void)QTSS_AddStaticAttribute(qtssRelayOutputObjectType, sOutputCurBitsPerSecName, NULL, qtssAttrDataTypeUInt32);
|
||||
(void)QTSS_IDForAttr(qtssRelayOutputObjectType, sOutputCurBitsPerSecName, &sOutputCurBitsPerSec); // cur bits/sec
|
||||
|
||||
(void)QTSS_AddStaticAttribute(qtssRelayOutputObjectType, sOutputTotalPacketsSentName, NULL, qtssAttrDataTypeUInt64);
|
||||
(void)QTSS_IDForAttr(qtssRelayOutputObjectType, sOutputTotalPacketsSentName, &sOutputTotalPacketsSent);// total packets
|
||||
|
||||
(void)QTSS_AddStaticAttribute(qtssRelayOutputObjectType, sOutputTotalBytesSentName, NULL, qtssAttrDataTypeUInt64);
|
||||
(void)QTSS_IDForAttr(qtssRelayOutputObjectType, sOutputTotalBytesSentName, &sOutputTotalBytesSent); // total bytes
|
||||
|
||||
}
|
||||
|
||||
RelayOutput::RelayOutput(SourceInfo* inInfo, UInt32 inWhichOutput, RelaySession* inRelaySession, Bool16 isRTSPSourceInfo)
|
||||
: fRelaySession(inRelaySession),
|
||||
fOutputSocket(NULL, Socket::kNonBlockingSocketType),
|
||||
fNumStreams(inRelaySession->GetSourceInfo()->GetNumStreams()), // use the reflector session's source info
|
||||
fOutputInfo(*inInfo->GetOutputInfo(inWhichOutput)),
|
||||
fQueueElem(),
|
||||
fFormatter(&fHTMLBuf[0], kMaxHTMLSize),
|
||||
fPacketsPerSecond(0),
|
||||
fBitsPerSecond(0),
|
||||
fLastUpdateTime(0),
|
||||
fTotalPacketsSent(0),
|
||||
fTotalBytesSent(0),
|
||||
fLastPackets(0),
|
||||
fLastBytes(0),
|
||||
fClientSocket(NULL),
|
||||
fClient(NULL),
|
||||
fDoingAnnounce(false),
|
||||
fValid(true),
|
||||
fOutgoingSDP(NULL),
|
||||
fAnnounceTask(NULL),
|
||||
fRTSPOutputInfo(NULL)
|
||||
{
|
||||
Assert(fNumStreams > 0);
|
||||
|
||||
fQueueElem.SetEnclosingObject(this);
|
||||
fStreamCookieArray = NEW void*[fNumStreams];
|
||||
fTrackIDArray = NEW UInt32[fNumStreams];
|
||||
fOutputInfo.fPortArray = NEW UInt16[fNumStreams];//copy constructor doesn't do this
|
||||
::memset(fOutputInfo.fPortArray, 0, fNumStreams * sizeof(UInt16));
|
||||
|
||||
// create a bookmark for each stream we'll reflect
|
||||
this->InititializeBookmarks( inRelaySession->GetNumStreams() );
|
||||
|
||||
// Copy out all the track IDs for each stream
|
||||
for (UInt32 x = 0; x < fNumStreams; x++)
|
||||
{
|
||||
fTrackIDArray[x] = inRelaySession->GetSourceInfo()->GetStreamInfo(x)->fTrackID;
|
||||
fStreamCookieArray[x] = inRelaySession->GetStreamCookie(fTrackIDArray[x]);
|
||||
}
|
||||
|
||||
// Copy the contents of the output port array
|
||||
|
||||
if (inInfo->GetOutputInfo(inWhichOutput)->fPortArray != NULL)
|
||||
{
|
||||
UInt32 copySize = fNumStreams;
|
||||
if (fOutputInfo.fNumPorts < fNumStreams)
|
||||
copySize = fOutputInfo.fNumPorts;
|
||||
::memcpy(fOutputInfo.fPortArray, inInfo->GetOutputInfo(inWhichOutput)->fPortArray, copySize * sizeof(UInt16));
|
||||
}
|
||||
else if (fOutputInfo.fBasePort != 0)
|
||||
{
|
||||
for (UInt32 y = 0; y < fNumStreams; y++)
|
||||
fOutputInfo.fPortArray[y] = (UInt16) (fOutputInfo.fBasePort + (y * 2) );
|
||||
}
|
||||
|
||||
OS_Error err = BindSocket();
|
||||
if (err != OS_NoErr)
|
||||
{
|
||||
fValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
RTSPOutputInfo* rtspInfo = NULL;
|
||||
if (isRTSPSourceInfo)
|
||||
{
|
||||
// in the case of the announce source info, the passed in source info will have the new
|
||||
// output information, but only the session's source info will have the sdp and url.
|
||||
RTSPSourceInfo* rtspSourceInfo = (RTSPSourceInfo *)(inInfo);
|
||||
Assert(rtspSourceInfo != NULL);
|
||||
RTSPSourceInfo* sessionSourceInfo = (RTSPSourceInfo *)(inRelaySession->GetSourceInfo());
|
||||
Assert(sessionSourceInfo != NULL);
|
||||
|
||||
rtspInfo = rtspSourceInfo->GetRTSPOutputInfo(inWhichOutput);
|
||||
if (rtspInfo->fIsAnnounced)
|
||||
{
|
||||
fRTSPOutputInfo = NEW RTSPOutputInfo();
|
||||
fRTSPOutputInfo->Copy(*rtspInfo);
|
||||
|
||||
fDoingAnnounce = true;
|
||||
// set up rtsp socket and client
|
||||
fClientSocket = new TCPClientSocket(Socket::kNonBlockingSocketType);
|
||||
fClient = new RTSPClient(fClientSocket, false, RelaySession::sRelayUserAgent);
|
||||
|
||||
// set up the outgoing socket
|
||||
fClientSocket->Set(fOutputInfo.fDestAddr, rtspInfo->fAnnouncePort);
|
||||
int sndBufSize = 32 * 1024;
|
||||
int rcvBufSize=1024;
|
||||
fClientSocket->SetOptions(sndBufSize,rcvBufSize);
|
||||
|
||||
// set up the client object
|
||||
StrPtrLen url;
|
||||
if ((rtspInfo->fDestURl != NULL) && (strlen(rtspInfo->fDestURl) > 0))
|
||||
url.Set(rtspInfo->fDestURl);
|
||||
else
|
||||
url.Set(sessionSourceInfo->GetSourceURL());
|
||||
|
||||
fClient->Set(url);
|
||||
|
||||
fClient->SetTransportMode(RTSPClient::kPushMode);
|
||||
fClient->SetName(rtspInfo->fUserName);
|
||||
fClient->SetPassword(rtspInfo->fPassword);
|
||||
|
||||
UInt32 len;
|
||||
fOutgoingSDP = sessionSourceInfo->GetAnnounceSDP(fOutputInfo.fDestAddr, &len);
|
||||
fAnnounceState = kSendingAnnounce;
|
||||
fCurrentSetup = 0;
|
||||
fAnnounceTask = new RelayAnnouncer(this); // this will now go and run the async announce
|
||||
fAnnounceTask->Signal(Task::kStartEvent);
|
||||
}
|
||||
}
|
||||
|
||||
// Write the Output HTML
|
||||
// Looks like: Relaying to: 229.49.52.102, Ports: 16898 16900 Time to live: 15
|
||||
static StrPtrLen sHTMLStart("Relaying to: ");
|
||||
static StrPtrLen sPorts(", Ports: ");
|
||||
static StrPtrLen sTimeToLive(" Time to live: ");
|
||||
static StrPtrLen sHTMLEnd("<BR>");
|
||||
|
||||
// First, format the destination addr as a dotted decimal string
|
||||
char theIPAddrBuf[20];
|
||||
StrPtrLen theIPAddr(theIPAddrBuf, 20);
|
||||
struct in_addr theAddr;
|
||||
theAddr.s_addr = htonl(fOutputInfo.fDestAddr);
|
||||
SocketUtils::ConvertAddrToString(theAddr, &theIPAddr);
|
||||
|
||||
// Begin writing the HTML
|
||||
fFormatter.Put(sHTMLStart);
|
||||
fFormatter.Put(theIPAddr);
|
||||
fFormatter.Put(sPorts);
|
||||
|
||||
for (UInt32 y = 0; y < fNumStreams; y++)
|
||||
{
|
||||
// Write all the destination ports
|
||||
fFormatter.Put(fOutputInfo.fPortArray[y]);
|
||||
fFormatter.PutSpace();
|
||||
}
|
||||
|
||||
if (SocketUtils::IsMulticastIPAddr(inInfo->GetOutputInfo(inWhichOutput)->fDestAddr))
|
||||
{
|
||||
// Put the time to live if this is a multicast destination
|
||||
fFormatter.Put(sTimeToLive);
|
||||
fFormatter.Put(fOutputInfo.fTimeToLive);
|
||||
}
|
||||
fFormatter.Put(sHTMLEnd);
|
||||
|
||||
// Setup the StrPtrLen to point to the right stuff
|
||||
fOutputInfoHTML.Ptr = fFormatter.GetBufPtr();
|
||||
fOutputInfoHTML.Len = fFormatter.GetCurrentOffset();
|
||||
|
||||
OSMutexLocker locker(&sQueueMutex);
|
||||
sRelayOutputQueue.EnQueue(&fQueueElem);
|
||||
|
||||
SetupRelayOutputObject(rtspInfo);
|
||||
}
|
||||
|
||||
RelayOutput::~RelayOutput()
|
||||
{
|
||||
OSMutexLocker locker(&sQueueMutex);
|
||||
sRelayOutputQueue.Remove(&fQueueElem);
|
||||
|
||||
if (fClientSocket)
|
||||
delete fClientSocket;
|
||||
if (fClient)
|
||||
delete fClient;
|
||||
|
||||
delete [] fStreamCookieArray;
|
||||
|
||||
delete fOutgoingSDP;
|
||||
fOutgoingSDP = NULL;
|
||||
|
||||
if (fAnnounceTask != NULL)
|
||||
fAnnounceTask->fOutput = NULL;
|
||||
|
||||
if (fRTSPOutputInfo != NULL)
|
||||
delete fRTSPOutputInfo;
|
||||
|
||||
QTSS_Object outputObject;
|
||||
UInt32 len = sizeof(QTSS_Object);
|
||||
|
||||
for (int x = 0; QTSS_GetValue(fRelaySessionObject, RelaySession::sRelayOutputObject, x, &outputObject, &len) == QTSS_NoErr; x++)
|
||||
{
|
||||
Assert(outputObject != NULL);
|
||||
Assert(len == sizeof(QTSS_Object));
|
||||
|
||||
if (outputObject == fRelayOutputObject)
|
||||
{
|
||||
(void)QTSS_RemoveValue(fRelaySessionObject, RelaySession::sRelayOutputObject, x);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
OS_Error RelayOutput::BindSocket()
|
||||
{
|
||||
OS_Error theErr = fOutputSocket.Open();
|
||||
if (theErr != OS_NoErr)
|
||||
return theErr;
|
||||
|
||||
// We don't care what local port we bind to
|
||||
theErr = fOutputSocket.Bind(fOutputInfo.fLocalAddr, 0);
|
||||
if (theErr != OS_NoErr)
|
||||
return theErr;
|
||||
|
||||
// Set the ttl to be the proper value
|
||||
return fOutputSocket.SetTtl(fOutputInfo.fTimeToLive);
|
||||
}
|
||||
|
||||
Bool16 RelayOutput::Equal(SourceInfo* inInfo)
|
||||
{
|
||||
// First check if the Source Info matches this RelaySession
|
||||
if (!fRelaySession->Equal(inInfo))
|
||||
return false;
|
||||
for (UInt32 x = 0; x < inInfo->GetNumOutputs(); x++)
|
||||
{
|
||||
if (inInfo->GetOutputInfo(x)->Equal(fOutputInfo))
|
||||
{
|
||||
RTSPOutputInfo* rtspOutputInfo = NULL;
|
||||
if (inInfo->IsRTSPSourceInfo())
|
||||
{
|
||||
rtspOutputInfo = ((RTSPSourceInfo*)inInfo)->GetRTSPOutputInfo(x);
|
||||
if (!rtspOutputInfo->fIsAnnounced)
|
||||
rtspOutputInfo = NULL;
|
||||
}
|
||||
|
||||
if (fRTSPOutputInfo != NULL) // announced output
|
||||
{
|
||||
if (!fRTSPOutputInfo->Equal(rtspOutputInfo)) // doesn't match the output
|
||||
continue;
|
||||
}
|
||||
else if (rtspOutputInfo != NULL)
|
||||
continue;
|
||||
|
||||
// This is a rather special purpose function... here we set this
|
||||
// flag marking this particular output as a duplicate, because
|
||||
// we know it is equal to this object.
|
||||
// (This is used in QTSSReflectorModule.cpp:RereadRelayPrefs)
|
||||
inInfo->GetOutputInfo(x)->fAlreadySetup = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QTSS_Error RelayOutput::WritePacket(StrPtrLen* inPacket, void* inStreamCookie, UInt32 inFlags, SInt64 /*packetLatenessInMSec*/, SInt64* /*timeToSendThisPacketAgain*/, UInt64* packetIDPtr, SInt64* /*arrivalTimeMSec*/, Bool16 /*firstPacket */ )
|
||||
{
|
||||
|
||||
if (!fValid || fDoingAnnounce)
|
||||
return OS_NoErr; // Not done setting up or we had an error setting up
|
||||
|
||||
// we don't use packetLateness becuase relays don't need to worry about TCP flow control induced transmit delay
|
||||
|
||||
// Look for the matching streamID
|
||||
for (UInt32 x = 0; x < fNumStreams; x++)
|
||||
{
|
||||
if (inStreamCookie == fStreamCookieArray[x])
|
||||
{
|
||||
UInt16 theDestPort = fOutputInfo.fPortArray[x];
|
||||
Assert((theDestPort & 1) == 0); //this should always be an RTP port (even)
|
||||
if (inFlags & qtssWriteFlagsIsRTCP)
|
||||
theDestPort++;
|
||||
|
||||
(void)fOutputSocket.SendTo(fOutputInfo.fDestAddr, theDestPort,
|
||||
inPacket->Ptr, inPacket->Len);
|
||||
|
||||
// Update our totals
|
||||
fTotalPacketsSent++;
|
||||
fTotalBytesSent += inPacket->Len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If it is time to recalculate statistics, do so
|
||||
SInt64 curTime = OS::Milliseconds();
|
||||
if ((fLastUpdateTime + kStatsIntervalInMilSecs) < curTime)
|
||||
{
|
||||
// Update packets per second
|
||||
Float64 packetsPerSec = (Float64)((SInt64)fTotalPacketsSent - (SInt64)fLastPackets);
|
||||
packetsPerSec *= 1000;
|
||||
packetsPerSec /= (Float64)(curTime - fLastUpdateTime);
|
||||
fPacketsPerSecond = (UInt32)packetsPerSec;
|
||||
|
||||
// Update bits per second. Win32 doesn't implement UInt64 -> Float64.
|
||||
Float64 bitsPerSec = (Float64)((SInt64)fTotalBytesSent - (SInt64)fLastBytes);
|
||||
bitsPerSec *= 1000 * 8;//convert from seconds to milsecs, bytes to bits
|
||||
bitsPerSec /= (Float64)(curTime - fLastUpdateTime);
|
||||
fBitsPerSecond = (UInt32)bitsPerSec;
|
||||
|
||||
fLastUpdateTime = curTime;
|
||||
fLastPackets = fTotalPacketsSent;
|
||||
fLastBytes = fTotalBytesSent;
|
||||
}
|
||||
|
||||
return QTSS_NoErr;
|
||||
}
|
||||
|
||||
SInt64 RelayOutput::RelayAnnouncer::Run()
|
||||
{
|
||||
OSMutexLocker locker(RelayOutput::GetQueueMutex());
|
||||
SInt64 result = -1;
|
||||
if (fOutput != NULL)
|
||||
result = fOutput->RunAnnounce();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
SInt64 RelayOutput::RunAnnounce()
|
||||
{
|
||||
OS_Error err = OS_NoErr;
|
||||
SInt64 result = 1000;
|
||||
|
||||
if (fAnnounceState == kSendingAnnounce)
|
||||
{
|
||||
if (fOutgoingSDP == NULL || ::strlen(fOutgoingSDP) == 0)
|
||||
err = ENOTCONN;
|
||||
else
|
||||
{
|
||||
err = fClient->SendAnnounce(fOutgoingSDP);
|
||||
if (err == OS_NoErr)
|
||||
{
|
||||
delete fOutgoingSDP;
|
||||
fOutgoingSDP = NULL;
|
||||
if (fClient->GetStatus() == 200)
|
||||
fAnnounceState = kSendingSetup;
|
||||
else
|
||||
err = ENOTCONN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while ((fAnnounceState == kSendingSetup) && (err == OS_NoErr))
|
||||
{
|
||||
err = fClient->SendUDPSetup(fTrackIDArray[fCurrentSetup], 10000);
|
||||
if (err == OS_NoErr)
|
||||
{
|
||||
if (fClient->GetStatus() == 200)
|
||||
{
|
||||
fOutputInfo.fPortArray[fCurrentSetup] = fClient->GetServerPort(); // this got set from the Setup reply
|
||||
fCurrentSetup++;
|
||||
if (fCurrentSetup == fNumStreams)
|
||||
fAnnounceState = kSendingPlay;
|
||||
}
|
||||
else
|
||||
err = ENOTCONN;
|
||||
}
|
||||
}
|
||||
|
||||
if (fAnnounceState == kSendingPlay)
|
||||
{
|
||||
err = fClient->SendPlay(0);
|
||||
if (err == OS_NoErr)
|
||||
{
|
||||
if (fClient->GetStatus() == 200)
|
||||
fAnnounceState = kDone;
|
||||
else
|
||||
err = ENOTCONN;
|
||||
}
|
||||
}
|
||||
|
||||
if (fAnnounceState == kDone)
|
||||
{
|
||||
for (UInt32 index = 0; index < fNumStreams; index++) // source udp ports
|
||||
{
|
||||
UInt16 udpPort = fOutputInfo.fPortArray[index];
|
||||
err = QTSS_SetValue (fRelayOutputObject, sOutputUDPPorts, index, &udpPort, sizeof(udpPort));
|
||||
Assert(err == QTSS_NoErr);
|
||||
}
|
||||
|
||||
fDoingAnnounce = false;
|
||||
result = -1; // let the task die
|
||||
fAnnounceTask = NULL;
|
||||
}
|
||||
|
||||
if ((err == EINPROGRESS) || (err == EAGAIN))
|
||||
{
|
||||
// Request an async event
|
||||
fClientSocket->GetSocket()->SetTask(fAnnounceTask);
|
||||
fClientSocket->GetSocket()->RequestEvent(fClientSocket->GetEventMask() );
|
||||
}
|
||||
else if (err != OS_NoErr)
|
||||
{
|
||||
// We encountered some fatal error with the socket. Record this as a connection failure
|
||||
fValid = false;
|
||||
result = -1; // let the task die
|
||||
fAnnounceTask = NULL;
|
||||
}
|
||||
|
||||
if ( (-1 == result) && (NULL != fClientSocket) && (NULL != fClientSocket->GetSocket() ) )
|
||||
fClientSocket->GetSocket()->SetTask(NULL); //remove fAnnounceTask from event handling code. The task can be safely deleted after detaching from the socket.
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void RelayOutput::SetupRelayOutputObject(RTSPOutputInfo* inRTSPInfo)
|
||||
{
|
||||
fRelaySessionObject = fRelaySession->GetRelaySessionObject();
|
||||
QTSS_Error theErr = QTSS_NoErr;
|
||||
UInt32 outIndex = 0;
|
||||
|
||||
theErr = QTSS_LockObject (fRelaySessionObject);
|
||||
Assert(theErr == QTSS_NoErr);
|
||||
|
||||
theErr = QTSS_CreateObjectValue (fRelaySessionObject , RelaySession::sRelayOutputObject, qtssRelayOutputObjectType, &outIndex, &fRelayOutputObject);
|
||||
Assert(theErr == QTSS_NoErr);
|
||||
|
||||
if ((inRTSPInfo == NULL) || !inRTSPInfo->fIsAnnounced) // output type
|
||||
{
|
||||
theErr = QTSS_SetValue (fRelayOutputObject, sOutputType, 0, (void*)sUDPDestStr.Ptr, sUDPDestStr.Len);
|
||||
Assert(theErr == QTSS_NoErr);
|
||||
}
|
||||
else
|
||||
{
|
||||
theErr = QTSS_SetValue (fRelayOutputObject, sOutputType, 0, (void*)sAnnouncedDestStr.Ptr, sAnnouncedDestStr.Len); // output type
|
||||
Assert(theErr == QTSS_NoErr);
|
||||
|
||||
theErr = QTSS_SetValue (fRelayOutputObject, sOutputRTSPPort, 0, &inRTSPInfo->fAnnouncePort, sizeof(inRTSPInfo->fAnnouncePort)); // rtsp port
|
||||
Assert(theErr == QTSS_NoErr);
|
||||
|
||||
theErr = QTSS_SetValue (fRelayOutputObject, sOutputURL, 0, (fClient->GetURL())->Ptr, (fClient->GetURL())->Len); // output url
|
||||
Assert(theErr == QTSS_NoErr);
|
||||
}
|
||||
|
||||
char theIPAddrBuf[20];
|
||||
StrPtrLen theIPAddr(theIPAddrBuf, 20);
|
||||
|
||||
struct in_addr theDestAddr; // output destination address
|
||||
theDestAddr.s_addr = htonl(fOutputInfo.fDestAddr);
|
||||
SocketUtils::ConvertAddrToString(theDestAddr, &theIPAddr);
|
||||
|
||||
theErr = QTSS_SetValue (fRelayOutputObject, sOutputDestAddr, 0, (void*)theIPAddr.Ptr, theIPAddr.Len);
|
||||
Assert(theErr == QTSS_NoErr);
|
||||
|
||||
struct in_addr theLocalAddr; // output local address
|
||||
theLocalAddr.s_addr = htonl(fOutputInfo.fLocalAddr);
|
||||
SocketUtils::ConvertAddrToString(theLocalAddr, &theIPAddr);
|
||||
|
||||
theErr = QTSS_SetValue (fRelayOutputObject, sOutputLocalAddr, 0, (void*)theIPAddr.Ptr, theIPAddr.Len);
|
||||
Assert(theErr == QTSS_NoErr);
|
||||
|
||||
|
||||
for (UInt32 index = 0; index < fNumStreams; index++) // output udp ports
|
||||
{
|
||||
UInt16 udpPort = fOutputInfo.fPortArray[index];
|
||||
theErr = QTSS_SetValue (fRelayOutputObject, sOutputUDPPorts, index, &udpPort, sizeof(udpPort));
|
||||
Assert(theErr == QTSS_NoErr);
|
||||
}
|
||||
|
||||
theErr = QTSS_SetValue (fRelayOutputObject, sOutputTTL, 0, &(fOutputInfo.fTimeToLive), sizeof(fOutputInfo.fTimeToLive));
|
||||
Assert(theErr == QTSS_NoErr);
|
||||
|
||||
theErr = QTSS_SetValuePtr (fRelayOutputObject, sOutputCurPacketsPerSec, &fPacketsPerSecond, sizeof(fPacketsPerSecond));
|
||||
Assert(theErr == QTSS_NoErr);
|
||||
|
||||
theErr = QTSS_SetValuePtr (fRelayOutputObject, sOutputCurBitsPerSec, &fBitsPerSecond, sizeof(fBitsPerSecond));
|
||||
Assert(theErr == QTSS_NoErr);
|
||||
|
||||
theErr = QTSS_SetValuePtr (fRelayOutputObject, sOutputTotalPacketsSent, &fTotalPacketsSent, sizeof(fTotalPacketsSent));
|
||||
Assert(theErr == QTSS_NoErr);
|
||||
|
||||
theErr = QTSS_SetValuePtr (fRelayOutputObject, sOutputTotalBytesSent, &fTotalBytesSent, sizeof(fTotalBytesSent));
|
||||
Assert(theErr == QTSS_NoErr);
|
||||
|
||||
theErr = QTSS_UnlockObject (fRelaySessionObject);
|
||||
Assert(theErr == QTSS_NoErr);
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue