OStreamUCast.cpp

Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) Massimo Cora' 2006 <maxcvs@email.it>
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (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 Library General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 #include "OStreamUCast.hh"
00020 
00021 using namespace std;
00022 
00023 //--------------------------------------------------------------------------
00024 // unicast streamer constructor
00025 
00026 OStreamUCast::OStreamUCast( on_parsable_image_cb *f, void *parsable_image_callback_data,
00027                                                    int num_of_streams /* = 1 */ ) :
00028                         f_parsable_image_cb ( f ),
00029                         _parsable_image_callback_data( parsable_image_callback_data ),
00030                         _num_of_streams( num_of_streams )
00031 {
00032         if ( _num_of_streams > 1 )
00033                 _multi_stream_mode = true;
00034         else
00035                 _multi_stream_mode = false;
00036         
00037         _scheduler = BasicTaskScheduler::createNew( );
00038         _env = BasicUsageEnvironment::createNew( *_scheduler );
00039 
00040         _dms_list = new list<OStreamOnDemandSMS *>;
00041         
00042         _watchVariable = 0;
00043 }
00044 
00045 
00046 OStreamUCast::~OStreamUCast() 
00047 {
00048         _env->reclaim();
00049         delete _scheduler;
00050 }
00051 
00052 
00053 //--------------------------------------------------------------------------
00054 // raise up a RTSP server and start streaming session
00055 
00056 bool OStreamUCast::startStreaming( int encoding_type,
00057                                                                    char* file_path,                             /* = NULL */
00058                                                                    int camera_num,                              /* = 0 */
00059                                                                    int audio_port,                              /* = -1 */
00060                                                                    const char* subsession_url,  /* = "testStream" */
00061                                                                    unsigned short port_rtsp,    /* = 8554 */
00062                                                                    unsigned int fps                     /* = 25 */
00063                                                                   )  
00064 {
00065         char *subsession_str = strdup( subsession_url );
00066         Port port_to_listen( port_rtsp );
00067         
00068         _fps = fps;
00069 
00070         createRTSPInstance( port_to_listen );
00071         createServerMediaSession( encoding_type, subsession_str, file_path, camera_num, audio_port );
00072 
00073         // Finally, start the streaming on demand:
00074 
00075         // returns when the watch variable is != 0 as from 
00076         // http://www.live.com/liveMedia/doxygen/html/UsageEnvironment_8hh-source.html
00077         // FIXME BUG: when there are other clients listening in unicast there's a crash here
00078         _env->taskScheduler().doEventLoop( &_watchVariable ); 
00079 
00080         // we reach this point after stopStreaming(), 
00081         // which set the watchVariable to 1: the doEventLoop returns.
00082 
00083         free ( subsession_str );
00084         
00085         return true;
00086 }
00087 
00088 
00089 //--------------------------------------------------------------------------
00090 // will stop the streaming
00091 
00092 bool OStreamUCast::stopStreaming() {
00093 
00094         // remove the _sms server, along with the *VideoSource inside it.
00095         _rtspServer->removeServerMediaSession( _sms );
00096 
00097         // close the rtsp server
00098         Medium::close( _rtspServer );
00099 
00100         _watchVariable = 1;
00101         return true;
00102 }
00103 
00104 
00105 //--------------------------------------------------------------------------
00106 //
00107 
00108 void OStreamUCast::createRTSPInstance( Port &port_to_listen ) {
00109 
00110         // create a new server.
00111         _rtspServer = RTSPServer::createNew( *_env, port_to_listen, NULL, 0 );
00112 
00113         if ( _rtspServer == NULL ) {
00114                 *_env << "Failed to create RTSP server: " << _env->getResultMsg() << "\n";
00115                 exit(1);
00116         }
00117 }
00118 
00119 
00120 //--------------------------------------------------------------------------
00121 //
00122 
00123 void OStreamUCast::createServerMediaSession( int encoding_type, char *sub_url,
00124                                                                                          char* file_path, int camera_num, int audio_num ) 
00125 {
00126         bool using_file = (file_path != NULL) ? true : false;
00127         bool using_audio = (audio_num != -1) ? true : false;
00128         bool using_video = (encoding_type != OSTREAM_ENCODING_NONE) ? true : false;
00129                                                                                                          
00130         // create a new server
00131         _sms = ServerMediaSession::createNew( *_env, sub_url, 0,
00132                    "Session streamed by Omnimeeting",  true );
00133 
00134         OStreamOnDemandSMS *on_demand_sms;
00135         // single mode
00136         if ( using_video ) {
00137                 if ( _multi_stream_mode == false ) {            
00138                         BaseInputVideo *input_video;
00139                 
00140                         if ( using_file )
00141                                 input_video = new FileSingleVideoSource( file_path );
00142                         else
00143                                 input_video = new HardwareSingleVideoSource( camera_num );
00144                 
00145                         DEBUG_PRINT("initializing single-stream mode...\n");
00146                 
00147                         on_demand_sms = OStreamOnDemandSMS::createNew( *_env, false, input_video, encoding_type, -1 );
00148 
00149                         // add it to ServerMediaSession
00150                         _sms->addSubsession( on_demand_sms );
00151                 
00152                         // push back on the list
00153                         _dms_list->push_back( on_demand_sms );
00154                 
00155                         DEBUG_PRINT("done, connect here for the stream %s\n", _rtspServer->rtspURL(_sms) );
00156                 }
00157                 else {  // multi mode
00158                         // BufferedImageMultiVideoSource  will use single video sources internally. 
00159                         BufferedImageMultiVideoSource *buff_vid_source;
00160                         BaseInputVideo *input_single_video;
00161                 
00162                         if ( using_file )
00163                                 input_single_video = new FileSingleVideoSource( file_path );
00164                         else
00165                                 input_single_video = new HardwareSingleVideoSource( camera_num );
00166 
00167                         DEBUG_PRINT("initializing multi-stream mode...\n");
00168                 
00169                         // a container for all the streams: the tracked faces will be queued in this class
00170                         // till when a "personalized" OStreamOnDemandSMS instance will retrieve the 
00171                         // single queue based on a stream_id
00172                         buff_vid_source = new BufferedImageMultiVideoSource( _num_of_streams, f_parsable_image_cb,
00173                                                                                                                           _parsable_image_callback_data, input_single_video );
00174                 
00175                         // do it once for every stream
00176                         for (unsigned int i=0; i < _num_of_streams; i++) {
00177                                 // add it to ServerMediaSession         
00178                                 on_demand_sms = OStreamOnDemandSMS::createNew( *_env, false, buff_vid_source, encoding_type, -1, i );
00179                                 _sms->addSubsession( on_demand_sms );
00180 
00181                                 // push back on the list
00182                                 _dms_list->push_back( on_demand_sms );
00183                         }
00184 
00185                         DEBUG_PRINT("done, connect here for streams %s\n", _rtspServer->rtspURL(_sms) );
00186                 }
00187         }
00188 
00189         // audio parsing stuff
00190         if ( using_audio ) {
00191                 on_demand_sms = OStreamOnDemandSMS::createNew( *_env, false, NULL, OSTREAM_ENCODING_MP3,  audio_num );
00192                 _sms->addSubsession( on_demand_sms );
00193                 _dms_list->push_back( on_demand_sms );
00194         }
00195 
00196         // finally add it to rtsp server
00197         _rtspServer->addServerMediaSession( _sms );
00198 }
00199 
00200 
00201 //--------------------------------------------------------------------------
00202 // return the effective url to play the rtsp stream
00203 
00204 char* OStreamUCast::getUrlToPlay() 
00205 {
00206         return _rtspServer->rtspURL(_sms);
00207 }
00208 
00209 
00210 
00211 

Generated on Tue Dec 26 10:32:38 2006 for Omnimeeting by  doxygen 1.4.7