540 lines
14 KiB
C++
540 lines
14 KiB
C++
/*
|
|
*
|
|
* @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_parsers.h"
|
|
|
|
char* SDPFileParser::sMediaTag = "m";
|
|
char* SDPFileParser::sAttributeTag = "a";
|
|
char* SDPFileParser::sConnectionTag = "c";
|
|
|
|
SDPFileParser::~SDPFileParser()
|
|
{
|
|
if (fSDPBuff)
|
|
{ delete[] fSDPBuff;
|
|
fSDPBuff = NULL;
|
|
}
|
|
}
|
|
|
|
bool SDPFileParser::IsCommented(SimpleString *theString)
|
|
{
|
|
if ( NULL == theString) return false;
|
|
if ( theString->fLen == 0) return false;
|
|
if ( theString->fTheString[0] == '#' ) return true; // It's commented if the first non-white char is #
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
int TextLine::Parse (SimpleString *textStrPtr)
|
|
{
|
|
short count = 0;
|
|
|
|
do
|
|
{
|
|
if (!textStrPtr) break;
|
|
|
|
count = CountDelimeters(textStrPtr,sWordDelimeters);
|
|
if (count < 1) break;
|
|
|
|
fWords.SetSize(count);
|
|
fSource = *textStrPtr;
|
|
SimpleString *listStringPtr = fWords.Begin();
|
|
|
|
SimpleString currentString;
|
|
currentString.SetString(textStrPtr->fTheString, 0);
|
|
|
|
for ( short i = 0; i < count; i ++)
|
|
{ GetNextThing(textStrPtr,¤tString, sWordDelimeters, ¤tString);
|
|
*listStringPtr = currentString;
|
|
listStringPtr++;
|
|
}
|
|
|
|
} while (false);
|
|
|
|
|
|
return count;
|
|
}
|
|
|
|
int LineAndWordsParser::Parse (SimpleString *textStrPtr)
|
|
{
|
|
short count = 0;
|
|
|
|
do
|
|
{
|
|
if (!textStrPtr) break;
|
|
|
|
count = CountDelimeters(textStrPtr,sLineDelimeters);
|
|
if (count < 1) break;
|
|
|
|
fLines.SetSize(count);
|
|
fSource = *textStrPtr;
|
|
TextLine *listStringPtr = fLines.Begin();
|
|
|
|
SimpleString currentString;
|
|
currentString.SetString(textStrPtr->fTheString, 0);
|
|
|
|
for ( short i = 0; i < count; i ++)
|
|
{ GetNextThing(textStrPtr,¤tString, sLineDelimeters, ¤tString);
|
|
listStringPtr->Parse(¤tString);
|
|
listStringPtr++;
|
|
}
|
|
} while (false);
|
|
|
|
return count;
|
|
}
|
|
|
|
|
|
short SDPFileParser::CountQTTextLines()
|
|
{
|
|
short numlines = 0;
|
|
TextLine *theLinePtr = fParser.fLines.Begin();
|
|
|
|
while (theLinePtr)
|
|
{ if (GetQTTextFromLine(theLinePtr))
|
|
numlines ++;
|
|
|
|
theLinePtr = fParser.fLines.Next();
|
|
};
|
|
|
|
return numlines;
|
|
}
|
|
|
|
|
|
short SDPFileParser::CountMediaEntries()
|
|
{
|
|
bool commented = false;
|
|
bool isEqual = false;
|
|
short numTracks = 0;
|
|
|
|
TextLine *theLinePtr = fParser.fLines.Begin();
|
|
SimpleString *firstWordPtr;
|
|
|
|
while (theLinePtr)
|
|
{
|
|
do
|
|
{ firstWordPtr = theLinePtr->fWords.Begin();
|
|
if (!firstWordPtr) break;
|
|
|
|
commented = IsCommented(firstWordPtr);
|
|
if (commented) break;
|
|
|
|
isEqual = Compare(firstWordPtr, SDPFileParser::sMediaTag, true);
|
|
if (!isEqual) break;
|
|
|
|
numTracks ++;
|
|
|
|
} while (false);
|
|
|
|
theLinePtr = fParser.fLines.Next();
|
|
};
|
|
|
|
return numTracks;
|
|
}
|
|
|
|
short SDPFileParser::CountRTPMapEntries()
|
|
{
|
|
short startPos = fParser.fLines.GetPos();
|
|
short result = 0;
|
|
TextLine *theLinePtr = fParser.fLines.Get();
|
|
SimpleString mapString("rtpmap");
|
|
SimpleString *aWordPtr;
|
|
bool isEqual;
|
|
|
|
while (theLinePtr)
|
|
{
|
|
aWordPtr = theLinePtr->fWords.Begin();
|
|
if (aWordPtr)
|
|
{
|
|
isEqual = Compare(aWordPtr, SDPFileParser::sAttributeTag, true);
|
|
if (isEqual) // see if this attribute is a rtpmap line
|
|
{
|
|
aWordPtr = theLinePtr->fWords.SetPos(1);
|
|
isEqual = Compare(aWordPtr, &mapString, false);
|
|
if (isEqual) result ++;
|
|
}
|
|
else // could be a comment or some other attribute
|
|
{ isEqual = Compare(aWordPtr, SDPFileParser::sMediaTag, true);
|
|
if (isEqual) break; // its another media line so stop
|
|
}
|
|
}
|
|
theLinePtr = fParser.fLines.Next();
|
|
};
|
|
|
|
fParser.fLines.SetPos(startPos);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
void SDPFileParser::GetPayLoadsFromLine(TextLine *theLinePtr, TypeMap *theTypeMapPtr)
|
|
{
|
|
short count = 0;
|
|
if (theLinePtr == NULL || theTypeMapPtr == NULL)
|
|
return;
|
|
|
|
SimpleString *aWordPtr = theLinePtr->fWords.SetPos(5);// get protocol ID str
|
|
while (aWordPtr)
|
|
{ count ++;
|
|
aWordPtr = theLinePtr->fWords.Next();// get next protocol ID str
|
|
}
|
|
|
|
theTypeMapPtr->fPayLoads.SetSize(count);
|
|
short* idPtr = theTypeMapPtr->fPayLoads.Begin();// get protocol ID ref
|
|
aWordPtr = theLinePtr->fWords.SetPos(5);// get protocol ID str
|
|
|
|
while (aWordPtr && idPtr)
|
|
{
|
|
*idPtr = (short) aWordPtr->GetInt();
|
|
aWordPtr = theLinePtr->fWords.Next();// get next protocol ID str
|
|
idPtr = theTypeMapPtr->fPayLoads.Next();// get next protocol ID ref
|
|
}
|
|
}
|
|
|
|
bool SDPFileParser::GetQTTextFromLine(TextLine *theLinePtr)
|
|
{
|
|
//a=x-qt-text-cpy:xxxxx
|
|
//a=x-qt-text-nam:xxxxxx
|
|
//a=x-qt-text-inf:xxxxxxx
|
|
|
|
bool result = false;
|
|
SimpleString *aWordPtr;
|
|
char *xString ="a=x-qt-text";
|
|
do
|
|
{
|
|
aWordPtr = theLinePtr->fWords.Begin();
|
|
if (!aWordPtr) break;
|
|
|
|
bool isEqual = (0 == strncmp(aWordPtr->fTheString, xString,strlen(xString) ) ) ? true: false;
|
|
if (!isEqual) break;
|
|
|
|
result = true;
|
|
|
|
} while (false);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
bool SDPFileParser::GetMediaFromLine(TextLine *theLinePtr, TypeMap *theTypeMapPtr)
|
|
{
|
|
bool result = false;
|
|
SimpleString *aWordPtr;
|
|
|
|
do
|
|
{
|
|
aWordPtr = theLinePtr->fWords.Begin();
|
|
if (!aWordPtr) break;
|
|
|
|
bool isEqual = Compare(aWordPtr, SDPFileParser::sMediaTag, true);
|
|
if (!isEqual) break;
|
|
|
|
aWordPtr = theLinePtr->fWords.SetPos(1);// get type
|
|
if (!aWordPtr) break;
|
|
|
|
theTypeMapPtr->fTheTypeStr = *aWordPtr;
|
|
|
|
aWordPtr = theLinePtr->fWords.SetPos(2);// get movie port
|
|
if (!aWordPtr) break;
|
|
|
|
theTypeMapPtr->fPort = aWordPtr->GetInt();
|
|
|
|
aWordPtr = theLinePtr->fWords.SetPos(3);// get protocol
|
|
if (!aWordPtr) break;
|
|
|
|
theTypeMapPtr->fProtocolStr = *aWordPtr;
|
|
|
|
GetPayLoadsFromLine(theLinePtr, theTypeMapPtr);
|
|
|
|
result = true;
|
|
} while (false);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
bool SDPFileParser::GetRTPMap(TextLine *theLinePtr,PayLoad *payloadPtr)
|
|
{
|
|
bool lineOK = false;
|
|
SimpleString *aWordPtr;
|
|
SimpleString mapString("rtpmap");
|
|
|
|
do
|
|
{
|
|
if (!theLinePtr || !payloadPtr) break;
|
|
|
|
aWordPtr = theLinePtr->fWords.SetPos(1); // the attribute name
|
|
if (!aWordPtr) break;
|
|
if (!Compare(aWordPtr, &mapString, false))
|
|
break;
|
|
|
|
aWordPtr = theLinePtr->fWords.Next(); // the Payload ID
|
|
if (!aWordPtr) break;
|
|
payloadPtr->payloadID = aWordPtr->GetInt();
|
|
|
|
aWordPtr = theLinePtr->fWords.Next(); // the Payload type string
|
|
if (!aWordPtr) break;
|
|
payloadPtr->payLoadString = *aWordPtr;
|
|
|
|
payloadPtr->timeScale = 0;
|
|
aWordPtr = theLinePtr->fWords.Next(); // the Payload timeScale
|
|
if (aWordPtr)
|
|
payloadPtr->timeScale = aWordPtr->GetInt();
|
|
|
|
lineOK = true;
|
|
|
|
} while (false);
|
|
|
|
return lineOK;
|
|
|
|
}
|
|
|
|
TextLine *SDPFileParser::GetRTPMapLines(TextLine *theLinePtr,TypeMap *theTypeMapPtr)
|
|
{
|
|
|
|
do
|
|
{
|
|
if (!theLinePtr || !theTypeMapPtr) break;
|
|
|
|
short numAttributes = CountRTPMapEntries();
|
|
theTypeMapPtr->fPayLoadTypes.SetSize(numAttributes);
|
|
PayLoad *payloadPtr = theTypeMapPtr->fPayLoadTypes.Begin();
|
|
|
|
while( theLinePtr && payloadPtr && (numAttributes > 0) )
|
|
{
|
|
bool haveMAP = GetRTPMap(theLinePtr,payloadPtr);
|
|
if (haveMAP)
|
|
{ numAttributes --;
|
|
payloadPtr = theTypeMapPtr->fPayLoadTypes.Next(); //skip to next payload entry
|
|
}
|
|
|
|
theLinePtr = fParser.fLines.Next(); // skip to next line
|
|
if(theLinePtr == NULL || Compare(theLinePtr->fWords.Begin(), SDPFileParser::sMediaTag, true)) //stop checking if this is a new media line
|
|
break;
|
|
|
|
}
|
|
} while (false);
|
|
|
|
return theLinePtr;
|
|
}
|
|
|
|
TextLine * SDPFileParser::GetTrackID(TextLine *theLinePtr,TypeMap *theTypeMapPtr)
|
|
{
|
|
SimpleString *aFieldPtr;
|
|
SimpleString *aWordPtr;
|
|
Bool16 foundID = false;
|
|
|
|
while(theLinePtr && !foundID)
|
|
{
|
|
if(Compare(theLinePtr->fWords.Begin(), SDPFileParser::sMediaTag, true)) //stop checking if this is a new media line
|
|
break;
|
|
|
|
do
|
|
{
|
|
SimpleString controlString("control");
|
|
|
|
aFieldPtr = theLinePtr->fWords.Begin();
|
|
if (!aFieldPtr) break;
|
|
|
|
bool isEqual = Compare(aFieldPtr, SDPFileParser::sAttributeTag, true);
|
|
if (!isEqual) break;
|
|
|
|
aWordPtr = theLinePtr->fWords.SetPos(1);
|
|
if (!aWordPtr) break;
|
|
|
|
isEqual = Compare(aWordPtr, &controlString, false);
|
|
if (!isEqual) break;
|
|
|
|
aWordPtr = theLinePtr->fWords.SetPos(3);
|
|
if (!aWordPtr) break;
|
|
|
|
theTypeMapPtr->fTrackID = aWordPtr->GetInt();
|
|
foundID = true;
|
|
|
|
} while (false);
|
|
|
|
|
|
theLinePtr = fParser.fLines.Next();
|
|
|
|
}
|
|
|
|
return theLinePtr;
|
|
|
|
}
|
|
bool SDPFileParser::ParseIPString(TextLine *theLinePtr)
|
|
{
|
|
bool result = false;
|
|
SimpleString *aWordPtr;
|
|
do
|
|
{
|
|
SimpleString ipIDString("IP4");
|
|
|
|
aWordPtr = theLinePtr->fWords.Begin();
|
|
if (!aWordPtr) break;
|
|
|
|
bool isEqual = Compare(aWordPtr,SDPFileParser::sConnectionTag, true);
|
|
if (!isEqual) break;
|
|
|
|
aWordPtr = theLinePtr->fWords.SetPos(2);
|
|
if (!aWordPtr) break;
|
|
|
|
isEqual = Compare(aWordPtr, &ipIDString, false);
|
|
if (!isEqual) break;
|
|
|
|
aWordPtr = theLinePtr->fWords.SetPos(3);
|
|
if (!aWordPtr) break;
|
|
|
|
fIPAddressString.SetString(aWordPtr->fTheString, aWordPtr->fLen);
|
|
result = true;
|
|
|
|
} while (false);
|
|
|
|
return result;
|
|
|
|
}
|
|
SInt32 SDPFileParser::ParseSDP(char *theBuff)
|
|
{
|
|
SInt32 result = 0;
|
|
bool found = false;
|
|
|
|
SimpleString source(theBuff);
|
|
fSource.SetString( theBuff, strlen(theBuff) );
|
|
fParser.Parse(&source);
|
|
|
|
|
|
// Test parse
|
|
#if 0
|
|
qtss_printf("-----------------------------------------------------\n");
|
|
char tempString[256];
|
|
TextLine *theLine = fParser.fLines.Begin();
|
|
while (theLine)
|
|
{ SimpleString *theWord = theLine->fWords.Begin();
|
|
while (theWord)
|
|
{ theWord->GetString(tempString,256);
|
|
qtss_printf(tempString);
|
|
theWord = theLine->fWords.Next();
|
|
if (theWord) qtss_printf(" _ ");
|
|
}
|
|
theLine = fParser.fLines.Next();
|
|
qtss_printf("\n");
|
|
}
|
|
// exit (0);
|
|
#endif
|
|
|
|
fNumQTTextLines = CountQTTextLines();
|
|
fQTTextLines.SetSize( (SInt16) fNumQTTextLines);
|
|
SimpleString *theQTTextPtr = fQTTextLines.Begin();
|
|
|
|
fNumTracks = CountMediaEntries();
|
|
fSDPMediaList.SetSize((SInt16) fNumTracks);
|
|
|
|
TextLine *theLinePtr = fParser.fLines.Begin();
|
|
TypeMap *theTypeMapPtr = fSDPMediaList.Begin();
|
|
|
|
bool foundIP = false;
|
|
while (theLinePtr && theTypeMapPtr)
|
|
{
|
|
if (foundIP == false)
|
|
{ foundIP = ParseIPString(theLinePtr);
|
|
}
|
|
|
|
if (theQTTextPtr && GetQTTextFromLine(theLinePtr))
|
|
{ SimpleString *srcLinePtr = theLinePtr->fWords.Begin();
|
|
theQTTextPtr->SetString(srcLinePtr->fTheString, strcspn(srcLinePtr->fTheString, "\r\n") );
|
|
theQTTextPtr = fQTTextLines.Next();
|
|
}
|
|
|
|
found = GetMediaFromLine(theLinePtr, theTypeMapPtr);
|
|
if (found)
|
|
{
|
|
theLinePtr = fParser.fLines.Next();
|
|
if (!theLinePtr) break; // no more lines to process
|
|
|
|
int startLine = fParser.fLines.GetPos();
|
|
|
|
theLinePtr = fParser.fLines.SetPos(startLine);
|
|
(void) GetRTPMapLines(theLinePtr,theTypeMapPtr);
|
|
|
|
theLinePtr = fParser.fLines.SetPos(startLine);
|
|
(void) GetTrackID(theLinePtr,theTypeMapPtr);
|
|
|
|
theLinePtr = fParser.fLines.SetPos(startLine);
|
|
theTypeMapPtr = fSDPMediaList.Next();
|
|
continue;
|
|
}
|
|
|
|
theLinePtr = fParser.fLines.Next();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
SInt32 SDPFileParser::ReadSDP(char *filename)
|
|
{
|
|
int result = -1;
|
|
SInt32 bytes= 0;
|
|
|
|
FILE *f = NULL;
|
|
|
|
if (fSDPBuff != NULL)
|
|
{ delete[] fSDPBuff;
|
|
fSDPBuff = NULL;
|
|
}
|
|
|
|
do
|
|
{
|
|
f = ::fopen(filename, "r");
|
|
if (f == NULL) break;
|
|
|
|
result = 1;
|
|
result = ::fseek(f, 0, SEEK_SET);
|
|
if (result != 0) break;
|
|
|
|
fSDPBuff = new char[cMaxBytes + 1];
|
|
if (NULL == fSDPBuff) break;
|
|
fSDPBuff[cMaxBytes] = 0;
|
|
|
|
bytes = ::fread(fSDPBuff, sizeof(char), cMaxBytes, f);
|
|
if (bytes < 1) break;
|
|
fSDPBuff[bytes] = 0;
|
|
|
|
result = ParseSDP(fSDPBuff);
|
|
if (result != 0) break;
|
|
|
|
result = 0;
|
|
|
|
} while (false);
|
|
|
|
if (f != NULL)
|
|
{ ::fclose (f);
|
|
f = NULL;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|