void JournalDM_TestModel::test_translation_parser() { JournalDM_TranslationParser aParser( 0 ); JournalDM_ExerciseList aResult; bool isBlock; aResult = aParser.extractData( "a = b", isBlock ); CPPUNIT_ASSERT_EQUAL( 2, aResult.size() ); CPPUNIT_ASSERT_EQUAL( QString( "... = b" ), aResult[0].Question ); CPPUNIT_ASSERT_EQUAL( QString( "a" ), aResult[0].Answer ); aResult = aParser.extractData( "a != b", isBlock ); CPPUNIT_ASSERT_EQUAL( 0, aResult.size() ); }
char* SDPSourceInfo::GetLocalSDP(UInt32* newSDPLen) { Assert(fSDPData.Ptr != NULL); bool appendCLine = true; UInt32 trackIndex = 0; char *localSDP = new char[fSDPData.Len * 2]; OSCharArrayDeleter charArrayPathDeleter(localSDP); StringFormatter localSDPFormatter(localSDP, fSDPData.Len * 2); StrPtrLen sdpLine; StringParser sdpParser(&fSDPData); char trackIndexBuffer[50]; // Only generate our own trackIDs if this file doesn't have 'em. // Our assumption here is that either the file has them, or it doesn't. // A file with some trackIDs, and some not, won't work. bool hasControlLine = false; while (sdpParser.GetDataRemaining() > 0) { //stop when we reach an empty line. sdpParser.GetThruEOL(&sdpLine); if (sdpLine.Len == 0) continue; switch (*sdpLine.Ptr) { case 'c': break;//ignore connection information case 'm': { //append new connection information right before the first 'm' if (appendCLine) { localSDPFormatter.Put(sCLine); localSDPFormatter.PutEOL(); if (!hasControlLine) { localSDPFormatter.Put(sControlLine); localSDPFormatter.PutEOL(); } appendCLine = false; } //the last "a=" for each m should be the control a= if ((trackIndex > 0) && (!hasControlLine)) { qtss_sprintf(trackIndexBuffer, "a=control:trackID=%" _S32BITARG_ "\r\n",trackIndex); localSDPFormatter.Put(trackIndexBuffer, ::strlen(trackIndexBuffer)); } //now write the 'm' line, but strip off the port information StringParser mParser(&sdpLine); StrPtrLen mPrefix; mParser.ConsumeUntil(&mPrefix, StringParser::sDigitMask); localSDPFormatter.Put(mPrefix); localSDPFormatter.Put("0", 1); (void)mParser.ConsumeInteger(NULL); localSDPFormatter.Put(mParser.GetCurrentPosition(), mParser.GetDataRemaining()); localSDPFormatter.PutEOL(); trackIndex++; break; } case 'a': { StringParser aParser(&sdpLine); aParser.ConsumeLength(NULL, 2);//go past 'a=' StrPtrLen aLineType; aParser.ConsumeWord(&aLineType); if (aLineType.Equal(sControlStr)) { aParser.ConsumeUntil(NULL, '='); aParser.ConsumeUntil(NULL, StringParser::sDigitMask); StrPtrLen aDigitType; (void)aParser.ConsumeInteger(&aDigitType); if (aDigitType.Len > 0) { localSDPFormatter.Put("a=control:trackID=", 18); localSDPFormatter.Put(aDigitType); localSDPFormatter.PutEOL(); hasControlLine = true; break; } } localSDPFormatter.Put(sdpLine); localSDPFormatter.PutEOL(); break; } default: { localSDPFormatter.Put(sdpLine); localSDPFormatter.PutEOL(); } } } if ((trackIndex > 0) && (!hasControlLine)) { qtss_sprintf(trackIndexBuffer, "a=control:trackID=%" _S32BITARG_ "\r\n",trackIndex); localSDPFormatter.Put(trackIndexBuffer, ::strlen(trackIndexBuffer)); } *newSDPLen = (UInt32)localSDPFormatter.GetCurrentOffset(); StrPtrLen theSDPStr(localSDP, *newSDPLen);//localSDP is not 0 terminated so initialize theSDPStr with the len. SDPContainer rawSDPContainer; (void) rawSDPContainer.SetSDPBuffer( &theSDPStr ); SDPLineSorter sortedSDP(&rawSDPContainer); return sortedSDP.GetSortedSDPCopy(); // return a new copy of the sorted SDP }
void SDPSourceInfo::Parse(char* sdpData, UInt32 sdpLen) { // // There are some situations in which Parse can be called twice. // If that happens, just return and don't do anything the second time. if (fSDPData.Ptr != NULL) return; Assert(fStreamArray == NULL); char *sdpDataCopy = new char[sdpLen]; Assert(sdpDataCopy != NULL); memcpy(sdpDataCopy,sdpData, sdpLen); fSDPData.Set(sdpDataCopy, sdpLen); // If there is no trackID information in this SDP, we make the track IDs start // at 1 -> N UInt32 currentTrack = 1; bool hasGlobalStreamInfo = false; StreamInfo theGlobalStreamInfo; //needed if there is one c= header independent of //individual streams StrPtrLen sdpLine; StringParser trackCounter(&fSDPData); StringParser sdpParser(&fSDPData); UInt32 theStreamIndex = 0; //walk through the SDP, counting up the number of tracks // Repeat until there's no more data in the SDP while (trackCounter.GetDataRemaining() > 0) { //each 'm' line in the SDP file corresponds to another track. trackCounter.GetThruEOL(&sdpLine); if ((sdpLine.Len > 0) && (sdpLine.Ptr[0] == 'm')) fNumStreams++; } //We should scale the # of StreamInfos to the # of trax, but we can't because //of an annoying compiler bug... fStreamArray = new StreamInfo[fNumStreams]; ::memset(fStreamArray, 0, sizeof(StreamInfo) * fNumStreams); // set the default destination as our default IP address and set the default ttl theGlobalStreamInfo.fDestIPAddr = INADDR_ANY; theGlobalStreamInfo.fTimeToLive = kDefaultTTL; //Set bufferdelay to default of 3 theGlobalStreamInfo.fBufferDelay = (Float32) eDefaultBufferDelay; //Now actually get all the data on all the streams while (sdpParser.GetDataRemaining() > 0) { sdpParser.GetThruEOL(&sdpLine); if (sdpLine.Len == 0) continue;//skip over any blank lines switch (*sdpLine.Ptr) { case 't': { StringParser mParser(&sdpLine); mParser.ConsumeUntil(NULL, StringParser::sDigitMask); UInt32 ntpStart = mParser.ConsumeInteger(NULL); mParser.ConsumeUntil(NULL, StringParser::sDigitMask); UInt32 ntpEnd = mParser.ConsumeInteger(NULL); SetActiveNTPTimes(ntpStart,ntpEnd); } break; case 'm': { if (hasGlobalStreamInfo) { fStreamArray[theStreamIndex].fDestIPAddr = theGlobalStreamInfo.fDestIPAddr; fStreamArray[theStreamIndex].fTimeToLive = theGlobalStreamInfo.fTimeToLive; } fStreamArray[theStreamIndex].fTrackID = currentTrack; currentTrack++; StringParser mParser(&sdpLine); //find out what type of track this is mParser.ConsumeLength(NULL, 2);//go past 'm=' StrPtrLen theStreamType; mParser.ConsumeWord(&theStreamType); if (theStreamType.Equal(sVideoStr)) fStreamArray[theStreamIndex].fPayloadType = qtssVideoPayloadType; else if (theStreamType.Equal(sAudioStr)) fStreamArray[theStreamIndex].fPayloadType = qtssAudioPayloadType; //find the port for this stream mParser.ConsumeUntil(NULL, StringParser::sDigitMask); SInt32 tempPort = mParser.ConsumeInteger(NULL); if ((tempPort > 0) && (tempPort < 65536)) fStreamArray[theStreamIndex].fPort = (UInt16) tempPort; // find out whether this is TCP or UDP mParser.ConsumeWhitespace(); StrPtrLen transportID; mParser.ConsumeWord(&transportID); static const StrPtrLen kTCPTransportStr("RTP/AVP/TCP"); if (transportID.Equal(kTCPTransportStr)) fStreamArray[theStreamIndex].fIsTCP = true; theStreamIndex++; } break; case 'a': { StringParser aParser(&sdpLine); aParser.ConsumeLength(NULL, 2);//go past 'a=' StrPtrLen aLineType; aParser.ConsumeWord(&aLineType); if (aLineType.Equal(sBroadcastControlStr)) { // found a control line for the broadcast (delete at time or delete at end of broadcast/server startup) // qtss_printf("found =%s\n",sBroadcastControlStr); aParser.ConsumeUntil(NULL,StringParser::sWordMask); StrPtrLen sessionControlType; aParser.ConsumeWord(&sessionControlType); if (sessionControlType.Equal(sAutoDisconnect)) { fSessionControlType = kRTSPSessionControl; } else if (sessionControlType.Equal(sAutoDisconnectTime)) { fSessionControlType = kSDPTimeControl; } } //if we haven't even hit an 'm' line yet, just ignore all 'a' lines if (theStreamIndex == 0) break; if (aLineType.Equal(sRtpMapStr)) { //mark the codec type if this line has a codec name on it. If we already //have a codec type for this track, just ignore this line if ((fStreamArray[theStreamIndex - 1].fPayloadName.Len == 0) && (aParser.GetThru(NULL, ' '))) { StrPtrLen payloadNameFromParser; (void)aParser.GetThruEOL(&payloadNameFromParser); char* temp = payloadNameFromParser.GetAsCString(); // qtss_printf("payloadNameFromParser (%x) = %s\n", temp, temp); (fStreamArray[theStreamIndex - 1].fPayloadName).Set(temp, payloadNameFromParser.Len); // qtss_printf("%s\n", fStreamArray[theStreamIndex - 1].fPayloadName.Ptr); } } else if (aLineType.Equal(sControlStr)) { // Modify By EasyDarwin //if ((fStreamArray[theStreamIndex - 1].fTrackName.Len == 0) && // (aParser.GetThru(NULL, ' '))) { StrPtrLen trackNameFromParser; aParser.ConsumeUntil(NULL,':'); aParser.ConsumeLength(NULL,1); aParser.GetThruEOL(&trackNameFromParser); char* temp = trackNameFromParser.GetAsCString(); // qtss_printf("trackNameFromParser (%x) = %s\n", temp, temp); (fStreamArray[theStreamIndex - 1].fTrackName).Set(temp, trackNameFromParser.Len); // qtss_printf("%s\n", fStreamArray[theStreamIndex - 1].fTrackName.Ptr); StringParser tParser(&trackNameFromParser); tParser.ConsumeUntil(NULL, '='); tParser.ConsumeUntil(NULL, StringParser::sDigitMask); fStreamArray[theStreamIndex - 1].fTrackID = tParser.ConsumeInteger(NULL); } } else if (aLineType.Equal(sBufferDelayStr)) { // if a BufferDelay is found then set all of the streams to the same buffer delay (it's global) aParser.ConsumeUntil(NULL, StringParser::sDigitMask); theGlobalStreamInfo.fBufferDelay = aParser.ConsumeFloat(); } } break; case 'c': { //get the IP address off this header StringParser cParser(&sdpLine); cParser.ConsumeLength(NULL, 9);//strip off "c=in ip4 " UInt32 tempIPAddr = SDPSourceInfo::GetIPAddr(&cParser, '/'); //grab the ttl SInt32 tempTtl = kDefaultTTL; if (cParser.GetThru(NULL, '/')) { tempTtl = cParser.ConsumeInteger(NULL); Assert(tempTtl >= 0); Assert(tempTtl < 65536); } if (theStreamIndex > 0) { //if this c= line is part of a stream, it overrides the //global stream information fStreamArray[theStreamIndex - 1].fDestIPAddr = tempIPAddr; fStreamArray[theStreamIndex - 1].fTimeToLive = (UInt16) tempTtl; } else { theGlobalStreamInfo.fDestIPAddr = tempIPAddr; theGlobalStreamInfo.fTimeToLive = (UInt16) tempTtl; hasGlobalStreamInfo = true; } } } } // Add the default buffer delay Float32 bufferDelay = (Float32) eDefaultBufferDelay; if (theGlobalStreamInfo.fBufferDelay != (Float32) eDefaultBufferDelay) bufferDelay = theGlobalStreamInfo.fBufferDelay; UInt32 count = 0; while (count < fNumStreams) { fStreamArray[count].fBufferDelay = bufferDelay; count ++; } }