OStreamVideoDecoder.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 
00020 #include "OStreamVideoDecoder.hh"
00021 
00022 
00023 OStreamVideoDecoder::OStreamVideoDecoder( unsigned int io_buf_size, ostream_decoding_type decoding_type,
00024                                                                                   int fps /* = 25 */,
00025                                                                                   PixelFormat opencv_pix_fmt /*= PIX_FMT_BGR24*/) :
00026                                                         _internal_buffer_size( io_buf_size ),
00027                                                         _decoding_type( decoding_type ),
00028                                                         _fps( fps ),
00029                                                         _opencv_pix_fmt( opencv_pix_fmt )
00030 
00031 {
00032         _initialized = false;
00033                 
00034         _opencv_ready_frame = NULL;
00035         if ( io_buf_size <= 1 ) {
00036                 DEBUG_PRINT ("io_buf_size is wrong\n.");
00037                 return;
00038         }
00039         
00040         // allocate the internal buffer
00041         _internal_buffer = new unsigned char[_internal_buffer_size];
00042         
00043         if ( decoder_initialize () == true ) {
00044                 _initialized = true;
00045         }
00046 }
00047 
00048 
00049 OStreamVideoDecoder::~OStreamVideoDecoder()
00050 {
00051         if ( _internal_buffer )
00052                 delete _internal_buffer;
00053 
00054         avcodec_close( _codec_context );
00055 }
00056 
00057 
00058 bool OStreamVideoDecoder::decoder_initialize ()
00059 {
00060         // register all codecs
00061         av_register_all();
00062         
00063         switch ( _decoding_type ) {
00064                 case OSTREAM_DECODING_MJPEG:
00065                         _codec_decode = avcodec_find_decoder( CODEC_ID_MJPEG );
00066                         break;
00067                 
00068                 case OSTREAM_DECODING_H263P:
00069                         // decoder for h263+ is identified with CODEC_ID_H263
00070                         _codec_decode = avcodec_find_decoder( CODEC_ID_H263 );
00071                         break;
00072                 
00073                 default:
00074                         DEBUG_PRINT ("could not find known OSTREAM_DECODING type.\n" );
00075                         break;
00076         }
00077 
00078         if ( !_codec_decode ) {
00079         DEBUG_PRINT( "codec for decoding not found\n" );
00080         return false;
00081     }
00082         
00083         _codec_context = avcodec_alloc_context();
00084         _decoded_frame = avcodec_alloc_frame();
00085         
00086 
00087         // open it
00088         if ( avcodec_open( _codec_context, _codec_decode ) < 0 ) {
00089         DEBUG_PRINT( "could not open codec\n" );
00090             return false;
00091         }
00092         
00093         
00094         return true;
00095 }
00096 
00097 AVFrame* OStreamVideoDecoder::create_avframe( int pixel_format, int frame_width, int frame_height )
00098 {
00099     AVFrame *frame;
00100     unsigned char *picture_buf;
00101     int pic_size;
00102     
00103     frame = avcodec_alloc_frame ();
00104     if ( !frame )
00105         return NULL;
00106         
00107     pic_size = avpicture_get_size( pixel_format, frame_width, frame_height );
00108     picture_buf = (unsigned char*)calloc( pic_size, sizeof(unsigned char) );
00109     
00110         if ( !picture_buf ) {
00111         av_free( frame );
00112         return NULL;
00113     }
00114         
00115         // lets fill picture with the picture_buf just created
00116     avpicture_fill((AVPicture *)frame, picture_buf, pixel_format, frame_width, frame_height );
00117     return frame;
00118 }
00119 
00120 IplImage* OStreamVideoDecoder::decode_video_frame( unsigned char* buf, int buf_size )
00121 {
00122         int err_status;
00123         int got_decoded_frame_size;
00124         IplImage *ipl_image = NULL;
00125         
00126         /* int avcodec_decode_video(AVCodecContext *avctx, AVFrame *picture,
00127                          int *got_picture_ptr,
00128                          uint8_t *buf, int buf_size); */
00129         
00130         err_status = avcodec_decode_video( _codec_context, _decoded_frame, &got_decoded_frame_size,
00131                                            buf, buf_size );
00132         if ( err_status < 0) {
00133         DEBUG_PRINT( "Error while decoding frame.");
00134         return NULL;
00135     }
00136 
00137         // check whether the space for a decoded frame is already allocated or not
00138         // we should perform this operation just once, and just the first time.
00139         if ( _opencv_ready_frame == NULL) {
00140                 // this is where a _decoded_frame will be converted.
00141                 // the pixel format shoud be compatible with IplImages obviously
00142                 _opencv_ready_frame = create_avframe( _opencv_pix_fmt, _codec_context->width,
00143                                                                                         _codec_context->height );
00144         }
00145 
00146         if ( got_decoded_frame_size ) {
00147                 switch ( _decoding_type ) {
00148                         case OSTREAM_DECODING_MJPEG:
00149                                 img_convert( (AVPicture *)_opencv_ready_frame, _opencv_pix_fmt, 
00150                                                         (AVPicture *)_decoded_frame, PIX_FMT_YUVJ420P, 
00151                                                         _codec_context->width, _codec_context->height );
00152                                 break;
00153                 
00154                         case OSTREAM_DECODING_H263P:
00155                                 img_convert( (AVPicture *)_opencv_ready_frame, _opencv_pix_fmt, 
00156                                                         (AVPicture *)_decoded_frame, PIX_FMT_YUV420P, 
00157                                                         _codec_context->width, _codec_context->height );
00158                                                         
00159                                 break;
00160                 
00161                         default:
00162                                 DEBUG_PRINT ("img_convert doesn't know what to do.\n" );
00163                                 break;
00164                 }
00165 
00166                 // the cvSetData function doesn't do what we want here. It just set the _opencv_ready_frame pointer
00167                 // to the just created ipl_image header. But we want a clean and new allocated ipl_image, so 
00168                 // use the old good memcpy to store the data, and bye bye cv*Data friends.
00169                 ipl_image = cvCreateImage( cvSize( _codec_context->width, _codec_context->height ), IPL_DEPTH_8U, 3 );
00170                 memcpy( ipl_image->imageData, _opencv_ready_frame->data[0], ipl_image->imageSize );
00171                 ipl_image->widthStep = _opencv_ready_frame->linesize[0];
00172         }
00173         
00174         return ipl_image;
00175 }
00176 
00177 
00178 
00179 

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