00001 // 00002 // Copyright (C) 2005 Andras Varga 00003 // 00004 // This program is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public License 00006 // as published by the Free Software Foundation; either version 2 00007 // of the License, or (at your option) any later version. 00008 // 00009 // This program is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU Lesser General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU Lesser General Public License 00015 // along with this program; if not, see <http://www.gnu.org/licenses/>. 00016 // 00017 00018 00019 // 00020 // based on the video streaming app of the similar name by Johnny Lai 00021 // 00022 00023 00024 #include "UDPVideoStreamSvr.h" 00025 #include "UDPControlInfo_m.h" 00026 00027 00028 Define_Module(UDPVideoStreamSvr); 00029 00030 inline std::ostream& operator<<(std::ostream& out, const UDPVideoStreamSvr::VideoStreamData& d) { 00031 out << "client=" << d.clientAddr << ":" << d.clientPort 00032 << " size=" << d.videoSize << " pksent=" << d.numPkSent << " bytesleft=" << d.bytesLeft; 00033 return out; 00034 } 00035 00036 UDPVideoStreamSvr::UDPVideoStreamSvr() 00037 { 00038 } 00039 00040 UDPVideoStreamSvr::~UDPVideoStreamSvr() 00041 { 00042 for (unsigned int i=0; i<streamVector.size(); i++) 00043 delete streamVector[i]; 00044 } 00045 00046 void UDPVideoStreamSvr::initialize() 00047 { 00048 waitInterval = &par("waitInterval"); 00049 packetLen = &par("packetLen"); 00050 videoSize = &par("videoSize"); 00051 serverPort = par("serverPort"); 00052 00053 numStreams = 0; 00054 numPkSent = 0; 00055 00056 WATCH_PTRVECTOR(streamVector); 00057 00058 bindToPort(serverPort); 00059 } 00060 00061 void UDPVideoStreamSvr::finish() 00062 { 00063 recordScalar("streams served", numStreams); 00064 recordScalar("packets sent", numPkSent); 00065 } 00066 00067 void UDPVideoStreamSvr::handleMessage(cMessage *msg) 00068 { 00069 if (msg->isSelfMessage()) 00070 { 00071 // timer for a particular video stream expired, send packet 00072 sendStreamData(msg); 00073 } 00074 else 00075 { 00076 // start streaming 00077 processStreamRequest(msg); 00078 } 00079 } 00080 00081 00082 void UDPVideoStreamSvr::processStreamRequest(cMessage *msg) 00083 { 00084 // register video stream... 00085 UDPControlInfo *ctrl = check_and_cast<UDPControlInfo *>(msg->getControlInfo()); 00086 00087 VideoStreamData *d = new VideoStreamData; 00088 d->clientAddr = ctrl->getSrcAddr(); 00089 d->clientPort = ctrl->getSrcPort(); 00090 d->videoSize = (*videoSize); 00091 d->bytesLeft = d->videoSize; 00092 d->numPkSent = 0; 00093 streamVector.push_back(d); 00094 00095 cMessage *timer = new cMessage("VideoStreamTmr"); 00096 timer->setContextPointer(d); 00097 00098 // ... then transmit first packet right away 00099 sendStreamData(timer); 00100 00101 numStreams++; 00102 } 00103 00104 00105 void UDPVideoStreamSvr::sendStreamData(cMessage *timer) 00106 { 00107 VideoStreamData *d = (VideoStreamData *) timer->getContextPointer(); 00108 00109 // generate and send a packet 00110 cPacket *pkt = new cPacket("VideoStrmPk"); 00111 long pktLen = packetLen->longValue(); 00112 if (pktLen > d->bytesLeft) 00113 pktLen = d->bytesLeft; 00114 pkt->setByteLength(pktLen); 00115 sendToUDP(pkt, serverPort, d->clientAddr, d->clientPort); 00116 00117 d->bytesLeft -= pktLen; 00118 d->numPkSent++; 00119 numPkSent++; 00120 00121 // reschedule timer if there's bytes left to send 00122 if (d->bytesLeft!=0) 00123 { 00124 simtime_t interval = (*waitInterval); 00125 scheduleAt(simTime()+interval, timer); 00126 } 00127 else 00128 { 00129 delete timer; 00130 // TBD find VideoStreamData in streamVector and delete it 00131 } 00132 }