Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members
ClientSession.cpp
00001 00002 00003 /*********************************************************************** 00004 * * 00005 * ViTooKi * 00006 * * 00007 * title: ClientSession.cpp * 00008 * * 00009 * * 00010 * * 00011 * ITEC institute of the University of Klagenfurt (Austria) * 00012 * http://www.itec.uni-klu.ac.at * 00013 * * 00014 * * 00015 * For more information visit the ViTooKi homepage: * 00016 * http://ViTooKi.sourceforge.net * 00017 * vitooki-user@lists.sourceforge.net * 00018 * vitooki-devel@lists.sourceforge.net * 00019 * * 00020 * This file is part of ViTooKi, a free video toolkit. * 00021 * ViTooKi is free software; you can redistribute it and/or * 00022 * modify it under the terms of the GNU General Public License * 00023 * as published by the Free Software Foundation; either version 2 * 00024 * of the License, or (at your option) any later version. * 00025 * * 00026 * This program is distributed in the hope that it will be useful, * 00027 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00028 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00029 * GNU General Public License for more details. * 00030 * * 00031 * You should have received a copy of the GNU General Public License * 00032 * along with this program; if not, write to the Free Software * 00033 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * 00034 * MA 02111-1307, USA. * 00035 * * 00036 ***********************************************************************/ 00037 00038 /*********************************************************************** 00039 * * 00040 * REVISION HISTORY: * 00041 * * 00042 * * 00043 * * 00044 ***********************************************************************/ 00045 00046 00047 00048 #include "ClientSession.hpp" 00049 00050 #include "RTSP.hpp" 00051 #include "DataChannel.hpp" 00052 #include "DataSink.hpp" 00053 #include "ContainerInfo.hpp" 00054 #include "ESInfo.hpp" 00055 #include "Statistics.hpp" 00056 00057 #include "PacketizationLayer.hpp" 00058 #include "Url.hpp" 00059 #include "RFC3016.hpp" 00060 #include "RFC2250.hpp" 00061 00062 #include "metadata/TerminalCapabilities.hpp" 00063 #include "io/Rtp.hpp" 00064 #include "io/SimpleRtp.hpp" 00065 #include "SimpleStatistics.hpp" 00066 #include "adaptors/MP4Decoder.hpp" 00067 #include "adaptors/MP4audioDecoder.hpp" 00068 #include "adaptors/Forwarder.hpp" 00069 #include "cache/MetaObject.hpp" 00070 00071 00072 #ifdef WIN32 00073 #include <winsock2.h> 00074 #else 00075 #include <sys/socket.h> 00076 #include <arpa/inet.h> 00077 #include <netdb.h> 00078 #include <netinet/in.h> 00079 #endif 00080 00085 ClientSession::ClientSession(const char* uri, IO* vout, IO* aout, UserPreferences* up, bool enableRtx,bool visualize) 00086 { 00087 printf("\033[31mXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ClientSession UP: %p XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n\033[0m", up ); 00088 printf(uri); 00089 printf("\nX: min: %i, max: %i, best: %i\n", up->dimX.min, up->dimX.max, up->dimX.best); 00090 printf("B: min: %i, max: %i, best: %i\n", up->bitrate.min, up->bitrate.max, up->bitrate.best); 00091 printf("\n\n"); 00092 rtxEnabled=enableRtx; 00093 videoOut=vout; 00094 audioOut=aout; 00095 mp4Stream=NULL; 00096 protocol=NULL; 00097 assert(up); 00098 usrPref = up; 00099 // assert(up->pay); 00100 termCap=NULL; 00101 this->construct(uri); 00102 decodeData=visualize; 00103 } 00104 00105 ClientSession::ClientSession(const char* videoUri, const char* proxyUri, 00106 IO* vout, IO* aout, UserPreferences* up, 00107 bool enableRtx,bool visualize) 00108 { 00109 assert(videoUri); 00110 assert(proxyUri); 00111 rtxEnabled=enableRtx; 00112 videoOut=vout; 00113 audioOut=aout; 00114 mp4Stream=NULL; 00115 protocol=NULL; 00116 assert(up); 00117 usrPref = up; 00118 termCap=NULL; 00119 decodeData=visualize; 00120 url=new char[strlen(videoUri)+1]; 00121 strcpy(url,videoUri); 00122 // connect to proxy 00123 Url u(proxyUri); 00124 protocol = new RTSP(); 00125 const char* proxyName=u.getServerName(); 00126 int port=u.hasPort()?u.getPort():protocol->getDefaultPort(); 00127 server = new sockaddr_in(); 00128 dprintf_full("ClientSession::ClientSession: getting %s from %s:%i\n",videoUri,proxyName,port); 00129 if(!Url::convertUrlToSocket(proxyName,port,server,sessionControlChannel)) { 00130 // ignore proxy setting 00131 dprintf_err("Proxy connect failed! Ignoring Proxy... direct connect to server\n"); 00132 delete url; 00133 url=NULL; 00134 construct(videoUri); 00135 } 00136 else 00137 state = SESSION_CLOSED; 00138 }; 00139 ClientSession::ClientSession(const char* uri, IO* vout, IO* aout, TerminalCapabilities* tc,bool enableRtx,bool visualize) 00140 { 00141 rtxEnabled=enableRtx; 00142 videoOut=vout; 00143 audioOut=aout; 00144 termCap=tc; 00145 mp4Stream=NULL; 00146 protocol = NULL; 00147 usrPref = NULL; 00148 decodeData=visualize; 00149 this->construct(uri); 00150 00151 } 00152 00153 void ClientSession::construct(const char* uri) 00154 { 00155 // establish a connection to the server 00156 if(!uri) { 00157 dprintf_err("ClientSession::ClientSession: NULL url\r\n"); 00158 state=SESSION_ERR; 00159 return; 00160 } 00161 else { 00162 url=new char[strlen(uri)+1]; 00163 strcpy(url,uri); 00164 } 00165 00166 char* pUrl=strstr(url,"rtsp://"); 00167 pUrl+=strlen("rtsp://"); 00168 if(!pUrl) { 00169 dprintf_err("ClientSession::ClientSession: invalid RTSP url %s\r\n",url); 00170 state=SESSION_ERR; 00171 return; 00172 } 00173 00174 Url u(url); 00175 protocol = new RTSP(); 00176 const char* serverName=u.getServerName(); 00177 int port=u.hasPort()?u.getPort():protocol->getDefaultPort(); 00178 server = new sockaddr_in(); 00179 if(!Url::convertUrlToSocket(serverName,port,server,sessionControlChannel)) { 00180 state=SESSION_ERR; 00181 return; 00182 } 00183 state = SESSION_CLOSED; 00184 }; 00185 00186 ClientSession::ClientSession(int socket, const struct sockaddr_in *serv, const char* uri, 00187 IO* vout, IO* aout,TerminalCapabilities* tc, bool enableRtx,bool visualize) 00188 { 00189 rtxEnabled=enableRtx; 00190 state = SESSION_CLOSED; 00191 videoOut=vout; 00192 audioOut=aout; 00193 mp4Stream=NULL; 00194 usrPref = NULL; 00195 sessionControlChannel = socket; 00196 00197 if (serv) { 00198 server = new sockaddr_in(); 00199 memcpy(server, serv, sizeof(sockaddr_in)); 00200 } else { 00201 server = NULL; 00202 } 00203 00204 termCap=tc; 00205 00206 protocol = new RTSP(); 00207 if(!uri) 00208 url = NULL; 00209 else { 00210 url=new char[strlen(uri)+1]; 00211 strcpy(url,uri); 00212 } 00213 decodeData=visualize; 00214 }; 00215 00216 ClientSession::~ClientSession() 00217 { 00218 00219 #ifdef WIN32 00220 closesocket(sessionControlChannel); 00221 #else 00222 ::close(sessionControlChannel); 00223 #endif 00224 tearDown(INVALID_SESSIONID); 00225 if (protocol) { 00226 delete protocol; 00227 protocol = NULL; 00228 } 00229 00230 00231 00232 if ( server ) { 00233 delete server; 00234 server = NULL; 00235 } 00236 if (url) { 00237 delete url; 00238 url = NULL; 00239 } 00240 00241 00242 if(this->mp4Stream) 00243 delete mp4Stream; 00244 } 00245 00247 bool ClientSession::sendResponse(const char *str,int bytes) 00248 { 00249 if ( state == SESSION_ERR ) 00250 return false; 00251 00252 int n=0; 00253 int total=0; 00254 bool ret=false; 00255 dprintf_full("ClientSession::sendResponse: Writing %i bytes: XxX\033[33m%s\033[0mXxX\r\n",bytes,str); 00256 00257 while(bytes>0) { 00258 printf(">>>>>>>>>>>>>>SOCKET: %i with SessionState: %i<<<<<<<<<<<<<\n", sessionControlChannel, state); 00259 fflush(stdout); 00260 n=send(sessionControlChannel,str+total, bytes,0); 00261 if(n==-1) 00262 break; 00263 bytes-=n; 00264 total+=n; 00265 } 00266 if(bytes==0) 00267 ret=true; 00268 dprintf_full("ClientSession::sendResponse exit %i\r\n",(int)ret); 00269 return ret; 00270 }; 00271 00278 int ClientSession::readRequest(char* str, const int MAX_BYTES) 00279 { 00280 dprintf_full("\033[32mClientSession::readRequest( %p, %i )\n\033[0m", str, MAX_BYTES); 00281 if ( state == SESSION_ERR ) 00282 return -1; 00283 00284 int n=0; 00285 int total=0; 00286 memset(str,0,MAX_BYTES); 00287 00288 do { 00289 // n == 0 if connection closed 00290 // n < 0 if error 00291 n=recv(sessionControlChannel,str+total,MAX_BYTES-1-total,0); 00292 dprintf_full("ClientSession::readRequest: partial %i total %i\r\n",n,total); 00293 dprintf_full("ClientSession::readRequest:X%sX\r\n",str+total); 00294 if(n<=0) 00295 break; 00296 total+=n; 00297 } 00298 while(n>0 && !(total>3 && str[total-4]=='\r' && str[total-3]=='\n' && 00299 str[total-2]=='\r' && str[total-1]=='\n')); 00300 00301 dprintf_full("ClientSession::readRequest: %i\r\n",total);fflush(stdout); 00302 return total; 00303 }; 00304 00306 bool ClientSession::connect() 00307 { 00308 if(!protocol || !url) 00309 return false; 00310 char* serverID; 00311 00312 protocol->generateDescribeForUrl(url,PLAYER_ID,this->termCap,this->usrPref); 00313 00314 const char* req=protocol->getBuffer(); 00315 00316 if(!sendResponse(req,strlen(req))) { 00317 return false; 00318 } 00319 00320 00321 char *buffer = new char[MSG_BUFFER_SIZE]; 00322 buffer[0]=0; 00323 // read answer to describe 00324 int bytesRead=readRequest(buffer,MSG_BUFFER_SIZE); 00325 if(bytesRead<=0) { 00326 delete [] buffer; 00327 return false; 00328 } 00329 // FIXME: check RTSP 404 00330 00331 ContainerInfo* mp4=protocol->parseResponseDescribe(buffer,url,&serverID,&rtxInfo); 00332 if(this->mp4Stream) 00333 delete mp4Stream; 00334 mp4Stream=mp4; 00335 if(serverID) 00336 //printf(">>> %s\n",serverID); 00337 //delete serverID; 00338 00339 if(mp4) { 00340 state=SESSION_CONNECTED; 00341 } 00342 00343 delete [] buffer; 00344 00345 return state==SESSION_CONNECTED; 00346 }; 00347 00348 bool ClientSession::play(bool with_caching) 00349 { 00350 00351 dprintf_err("\033[32mClientSession::play(), mp4Stream is: %i\n\033[0m", (int)mp4Stream); 00352 00353 if(mp4Stream) 00354 { 00355 // search for the session 00356 int sessionId=0; 00357 u32 streamId=0; 00358 bool res = true; 00359 // start it 00360 for (list < DataChannel * >::iterator i = this->channels.begin(); 00361 i != this->channels.end(); i++) { 00362 streamId=(*i)->getESInfo()->getStreamId(); 00363 if(!clientObj[streamId]) { 00364 dprintf_err("ClientSession::play Failed to add NULL client???\r\n"); 00365 tearDown(TEARDOWN_ALL); 00366 state=SESSION_ERR; 00367 return false; 00368 } 00369 if ((*i)->getESInfo()->isVisualStream() || (*i)->getESInfo()->isAudioStream()) { 00370 sessionId=(*i)->getSessionId(); 00371 double duration=(double)(*i)->getESInfo()->getDurationInMs(); 00372 duration/=1000.0; 00373 if(rtxEnabled) 00374 protocol->generatePlay(this->url,sessionId,0.0,duration,RTP_PREFETCH_SECS); 00375 else 00376 protocol->generatePlay(this->url,sessionId,0.0,duration,3); 00377 const char* req=protocol->getBuffer(); 00378 if(!this->sendResponse(req,strlen(req))) { 00379 return false; 00380 } 00381 char *buffer = new char[MSG_BUFFER_SIZE]; 00382 int len=readRequest(buffer,MSG_BUFFER_SIZE); 00383 if(len<=0) 00384 { 00385 delete [] buffer; 00386 return false; 00387 } 00388 00389 if(!strstr(buffer,"200")) // status code for OK 00390 state=SESSION_ERR; 00391 if(state==SESSION_ERR) { 00392 delete [] buffer; 00393 return false; 00394 } 00395 00396 // insert client 00397 (*i)->insert(clientObj[streamId]); 00398 res &= (*i)->play(clientObj[streamId]->getDataSinkId(),RTP_PREFETCH_SECS); 00399 dprintf_full("ClientSession::play Successfully added client %s is %i\r\n", 00400 clientObj[streamId]->getAddress(), res); 00401 00402 00403 //IO* input=(*i)->getInput(); 00404 // if not yet started -> start it 00405 if (!(*i)->running()) { 00406 if ( with_caching ) 00407 { 00408 dprintf_full("\033[32mClientSession::enabled caching\n\033[32m"); 00409 (*i)->enableCaching(true,"."); 00410 } 00411 dprintf_full("\033[32mClientSession::thread started\n\033[0m"); 00412 (*i)->start(); 00413 state=SESSION_PLAYING; 00414 } else 00415 res= res & false; 00416 00417 delete [] buffer; 00418 } // a visual stream 00419 } // iterator 00420 return res; 00421 } //mp4Stream 00422 else { 00423 dprintf_err("ClientSession::play: FAILED. No ContainerInfo object\r\n"); 00424 } 00425 00426 dprintf_err("ClientSession::play: FAILED. No DataChannels found\r\n"); 00427 return false; 00428 }; 00429 00430 bool ClientSession::pause(u32 sessionId) 00431 { 00432 protocol->generatePause(this->url,sessionId); 00433 const char* req=protocol->getBuffer(); 00434 u32 streamId=0; 00435 // search for the session 00436 // pause it 00437 for (list < DataChannel * >::iterator i = this->channels.begin(); 00438 i != this->channels.end(); i++) { 00439 00440 if ((*i)->getSessionId() == sessionId) { 00441 if(!this->sendResponse(req,strlen(req))) { 00442 return false; 00443 } 00444 00445 char *buffer = new char[MSG_BUFFER_SIZE]; 00446 int len=readRequest(buffer,MSG_BUFFER_SIZE); 00447 if(len<0) { 00448 delete [] buffer; 00449 return false; 00450 } 00451 buffer[len]=0; 00452 if(!strstr(buffer,"200")) // status code for OK 00453 state=SESSION_ERR; 00454 else 00455 state=SESSION_PAUSED; 00456 streamId=(*i)->getESInfo()->getStreamId(); 00457 (*i)->pause(clientObj[streamId]->getDataSinkId()); 00458 00459 delete [] buffer; 00460 return state==SESSION_PAUSED; 00461 } 00462 } 00463 00464 return false; 00465 }; 00466 00467 bool ClientSession::tearDown(u32 sessionId) 00468 { 00469 if(sessionId==INVALID_SESSIONID) { 00470 // teardown all 00471 state = SESSION_CLOSED; 00472 list < DataChannel * >::iterator dcI; 00473 while (!channels.empty()) { 00474 dcI=channels.begin(); 00475 protocol->generateTeardown(this->url,(*dcI)->getSessionId()); 00476 const char* req=protocol->getBuffer(); 00477 this->sendResponse(req,strlen(req)); 00478 (*dcI)->teardown(clientObj[(*dcI)->getESInfo()->getStreamId()]->getDataSinkId()); 00479 // check if we have to delete it, might be shared with other sessions 00480 if((*dcI)->getNumberOfActiveDataSinks()==0) { 00481 (*dcI)->wait(); // wait for thread to finish 00482 delete (*dcI); 00483 } 00484 channels.pop_front(); 00485 } 00486 return true; 00487 } 00488 else { 00489 // teardown one session 00490 list < DataChannel * >::iterator dcI; 00491 if (!channels.empty()) { 00492 dcI = channels.begin(); 00493 while (dcI != channels.end()) { 00494 if ((*dcI)->getSessionId()== sessionId) { 00495 protocol->generateTeardown(this->url,sessionId); 00496 const char* req=protocol->getBuffer(); 00497 this->sendResponse(req,strlen(req)); 00498 char *t = new char[MSG_BUFFER_SIZE]; 00499 // read response -> overwrite req 00500 readRequest(t,MSG_BUFFER_SIZE); 00501 (*dcI)->teardown(clientObj[(*dcI)->getESInfo()->getStreamId()]->getDataSinkId()); 00502 // check if we have to delete it, might be shared with other sessions 00503 if((*dcI)->getNumberOfActiveDataSinks()==0) 00504 { 00505 (*dcI)->wait(); // wait for thread to finish 00506 delete (*dcI); 00507 00508 } 00509 channels.erase(dcI); 00510 if(channels.empty()) 00511 state = SESSION_CLOSED; 00512 00513 delete [] t; 00514 return true; 00515 } 00516 else { 00517 ++dcI; 00518 } 00519 } 00520 } 00521 return false; // delete on empty session 00522 } 00523 00524 return false; 00525 }; 00526 00527 void ClientSession::run() { 00528 00529 dprintf_full("\033[32mClientSession::run()\033[0m\n"); 00530 00531 if(!url) { 00532 dprintf_err("ClientSession::run(): No URL set. Can't continue\r\n"); 00533 this->exit(); 00534 return; 00535 } 00536 // url is set, check the session state 00537 if(this->state==SESSION_CLOSED) { 00538 if(!this->connect()) 00539 { 00540 printf("\033[33m!!! REJECTED REQUEST !!!\033[0m\n"); 00541 00542 state=SESSION_ERR; 00543 } 00544 else 00545 { 00546 printf("$$$$$$$$$$ REQUEST OK ... START STREAMING $$$$$$$$$$$$$$$\n"); 00547 } 00548 } 00549 if(this->state==SESSION_CONNECTED) { 00550 // do setup 00551 00552 if(mp4Stream==NULL) { 00553 tearDown(TEARDOWN_ALL); 00554 state=SESSION_ERR; 00555 this->exit(); 00556 return; 00557 } 00558 // FIXME: do SETUP for all ES of type visual & audio 00559 list<ESInfo*> *allES=mp4Stream->getESList(); 00560 if(allES->empty()) { 00561 tearDown(TEARDOWN_ALL); 00562 state=SESSION_ERR; 00563 this->exit(); 00564 return; 00565 } 00566 u32 streamId = 0; 00567 bool visualSet=false; 00568 bool audioSet=false; 00569 for(list<ESInfo*>::iterator esi=allES->begin(); 00570 esi!=allES->end(); ++esi) { 00571 00572 streamId = (*esi)->getStreamId(); 00573 00574 00575 00576 if( ((*esi)->isAudioStream() && !audioSet && audioOut) || 00577 ((*esi)->isVisualStream() && !visualSet && videoOut)) { 00578 dprintf_full("ClientSession::run(): streamID is %i\n",streamId); 00579 const char* buffer; 00580 if(rtxEnabled) 00581 protocol->generateSetup(url,streamId,portGen.getNextFreePortPair(),true, 00582 portGen.getNextFreePortPair()); 00583 else 00584 protocol->generateSetup(url,streamId,portGen.getNextFreePortPair(),true); 00585 buffer=protocol->getBuffer(); 00586 00587 if(!sendResponse(buffer,strlen(buffer))) 00588 state=SESSION_ERR; 00589 else 00590 state=SESSION_INITIALIZED; 00591 00592 if(state==SESSION_INITIALIZED) { 00593 // parse the response and create the RTP class 00594 char *response = new char[MSG_BUFFER_SIZE]; 00595 int len=readRequest(response,MSG_BUFFER_SIZE); 00596 if(len<=0) { 00597 state=SESSION_ERR; 00598 this->exit(); 00599 delete [] response; 00600 return; 00601 } 00602 int clientPort=0; 00603 int serverPort=0; 00604 bool unicast=true; 00605 char* ssrc=NULL; 00606 int sessionID; 00607 rtx_info* rtx=NULL; 00608 if(rtxEnabled && !rtxInfo.empty()) { 00609 list<rtx_group*>::iterator li=rtxInfo.begin(); 00610 while(li!=rtxInfo.end()) { 00611 if( (*li)->es && (*li)->es->getStreamId()==streamId) { 00612 rtx=(*li)->rtx; 00613 li=rtxInfo.end(); 00614 } 00615 else 00616 ++li; 00617 } 00618 } 00619 if(protocol->parseResponseSetup(response,&sessionID, 00620 &clientPort,&serverPort,&unicast,&ssrc,rtx)<4) { 00621 tearDown(TEARDOWN_ALL); 00622 state=SESSION_ERR; 00623 dprintf_err("parseResponseSetup failed\r\n"); 00624 if(ssrc) 00625 delete ssrc; 00626 this->exit(); 00627 00628 delete [] response; 00629 return; 00630 } 00631 dprintf_full("Session is %i\n",sessionID); 00632 char localhost[10]="127.0.0.1"; 00633 00634 PacketizationLayer * p; 00635 if ((*esi)->isAudioStream()) 00636 p = new RFC2250(); 00637 else 00638 p = new RFC3016(); 00639 00640 00641 IO* input = NULL; 00642 00643 #ifndef WINCE 00644 if ( !rtxEnabled ) 00645 { 00646 char logName[MAX_STR_LEN]; 00647 struct timeval t; 00648 gettimeofday(&t,NULL); 00649 sprintf(logName,"log%10i.%3i_%s_%s%llu_client.in", 00650 (int)t.tv_sec,(int)(t.tv_usec/1000), 00651 mp4Stream->getUrl()->getFileName(), 00652 ((*esi)->isAudioStream()?"aud":"vid"),(*esi)->getStreamId()); 00653 input= (IO*)new SimpleRtp( url, serverPort, clientPort, "127.0.0.1", *esi , p, false, logName, true, SimpleRtp::CTS_BASED, true, false); 00654 } 00655 else 00656 { 00657 #endif 00658 Statistics *stat = new Statistics(*esi,false); 00659 input=(IO*)new Rtp(localhost, serverPort, inet_ntoa(server->sin_addr), clientPort, 00660 *esi, p, false, this->termCap, NULL, stat); 00661 00662 if(rtx) 00663 ((Rtp*)input)->setRtxInfo(rtx); 00664 #ifndef WINCE 00665 } 00666 #endif 00667 00668 DataSink* clientTmp=0; 00669 Adaptor* a=NULL; 00670 if( (*esi)->isVisualStream()) { 00671 visualSet=true; 00672 videoOut->setESInfo( (*esi) ); 00673 00674 if(decodeData) 00675 a=new MP4Decoder(((VideoESInfo*)(*esi)),true, UncompressedVideoFrame::ColorSpaceRGB32); 00676 else { 00677 a=new Forwarder(); 00678 a->setESInfo(*esi); 00679 } 00680 clientTmp= new DataSink(0,videoOut,localhost,0,a); 00681 } 00682 else if( (*esi)->isAudioStream()) { 00683 audioSet=true; 00684 audioOut->setESInfo((*esi)); 00685 00686 if(decodeData) 00687 a=new MP4audioDecoder(((AudioESInfo*)(*esi)),true); 00688 else { 00689 a=new Forwarder(); 00690 a->setESInfo(*esi); 00691 } 00692 clientTmp= new DataSink(0,audioOut,localhost,0,a); 00693 } 00694 00695 // map clientObj to streamId 00696 clientObj[streamId]=clientTmp; 00697 // create DataChannel 00698 DataChannel* dc=new DataChannel(input,(*esi)); 00699 dc->setSessionId(sessionID); 00700 if(ssrc) 00701 delete ssrc; 00702 00703 setDataChannel(dc); 00704 00705 delete [] response; 00706 } // is audio or video 00707 } // for 00708 } 00709 allES->clear(); 00710 } 00711 if(this->state==SESSION_INITIALIZED || 00712 this->state==SESSION_PAUSED) { 00713 // do a play 00714 if(!this->play()) 00715 state=SESSION_ERR; 00716 } 00717 if(this->state==SESSION_PLAYING) { 00718 // we have tried to play 00719 // but we have to check the datachannels to be sure 00720 for (list < DataChannel * >::iterator i = this->channels.begin(); 00721 i != this->channels.end(); i++) { 00722 if( (*i)->running()) 00723 (*i)->wait(); 00724 } 00725 // teardown all 00726 #ifdef WIN32 00727 closesocket(sessionControlChannel); 00728 #else 00729 ::close(sessionControlChannel); 00730 #endif 00731 tearDown(INVALID_SESSIONID); 00732 state=SESSION_PAUSED; 00733 } 00734 this->exit(); 00735 } 00736 00737 00739 bool ClientSession::setRtxInfoForES(u32 esId, rtx_info* rtx) 00740 { 00741 const ESInfo* es=this->mp4Stream->getES(esId); 00742 if(!es) { 00743 dprintf("ClientSession::setRtxInfoForES: invalid esId as input\r\n"); 00744 return false; 00745 } 00746 00747 rtx_group* grp=new rtx_group(ACK,3000); 00748 grp->es=es; 00749 grp->rtx=rtx; 00750 rtx->mId=rtxInfo.size()+1; 00751 grp->midESInfo=esId; 00752 rtxInfo.push_back(grp); 00753 return true; 00754 }; 00755 00756 00758 rtx_group* ClientSession::getRtxGroup(u32 esId) 00759 { 00760 00761 for( list<rtx_group*>::iterator li=rtxInfo.begin(); 00762 li!=rtxInfo.end(); li++) { 00763 if(esId==(*li)->es->getStreamId()) 00764 return *li; 00765 } 00766 return NULL; 00767 00768 }; 00769 00770