OStreamBufferedSink.cpp

Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) Massimo Cora' 2006 <maxcvs@gmail.com>
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 
00020 #include "OStreamBufferedSink.hh"
00021 
00022 #include <GroupsockHelper.hh>
00023 
00024 OStreamBufferedSink::OStreamBufferedSink( UsageEnvironment& env, 
00025                                                                                   on_packet_video_received_cb* fv, 
00026                                                                                   const void *vid_callback_data,
00027                                                                                   on_packet_audio_received_cb* fa, 
00028                                                                                   const void *aud_callback_data,
00029                                                                                   const char* subsession_codec,
00030                                                                                   int stream_id,
00031                                                                                   const char* receiving_iface,
00032                                                                                   unsigned int buffer_size )
00033                                                                 : MediaSink( env ),
00034                                                                 f_on_packet_video_received_cb( fv ),
00035                                                                 _callback_video_data_packet_receiver( vid_callback_data ),
00036                                                                 f_on_packet_audio_received_cb( fa ),
00037                                                                 _callback_audio_data_packet_receiver( aud_callback_data ),
00038                                                                 _stream_id( stream_id ),
00039                                                                 _packet_buffer_size( buffer_size )
00040 {
00041 
00042         // set up the global variable
00043         ReceivingInterfaceAddr = our_inet_addr( receiving_iface );
00044 
00045         _packet_buffer = new unsigned char[_packet_buffer_size];        
00046         memset( _packet_buffer, 0, _packet_buffer_size );
00047 
00048         _subsession_codec_str = strdup( subsession_codec );
00049                 
00050         // we will fill with this function the 
00051         if ( parse_codec_str () == false ) {
00052                 DEBUG_PRINT("WARNING: Codec not recognized.\n");
00053                 return;
00054         }
00055 
00056         switch ( _subsession_codec_id ) {
00057                 case OSTREAM_DECODING_H263P:
00058                 case OSTREAM_DECODING_MJPEG:
00059 
00060                         // FIXME: the PIX_FMT_RGB24 is an hack here. It's done to have an RGB
00061                         // iplimage decoded, instead of a BGR. This will avoid a conversion
00062                         // BGR -> RGB once we want to display the result image with wxImage.
00063 
00064                         // NOTE: *IMPORTANT* the video format width and height will be automatically
00065                         // detected by the decoder, so there's no need to specify them here.
00066                         // Libavcodec will take them for us.
00067                         _video_decoder = new OStreamVideoDecoder( 1000000, _subsession_codec_id,
00068                                                                                                                 25, PIX_FMT_RGB24 );
00069                         break;
00070 
00071                 case OSTREAM_DECODING_MP3:
00072                         // TODO: we will not use a decoder for mp3 packets, coz we'll give them entirely
00073                         // to the callback function, which will provide playback support and buffer management.
00074                         break;
00075         }       
00076 }
00077 
00078 
00079 OStreamBufferedSink* OStreamBufferedSink::createNew( UsageEnvironment& env, 
00080                         on_packet_video_received_cb* fv, const void *vid_callback_data,
00081                         on_packet_audio_received_cb* fa, const void *aud_callback_data,
00082                         const char* subsession_codec, int stream_id, const char* receiving_iface, 
00083                         unsigned int buffer_size )
00084 {
00085         return new OStreamBufferedSink( env, fv, vid_callback_data, fa, aud_callback_data, subsession_codec, 
00086                                                                     stream_id, receiving_iface, buffer_size );
00087 }
00088 
00089 
00090 OStreamBufferedSink::~OStreamBufferedSink()
00091 {
00092         if ( _packet_buffer != NULL ) {
00093                 delete[] _packet_buffer;
00094                 _packet_buffer = NULL;
00095         }
00096 
00097         if ( _subsession_codec_str )
00098                 free( _subsession_codec_str );
00099 
00100         if ( _video_decoder )
00101                 delete _video_decoder;
00102 }
00103 
00104 
00105 Boolean OStreamBufferedSink::continuePlaying() 
00106 {
00107         if (fSource == NULL) 
00108                 return False;
00109 
00110         fSource->getNextFrame( _packet_buffer, _packet_buffer_size, 
00111                                                         afterGettingFrame, this,
00112                                                         onSourceClosure, this); 
00113 
00114         return True;
00115 }
00116 
00117 
00118 
00119 //-------------------------------------------------------------------------
00120 // perform actions after getting a frame
00121 
00122 void OStreamBufferedSink::afterGettingFrame( void* clientData, unsigned frameSize,
00123                                                                                 unsigned /*numTruncatedBytes*/,
00124                                                                                 struct timeval presentationTime,
00125                                                                                 unsigned /*durationInMicroseconds*/) 
00126 {
00127         OStreamBufferedSink* sink = (OStreamBufferedSink*)clientData;
00128         sink->afterGettingFrame1( frameSize, presentationTime );
00129 } 
00130 
00131 //-------------------------------------------------------------------------
00132 //
00133 
00134 void OStreamBufferedSink::afterGettingFrame1(unsigned frameSize,
00135                                   struct timeval presentationTime) 
00136 {
00137         switch ( _subsession_codec_id ) {
00138                 case OSTREAM_DECODING_H263P:
00139                 case OSTREAM_DECODING_MJPEG:
00140                         {
00141                                 IplImage *decoded_image;
00142 
00143                                 // because we can be in a thread, the image should be freed after having displayed,
00144                                 // so trying to release it now can produce crashes.
00145                                 decoded_image = _video_decoder->decode_video_frame( _packet_buffer, frameSize );
00146 
00147                                 // call our callback function. If some errors occurs, then simply return other than
00148                                 // continue playing
00149                                 if ( f_on_packet_video_received_cb( decoded_image, _stream_id, 
00150                                         _callback_video_data_packet_receiver ) == false ) {
00151                                         return;
00152                                 }
00153                         }
00154                         break;
00155 
00156                 case OSTREAM_DECODING_MP3:
00157 
00158                         if ( f_on_packet_audio_received_cb( _packet_buffer, frameSize, _stream_id, 
00159                                                                                            _callback_audio_data_packet_receiver ) == false ) {
00160                                 return;
00161                         }
00162                         break;
00163                 
00164                 default:
00165                         break;
00166         }
00167         
00168         // Then try getting the next frame
00169         continuePlaying();
00170 }
00171 
00172 
00173 //-----------------------------------------------------------------------------
00174 // to know which codecs are supported by liveMedia, jusr give 
00175 // grep -R fCodecName * 
00176 // inside liveMedia directory. 
00177 
00178 bool OStreamBufferedSink::parse_codec_str()
00179 {
00180         
00181         if ( _subsession_codec_str == NULL )
00182                 return false;
00183         
00184         if ( strcmp( _subsession_codec_str, "H263-1998" ) == 0 ) {
00185                 _subsession_codec_id = OSTREAM_DECODING_H263P;
00186         }
00187         else if ( strcmp( _subsession_codec_str, "H263-2000" ) == 0 ) {
00188                 _subsession_codec_id = OSTREAM_DECODING_H263P;
00189         }
00190         else if ( strcmp( _subsession_codec_str, "JPEG" ) == 0 ) {
00191                 _subsession_codec_id = OSTREAM_DECODING_MJPEG;
00192         }
00193         else if ( strcmp( _subsession_codec_str, "MPA-ROBUST" ) == 0 ) {
00194                 _subsession_codec_id = OSTREAM_DECODING_MP3;
00195         }
00196         else if ( strcmp( _subsession_codec_str, "MPA" ) == 0 ) {
00197                 _subsession_codec_id = OSTREAM_DECODING_MP3;
00198         }
00199         
00200         return true;
00201 
00202 }
00203 
00204 
00205 
00206 

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