Very rough first start, not even everything added
This commit is contained in:
commit
af3619d4fa
88 changed files with 24251 additions and 0 deletions
765
PlaylistBroadcaster.tproj/playlist_broadcaster.cpp
Normal file
765
PlaylistBroadcaster.tproj/playlist_broadcaster.cpp
Normal file
|
@ -0,0 +1,765 @@
|
|||
/*
|
||||
*
|
||||
* @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@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "playlist_broadcaster.h"
|
||||
#include "OS.h"
|
||||
#include "OSThread.h"
|
||||
#include "BroadcasterSession.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
QTFileBroadcaster::QTFileBroadcaster()
|
||||
{
|
||||
fRTPFilePtr = NULL;
|
||||
fMovieSDPParser = NULL;
|
||||
fBasePort = 0;
|
||||
fDebug = false;
|
||||
fDeepDebug = false;
|
||||
fQuitImmediatePtr = NULL;
|
||||
// transmit time trackers
|
||||
fLastTransmitTime = 0.0;
|
||||
|
||||
fStreamStartTime = 0;
|
||||
fMovieStartTime = 0;
|
||||
fMovieEndTime = 0;
|
||||
fMovieIntervalTime = 0;
|
||||
fMovieTimeDiffMilli = 0;
|
||||
|
||||
fMovieStart = false;
|
||||
fSendTimeOffset = 0.0;
|
||||
fMovieDuration = 0.0;
|
||||
fMovieTracks = 0;
|
||||
fMappedMovieTracks = 0;
|
||||
fNumMoviesPlayed = 0;
|
||||
fPlay = true;
|
||||
fSend = true;
|
||||
fBroadcastDefPtr = NULL;
|
||||
// current movie parameters parsed from SDP
|
||||
::strcpy(fCurrentMovieName, "-");
|
||||
::strcpy(fCurrentMovieCopyright, "-");
|
||||
::strcpy(fCurrentMovieComment, "-");
|
||||
::strcpy(fCurrentMovieAuthor, "-");
|
||||
::strcpy(fCurrentMovieArtist, "-");
|
||||
::strcpy(fCurrentMovieAlbum, "-");
|
||||
}
|
||||
|
||||
QTFileBroadcaster::~QTFileBroadcaster()
|
||||
{
|
||||
LogFileClose();
|
||||
if (fRTPFilePtr != NULL)
|
||||
{ delete fRTPFilePtr;
|
||||
}
|
||||
}
|
||||
|
||||
int QTFileBroadcaster::SetUp(PLBroadcastDef *broadcastDefPtr, bool *quitImmediatePtr)
|
||||
{
|
||||
int result = -1;
|
||||
int numStreams = 0;
|
||||
fQuitImmediatePtr = quitImmediatePtr;
|
||||
PlayListUtils::Initialize();
|
||||
do
|
||||
{
|
||||
if (! broadcastDefPtr)
|
||||
{ result = eParam; break; };
|
||||
|
||||
if (!broadcastDefPtr->mSDPFile || 0 == broadcastDefPtr->mSDPFile[0] )
|
||||
{ result = eSDPFileInvalidName; break; };
|
||||
|
||||
int nameLen = strlen(broadcastDefPtr->mSDPFile);
|
||||
if (nameLen > 255)
|
||||
{ result = eSDPFileInvalidName; break; };
|
||||
|
||||
if (0 == nameLen)
|
||||
{ result = eSDPFileInvalidName; break; };
|
||||
|
||||
if (broadcastDefPtr->mTheSession)
|
||||
{ if (!broadcastDefPtr->mDestSDPFile)
|
||||
{ result = eNetworkSDPFileNameInvalidMissing; break; };
|
||||
|
||||
if (!broadcastDefPtr->mDestSDPFile[0])
|
||||
{ result = eNetworkSDPFileNameInvalidMissing; break; };
|
||||
|
||||
if (!::strcmp(broadcastDefPtr->mDestSDPFile, "no_name"))
|
||||
{ result = eNetworkSDPFileNameInvalidMissing; break; };
|
||||
|
||||
// if ('/' == broadcastDefPtr->mDestSDPFile[0])
|
||||
// { result = eNetworkSDPFileNameInvalidBadPath; break; };
|
||||
}
|
||||
|
||||
result = fStreamSDPParser.ReadSDP(broadcastDefPtr->mSDPFile);
|
||||
|
||||
if (result != 0)
|
||||
{ if (result < 0) { result = eSDPFileNotFound; break; };
|
||||
if (result > 0) { result = eSDPFileInvalid; break; };
|
||||
}
|
||||
|
||||
|
||||
fBroadcastDefPtr = broadcastDefPtr;
|
||||
if (broadcastDefPtr->mTheSession == NULL)
|
||||
{ if (!broadcastDefPtr->mBasePort) { result = eSDPFileNoPorts; break; };
|
||||
|
||||
int portLen = strlen(broadcastDefPtr->mBasePort);
|
||||
if (0 == portLen) { result = eDescriptionInvalidDestPort; break; };
|
||||
if (portLen > 5 ) { result = eDescriptionInvalidDestPort; break; };
|
||||
|
||||
int basePort = atoi(broadcastDefPtr->mBasePort);
|
||||
if ( basePort > 65531 ) { result = eDescriptionInvalidDestPort; break; };
|
||||
if ( basePort < 5004 ) { result = eDescriptionInvalidDestPort; break; };
|
||||
|
||||
}
|
||||
|
||||
numStreams = fStreamSDPParser.GetNumTracks();
|
||||
if (numStreams == 0) { result = eSDPFileNoMedia; break; };
|
||||
|
||||
UDPSocketPair *socketArrayPtr = fSocketlist.SetSize(numStreams);
|
||||
if (socketArrayPtr == NULL) { result = eMem; break; };
|
||||
|
||||
// Bind SDP file defined ports to active stream ports
|
||||
{
|
||||
UInt16 streamIndex = 0;
|
||||
UInt16 rtpPort = 0;
|
||||
UInt16 rtcpPort = 0;
|
||||
TypeMap* mediaTypePtr;
|
||||
char sdpIPAddress[32];
|
||||
SimpleString* ipStringPtr = fStreamSDPParser.GetIPString();
|
||||
|
||||
if ( (NULL == ipStringPtr) || (ipStringPtr->fLen >= 32) )
|
||||
{
|
||||
result = eSDPFileInvalid;
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(sdpIPAddress,ipStringPtr->fTheString,ipStringPtr->fLen);
|
||||
sdpIPAddress[ipStringPtr->fLen] = '\0';
|
||||
|
||||
UDPSocketPair *aSocketPair = fSocketlist.Begin();
|
||||
Bool16 setupUDP = true;
|
||||
while (aSocketPair != NULL)
|
||||
{
|
||||
mediaTypePtr = fStreamSDPParser.fSDPMediaList.SetPos(streamIndex);
|
||||
|
||||
if (mediaTypePtr == NULL)
|
||||
{ result = eSDPFileInvalid;
|
||||
break;
|
||||
}
|
||||
|
||||
if (broadcastDefPtr->mTheSession != NULL)
|
||||
{
|
||||
mediaTypePtr->fPort = broadcastDefPtr->mTheSession->GetStreamDestPort(streamIndex);
|
||||
//qtss_printf("QTFileBroadcaster::SetUp streamIndex=%u port=%d\n",streamIndex,mediaTypePtr->fPort);
|
||||
|
||||
if (BroadcasterSession::kTCPTransportType == broadcastDefPtr->mTheSession->GetTransportType())
|
||||
{ aSocketPair->SetRTSPSession(broadcastDefPtr->mTheSession, (UInt8) streamIndex * 2);
|
||||
setupUDP = false;
|
||||
}
|
||||
else
|
||||
{ setupUDP = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (setupUDP)
|
||||
{
|
||||
SInt16 ttl = (SInt16) atoi(broadcastDefPtr->mTTL);
|
||||
if ( ( ttl > 255 ) || ( ttl < 1 ) )
|
||||
{ result = eSDPFileInvalidTTL; break;
|
||||
};
|
||||
|
||||
if (mediaTypePtr->fPort == 0)
|
||||
{
|
||||
result = eSDPFileInvalidPort;
|
||||
break;
|
||||
}
|
||||
|
||||
rtpPort = mediaTypePtr->fPort;
|
||||
rtcpPort = rtpPort + 1;
|
||||
|
||||
result = aSocketPair->OpenAndBind(rtpPort,rtcpPort,sdpIPAddress);
|
||||
if (result != 0)
|
||||
{
|
||||
result = eFailedBind;
|
||||
break;
|
||||
}
|
||||
|
||||
(void) aSocketPair->SetMultiCastOptions(ttl);
|
||||
|
||||
}
|
||||
|
||||
aSocketPair = fSocketlist.Next();
|
||||
streamIndex++;
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
MediaStream *mediaArrayPtr = fMediaStreamList.SetSize(numStreams);
|
||||
if (mediaArrayPtr == NULL)
|
||||
{
|
||||
result = eMem;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < numStreams; i ++)
|
||||
{ UDPSocketPair *socketPairPtr = fSocketlist.SetPos(i);
|
||||
MediaStream *mediaStreamPtr = fMediaStreamList.SetPos(i);
|
||||
TypeMap *streamMediaTypePtr = fStreamSDPParser.fSDPMediaList.SetPos(i);
|
||||
|
||||
if (socketPairPtr && mediaStreamPtr && streamMediaTypePtr)
|
||||
{
|
||||
mediaStreamPtr->fData.fSocketPair = socketPairPtr;
|
||||
streamMediaTypePtr->fMediaStreamPtr = mediaStreamPtr;
|
||||
mediaStreamPtr->fData.fStreamMediaTypePtr = streamMediaTypePtr;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = eMem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fMediaStreamList.SetUpStreamSSRCs();
|
||||
fStreamStartTime = PlayListUtils::Milliseconds();
|
||||
fMediaStreamList.StreamStarted(fStreamStartTime);
|
||||
result = 0;
|
||||
LogFileOpen();
|
||||
|
||||
} while (false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
PayLoad * QTFileBroadcaster::FindPayLoad(short id, ArrayList<PayLoad> *PayLoadListPtr)
|
||||
{
|
||||
PayLoad *thePayLoadPtr = PayLoadListPtr->Begin();
|
||||
while (thePayLoadPtr)
|
||||
{
|
||||
if (thePayLoadPtr->payloadID == id)
|
||||
break;
|
||||
|
||||
thePayLoadPtr = PayLoadListPtr->Next();
|
||||
}
|
||||
return thePayLoadPtr;
|
||||
}
|
||||
|
||||
|
||||
bool QTFileBroadcaster::CompareRTPMaps(TypeMap *movieMediaTypePtr, TypeMap *streamMediaTypePtr, short moviePayLoadID)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
do
|
||||
{
|
||||
PayLoad *moviePayLoadPtr = FindPayLoad(moviePayLoadID, &movieMediaTypePtr->fPayLoadTypes);
|
||||
if (!moviePayLoadPtr) break;
|
||||
|
||||
PayLoad *streamPayLoadPtr = streamMediaTypePtr->fPayLoadTypes.Begin();
|
||||
while (streamPayLoadPtr)
|
||||
{
|
||||
if (moviePayLoadPtr->timeScale == streamPayLoadPtr->timeScale)
|
||||
{ found = SimpleParser::Compare(&moviePayLoadPtr->payLoadString,&streamPayLoadPtr->payLoadString, false );
|
||||
}
|
||||
|
||||
if (found)
|
||||
{ moviePayLoadPtr->payloadID = streamPayLoadPtr->payloadID; // map movie ID to match stream id
|
||||
break;
|
||||
}
|
||||
streamPayLoadPtr = streamMediaTypePtr->fPayLoadTypes.Next();
|
||||
}
|
||||
|
||||
|
||||
} while (false);
|
||||
return found;
|
||||
}
|
||||
|
||||
bool QTFileBroadcaster::CompareMediaTypes(TypeMap *movieMediaTypePtr, TypeMap *streamMediaTypePtr)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
found = SimpleParser::Compare(&movieMediaTypePtr->fTheTypeStr,&streamMediaTypePtr->fTheTypeStr, false);
|
||||
if (found)
|
||||
{
|
||||
found = false;
|
||||
|
||||
short *movieIDPtr = movieMediaTypePtr->fPayLoads.Begin();
|
||||
while (movieIDPtr && !found)
|
||||
{
|
||||
short *streamIDPtr = streamMediaTypePtr->fPayLoads.Begin();
|
||||
while (streamIDPtr && !found)
|
||||
{
|
||||
|
||||
if (*movieIDPtr >= 96)
|
||||
found = CompareRTPMaps(movieMediaTypePtr, streamMediaTypePtr, *movieIDPtr);
|
||||
else
|
||||
found = (*streamIDPtr == *movieIDPtr) ? true : false;
|
||||
|
||||
streamIDPtr = streamMediaTypePtr->fPayLoads.Next();
|
||||
}
|
||||
|
||||
movieIDPtr = movieMediaTypePtr->fPayLoads.Next();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
int QTFileBroadcaster::MapMovieToStream()
|
||||
{
|
||||
int result = -1;
|
||||
bool matches = false;
|
||||
ArrayList<bool> map;
|
||||
bool *isMappedPtr;
|
||||
int masterPos = 0;
|
||||
int mappedTracks = 0;
|
||||
|
||||
map.SetSize(fStreamSDPParser.fSDPMediaList.Size());
|
||||
|
||||
isMappedPtr = map.Begin();
|
||||
|
||||
while (isMappedPtr)
|
||||
{ *isMappedPtr = false;
|
||||
isMappedPtr = map.Next();
|
||||
}
|
||||
|
||||
TypeMap *movieMediaTypePtr = fMovieSDPParser->fSDPMediaList.Begin();
|
||||
|
||||
while (movieMediaTypePtr)
|
||||
{
|
||||
TypeMap *streamMediaTypePtr = fStreamSDPParser.fSDPMediaList.Begin();
|
||||
|
||||
while (streamMediaTypePtr)
|
||||
{
|
||||
matches = CompareMediaTypes(movieMediaTypePtr, streamMediaTypePtr);
|
||||
|
||||
if (matches)
|
||||
{
|
||||
masterPos = fStreamSDPParser.fSDPMediaList.GetPos();
|
||||
isMappedPtr = map.SetPos(masterPos);
|
||||
if (isMappedPtr == NULL)
|
||||
break;
|
||||
|
||||
if (false == *isMappedPtr)
|
||||
{
|
||||
movieMediaTypePtr->fMediaStreamPtr = streamMediaTypePtr->fMediaStreamPtr;
|
||||
*isMappedPtr = true;
|
||||
mappedTracks++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
streamMediaTypePtr = fStreamSDPParser.fSDPMediaList.Next();
|
||||
}
|
||||
movieMediaTypePtr = fMovieSDPParser->fSDPMediaList.Next();
|
||||
}
|
||||
|
||||
result = mappedTracks;
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
UInt32 QTFileBroadcaster::GetSDPTracks(QTRTPFile *newRTPFilePtr)
|
||||
{
|
||||
char* sdpBuffer;
|
||||
int bufferLen = 0;
|
||||
UInt32 result = 0;
|
||||
|
||||
sdpBuffer = newRTPFilePtr->GetSDPFile(&bufferLen);
|
||||
fMovieSDPParser->ParseSDP(sdpBuffer);
|
||||
result = fMovieSDPParser->GetNumTracks();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int QTFileBroadcaster::AddTrackAndStream(QTRTPFile *newRTPFilePtr)
|
||||
{
|
||||
TypeMap* movieMediaTypePtr = fMovieSDPParser->fSDPMediaList.Begin();
|
||||
UInt32 trackID;
|
||||
char* cookie;
|
||||
int err = -1;
|
||||
|
||||
while (movieMediaTypePtr)
|
||||
{
|
||||
if (movieMediaTypePtr->fMediaStreamPtr != NULL)
|
||||
{
|
||||
trackID = movieMediaTypePtr->fTrackID;
|
||||
if (trackID == 0) break;
|
||||
|
||||
|
||||
movieMediaTypePtr->fMediaStreamPtr->fData.fMovieMediaTypePtr = movieMediaTypePtr;
|
||||
movieMediaTypePtr->fMediaStreamPtr->fData.fRTPFilePtr = newRTPFilePtr;
|
||||
movieMediaTypePtr->fMediaStreamPtr->fSend = fSend;
|
||||
|
||||
cookie = (char *) movieMediaTypePtr->fMediaStreamPtr;
|
||||
err = newRTPFilePtr->AddTrack(trackID, false);
|
||||
if (err != 0)
|
||||
break;
|
||||
|
||||
newRTPFilePtr->SetTrackCookies(trackID, cookie, 0);
|
||||
newRTPFilePtr->SetTrackSSRC(trackID, (UInt32) 0); // set later
|
||||
|
||||
err = newRTPFilePtr->Seek(0.0);
|
||||
if (err != QTRTPFile::errNoError)
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
movieMediaTypePtr = fMovieSDPParser->fSDPMediaList.Next();
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int QTFileBroadcaster::SetUpAMovie(char *theMovieFileName)
|
||||
{
|
||||
int err = -1;
|
||||
QTRTPFile *newRTPFilePtr = NULL;
|
||||
do {
|
||||
fMovieTracks = 0;
|
||||
fMappedMovieTracks = 0;
|
||||
|
||||
if (fMovieSDPParser != NULL) delete fMovieSDPParser;
|
||||
if (fRTPFilePtr != NULL) delete fRTPFilePtr;
|
||||
|
||||
fMovieSDPParser = NULL;
|
||||
fRTPFilePtr = NULL;
|
||||
|
||||
if (!theMovieFileName) { err = eMovieFileInvalidName; break; }
|
||||
int nameLen = strlen(theMovieFileName);
|
||||
if (nameLen > 255) { err = eMovieFileInvalidName; break; }
|
||||
if (0 == nameLen) { err = eMovieFileInvalidName; break; }
|
||||
|
||||
fMovieSDPParser = new SDPFileParser;
|
||||
if (NULL == fMovieSDPParser) { err = eMem; break;}
|
||||
|
||||
newRTPFilePtr = new QTRTPFile();
|
||||
if (NULL == newRTPFilePtr) { err = eMem; break;}
|
||||
|
||||
QTRTPFile::ErrorCode result = newRTPFilePtr->Initialize(theMovieFileName);
|
||||
err = EvalErrorCode(result);
|
||||
if (err) break;
|
||||
|
||||
fMovieTracks = GetSDPTracks(newRTPFilePtr);
|
||||
if (fMovieTracks < 1) { err = eMovieFileNoHintedTracks; break; }
|
||||
|
||||
fMappedMovieTracks = MapMovieToStream();
|
||||
if (fMappedMovieTracks < 1) { err = eMovieFileNoSDPMatches; break; }
|
||||
|
||||
err = AddTrackAndStream(newRTPFilePtr);
|
||||
if (err != 0) { err = eMovieFileInvalid; break; }
|
||||
|
||||
} while (false);
|
||||
|
||||
if (err)
|
||||
{ if (newRTPFilePtr)
|
||||
delete newRTPFilePtr;
|
||||
newRTPFilePtr = NULL;
|
||||
}
|
||||
|
||||
fRTPFilePtr = newRTPFilePtr;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void QTFileBroadcaster::MilliSleep(SInt32 sleepTimeMilli)
|
||||
{
|
||||
if (sleepTimeMilli > 0)
|
||||
{
|
||||
#if __solaris__
|
||||
struct timeval tv;
|
||||
::memset(&tv,0,sizeof(tv));
|
||||
tv.tv_usec = sleepTimeMilli * 1000;
|
||||
::select(0,NULL,NULL,NULL,&tv);
|
||||
#else
|
||||
OSThread::Sleep( (UInt32) sleepTimeMilli);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
Float64 QTFileBroadcaster::Sleep(Float64 transmitTimeMilli)
|
||||
{
|
||||
Float64 sleepTime;
|
||||
Float64 timeToSend;
|
||||
Float64 currentTime = (Float64) PlayListUtils::Milliseconds();
|
||||
|
||||
if (fMovieStart)
|
||||
{
|
||||
fMovieStart = false;
|
||||
}
|
||||
|
||||
|
||||
timeToSend = fMovieStartTime + transmitTimeMilli;
|
||||
sleepTime = timeToSend - currentTime;
|
||||
|
||||
|
||||
const Float64 maxSleepIntervalMilli = 100.0;
|
||||
const Float64 minSleepIntervalMilli = 1.0;
|
||||
Float64 intervalTime = sleepTime;
|
||||
SInt32 sleepMilli = 0;
|
||||
if (intervalTime > maxSleepIntervalMilli)
|
||||
{ while (intervalTime >= maxSleepIntervalMilli)
|
||||
{
|
||||
intervalTime -= maxSleepIntervalMilli;
|
||||
sleepMilli = (SInt32) maxSleepIntervalMilli;
|
||||
MilliSleep(sleepMilli);
|
||||
fMediaStreamList.UpdateSenderReportsOnStreams();
|
||||
//qtss_printf("sleepIntervalMilli %u \n",sleepMilli);
|
||||
}
|
||||
}
|
||||
if (intervalTime >= minSleepIntervalMilli)
|
||||
{ sleepMilli = (SInt32) intervalTime;
|
||||
MilliSleep(sleepMilli);
|
||||
//qtss_printf("sleepMilli %u \n",sleepMilli);
|
||||
}
|
||||
fMediaStreamList.UpdateSenderReportsOnStreams();
|
||||
|
||||
return sleepTime;
|
||||
}
|
||||
|
||||
/* changed by emil@popwire.com (see relaod.txt for info) */
|
||||
int QTFileBroadcaster::Play(char *mTimeFile)
|
||||
/* ***************************************************** */
|
||||
{
|
||||
SInt16 err = 0;
|
||||
Float64 transmitTime = 0;
|
||||
MediaStream *theStreamPtr = NULL;
|
||||
RTpPacket rtpPacket;
|
||||
unsigned int sleptTime;
|
||||
SInt32 movieStartOffset = 0; //z
|
||||
Bool16 negativeTime = false;
|
||||
fMovieDuration = fRTPFilePtr->GetMovieDuration();
|
||||
fSendTimeOffset = 0.0;
|
||||
fMovieStart = true;
|
||||
fNumMoviesPlayed ++;
|
||||
|
||||
if (fMovieEndTime > 0) // take into account the movie load time as well as the last movie early end.
|
||||
{ UInt64 timeNow = PlayListUtils::Milliseconds();
|
||||
fMovieIntervalTime = timeNow - fMovieEndTime;
|
||||
|
||||
SInt32 earlySleepTimeMilli = (SInt32)(fMovieTimeDiffMilli - fMovieIntervalTime);
|
||||
earlySleepTimeMilli -= 40; // Don't sleep the entire time we need some time to execute or else we will be late
|
||||
if (earlySleepTimeMilli > 0)
|
||||
{ OSThread::Sleep( earlySleepTimeMilli);
|
||||
}
|
||||
}
|
||||
|
||||
fMovieStartTime = PlayListUtils::Milliseconds();
|
||||
fMediaStreamList.MovieStarted(fMovieStartTime);
|
||||
|
||||
/* changed by emil@popwire.com (see relaod.txt for info) */
|
||||
if(mTimeFile!=NULL)
|
||||
{
|
||||
FILE *fTimeFile = NULL;
|
||||
struct timeval start, dur, end;
|
||||
struct tm tm_start, tm_dur, tm_end, timeResult;
|
||||
|
||||
memset (&start,0, sizeof(start));
|
||||
|
||||
SInt64 timenow = OS::Milliseconds();
|
||||
start.tv_sec = (SInt32) OS::TimeMilli_To_UnixTimeSecs(timenow);
|
||||
start.tv_usec = (SInt32) ((OS::TimeMilli_To_UnixTimeMilli(timenow) - (start.tv_sec * 1000)) * 1000);
|
||||
|
||||
dur.tv_sec = (SInt32)fMovieDuration;
|
||||
dur.tv_usec = (SInt32)((fMovieDuration - dur.tv_sec) * 1000000);
|
||||
|
||||
end.tv_sec = start.tv_sec + dur.tv_sec + (SInt32)((start.tv_usec + dur.tv_usec) / 1000000);
|
||||
end.tv_usec = (start.tv_usec + dur.tv_usec) % 1000000;
|
||||
time_t startSecs = start.tv_sec;
|
||||
time_t endSecs = end.tv_sec;
|
||||
memcpy(&tm_start, qtss_localtime(&startSecs, &timeResult), sizeof(struct tm));
|
||||
memcpy(&tm_end, qtss_localtime(&endSecs, &timeResult), sizeof(struct tm));
|
||||
|
||||
tm_dur.tm_hour = dur.tv_sec / 3600;
|
||||
tm_dur.tm_min = (dur.tv_sec % 3600) / 60;
|
||||
tm_dur.tm_sec = (dur.tv_sec % 3600) % 60;
|
||||
|
||||
// initialize all current movie parameters to unkown ("-").
|
||||
|
||||
::strcpy(fCurrentMovieName, "-");
|
||||
::strcpy(fCurrentMovieCopyright, "-");
|
||||
::strcpy(fCurrentMovieComment, "-");
|
||||
::strcpy(fCurrentMovieAuthor, "-");
|
||||
::strcpy(fCurrentMovieArtist, "-");
|
||||
::strcpy(fCurrentMovieAlbum, "-");
|
||||
|
||||
/* save start time, stop time and length of currently playing song to .current file */
|
||||
fTimeFile = fopen(mTimeFile, "a");
|
||||
if(fTimeFile)
|
||||
{
|
||||
SimpleString *theQTTextPtr = fMovieSDPParser->fQTTextLines.Begin();
|
||||
while (theQTTextPtr != NULL)
|
||||
{
|
||||
char tmp[256];
|
||||
::memcpy(tmp, theQTTextPtr->fTheString, theQTTextPtr->fLen);
|
||||
tmp[theQTTextPtr->fLen] = 0;
|
||||
// if this SDP parameter is needed for logging then cache it here so
|
||||
// we can log it later.
|
||||
if (::strstr(theQTTextPtr->fTheString, "a=x-qt-text-nam:")!=NULL)
|
||||
::strcpy(fCurrentMovieName, &tmp[16]);
|
||||
if (::strstr(theQTTextPtr->fTheString, "a=x-qt-text-cpy:")!=NULL)
|
||||
::strcpy(fCurrentMovieCopyright, &tmp[16]);
|
||||
if (::strstr(theQTTextPtr->fTheString, "a=x-qt-text-cmt:")!=NULL)
|
||||
::strcpy(fCurrentMovieComment, &tmp[16]);
|
||||
if (::strstr(theQTTextPtr->fTheString, "a=x-qt-text-aut:")!=NULL)
|
||||
::strcpy(fCurrentMovieAuthor, &tmp[16]);
|
||||
if (::strstr(theQTTextPtr->fTheString, "a=x-qt-text-ART:")!=NULL)
|
||||
::strcpy(fCurrentMovieArtist, &tmp[16]);
|
||||
if (::strstr(theQTTextPtr->fTheString, "a=x-qt-text-alb:")!=NULL)
|
||||
::strcpy(fCurrentMovieAlbum, &tmp[16]);
|
||||
fwrite(theQTTextPtr->fTheString,theQTTextPtr->fLen, sizeof(char),fTimeFile);
|
||||
qtss_fprintf(fTimeFile,"\n");
|
||||
theQTTextPtr = fMovieSDPParser->fQTTextLines.Next();
|
||||
}
|
||||
|
||||
time_t startTime = (time_t) start.tv_sec;
|
||||
time_t endTime = (time_t) end.tv_sec;
|
||||
char buffer[kTimeStrSize];
|
||||
char *timestringStart = qtss_ctime(&startTime, buffer, sizeof(buffer));
|
||||
qtss_fprintf(fTimeFile,"b=%02d:%02d:%02d:%06d %"_S32BITARG_" %s", (int) tm_start.tm_hour, (int) tm_start.tm_min, (int) tm_start.tm_sec, (int)start.tv_usec, (SInt32) startTime, timestringStart);
|
||||
char *timestringEnd = qtss_ctime(&endTime, buffer, sizeof(buffer));
|
||||
qtss_fprintf(fTimeFile,"e=%02d:%02d:%02d:%06d %"_S32BITARG_" %s", (int)tm_end.tm_hour, (int) tm_end.tm_min,(int) tm_end.tm_sec, (int) end.tv_usec,(SInt32) endTime, timestringEnd);
|
||||
qtss_fprintf(fTimeFile,"d=%02d:%02d:%02d:%06d %d \n", (int) tm_dur.tm_hour, (int) tm_dur.tm_min,(int) tm_dur.tm_sec, (int) dur.tv_usec, (int)dur.tv_sec);
|
||||
|
||||
fclose(fTimeFile);
|
||||
}
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (fQuitImmediatePtr && *fQuitImmediatePtr){err = 0; break; } // quit now not an error
|
||||
|
||||
if (fBroadcastDefPtr->mTheSession)
|
||||
{ UInt32 thePacketQLen = 0;
|
||||
thePacketQLen = fBroadcastDefPtr->mTheSession->GetPacketQLen();
|
||||
SInt64 maxSleep = PlayListUtils::Milliseconds() + 1000;
|
||||
if (thePacketQLen > eMaxPacketQLen)
|
||||
{ //qtss_printf("PacketQ too big = %"_U32BITARG_" \n", (UInt32) thePacketQLen);
|
||||
while ( (eMaxPacketQLen/2) < fBroadcastDefPtr->mTheSession->GetPacketQLen())
|
||||
{ this->SleepInterval(100.0);
|
||||
if (maxSleep < PlayListUtils::Milliseconds())
|
||||
break;
|
||||
}
|
||||
//qtss_printf("PacketQ after sleep = %"_U32BITARG_" \n", (UInt32) fBroadcastDefPtr->mTheSession->GetPacketQLen());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
transmitTime = fRTPFilePtr->GetNextPacket(&rtpPacket.fThePacket, &rtpPacket.fLength);
|
||||
theStreamPtr = (MediaStream*)fRTPFilePtr->GetLastPacketTrack()->Cookie1;
|
||||
err = fRTPFilePtr->Error();
|
||||
if (err != QTRTPFile::errNoError) {err = eMovieFileInvalid; break; } // error getting packet
|
||||
if (NULL == rtpPacket.fThePacket) {err = 0; break; } // end of movie not an error
|
||||
if (NULL == theStreamPtr) {err = eMovieFileInvalid; break; }// an error
|
||||
|
||||
|
||||
transmitTime *= (Float64) PlayListUtils::eMilli; // convert to milliseconds
|
||||
if (transmitTime < 0.0 && negativeTime == false) // Deal with negative transmission times
|
||||
{ movieStartOffset += (SInt32) (transmitTime / 15.0);
|
||||
negativeTime = true;
|
||||
}
|
||||
sleptTime = (unsigned int) Sleep(transmitTime);
|
||||
|
||||
err = theStreamPtr->Send(&rtpPacket);
|
||||
|
||||
if (err != 0) { break; }
|
||||
err = fMediaStreamList.UpdateStreams();
|
||||
if (err != 0) { break; }
|
||||
|
||||
if ( (fBroadcastDefPtr != NULL)
|
||||
&& (fBroadcastDefPtr->mTheSession != NULL)
|
||||
&& (fBroadcastDefPtr->mTheSession->GetReasonForDying() != BroadcasterSession::kDiedNormally)
|
||||
)
|
||||
{ break; }
|
||||
};
|
||||
|
||||
fMovieEndTime = (SInt64) PlayListUtils::Milliseconds();
|
||||
fMediaStreamList.MovieEnded(fMovieEndTime);
|
||||
|
||||
// see if the movie duration is greater than the time it took to send the packets.
|
||||
// the difference is a delay that we insert before playing the next movie.
|
||||
SInt64 playDurationMilli = (SInt64) fMovieEndTime - (SInt64) fMovieStartTime;
|
||||
fMovieTimeDiffMilli = ((SInt64) ( (Float64) fMovieDuration * (Float64) PlayListUtils::eMilli)) - (SInt64) playDurationMilli;
|
||||
fMovieTimeDiffMilli-= (movieStartOffset/2);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* changed by emil@popwire.com (see relaod.txt for info) */
|
||||
int QTFileBroadcaster::PlayMovie(char *movieFileName, char *currentFile)
|
||||
/* ***************************************************** */
|
||||
{
|
||||
|
||||
int err = eMovieFileInvalidName;
|
||||
if (movieFileName != NULL)
|
||||
{
|
||||
|
||||
err = SetUpAMovie(movieFileName);
|
||||
|
||||
if (!err && fPlay)
|
||||
/* changed by emil@popwire.com (see relaod.txt for info) */
|
||||
{ err = Play(currentFile);
|
||||
/* ***************************************************** */
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int QTFileBroadcaster::EvalErrorCode(QTRTPFile::ErrorCode err)
|
||||
{
|
||||
int result = eNoErr;
|
||||
|
||||
switch( err )
|
||||
{
|
||||
case QTRTPFile::errNoError:
|
||||
break;
|
||||
|
||||
case QTRTPFile::errFileNotFound:
|
||||
result = eMovieFileNotFound;
|
||||
break;
|
||||
|
||||
case QTRTPFile::errNoHintTracks:
|
||||
result = eMovieFileNoHintedTracks;
|
||||
break;
|
||||
|
||||
case QTRTPFile::errInvalidQuickTimeFile:
|
||||
result = eMovieFileInvalid;
|
||||
break;
|
||||
|
||||
case QTRTPFile::errInternalError:
|
||||
result = eInternalError;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = eInternalError;
|
||||
}
|
||||
return result;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue