Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members   Related Pages  

AVISource.cpp

Go to the documentation of this file.
00001 /**************************************************************************
00014  *
00015  * Source code for Real Time Image Library (libRTImage)
00016  *
00017  * Leeds Vision Group give permission for this code to be copied, modified 
00018  * and distributed within the University of Leeds subject to the following 
00019  * conditions:-
00020  *
00021  * - The code is not to be used for commercial gain.
00022  * - The code and use thereof will be attributed to the author where
00023  *   appropriate (inluding demonstrations which rely on it's use).
00024  * - All modified, distributions of the source files will retain this header.
00025  *
00026  ****************************************************************************/
00027  
00028 #include "ccvt/conv.h"
00029 #include "AVISource.h"
00030 
00031 
00032 AVISource::AVISource(char* path)
00038 {
00039 
00040         // Register all formats and codecs
00041         av_register_all();
00042         
00043         // Open video file
00044         if(av_open_input_file(&pFormatCtx, path, NULL, 0, NULL)!=0)
00045                 throw "couldn't open avi file";
00046 
00047         // Retrieve stream information
00048         if(av_find_stream_info(pFormatCtx)<0)
00049                 throw "couldn't find avi stream information";
00050 
00051         // Dump information about file onto standard error
00052         dump_format(pFormatCtx, 0, path, false);
00053         
00054         // Find the first video stream
00055         videoStream=-1;
00056         for(i=0; i<pFormatCtx->nb_streams; i++){
00057                 if(pFormatCtx->streams[i]->codec.codec_type==CODEC_TYPE_VIDEO){
00058                         videoStream=i;
00059                         break;
00060                 }
00061         }
00062         if(videoStream==-1)
00063                 throw "didn't find an avi video stream";
00064 
00065         // Get a pointer to the codec context for the video stream
00066         pCodecCtx=&pFormatCtx->streams[videoStream]->codec;
00067 
00068         // Find the decoder for the video stream
00069         pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
00070         if(pCodec==NULL)
00071                 throw "avi codec not found";
00072                                                                                 
00073         // Inform the codec that we can handle truncated bitstreams -- i.e.,
00074         // bitstreams where frame boundaries can fall in the middle of
00075         // packets
00076         if(pCodec->capabilities & CODEC_CAP_TRUNCATED)
00077                 pCodecCtx->flags|=CODEC_FLAG_TRUNCATED;
00078                                                                                 
00079         // Open codec
00080         if(avcodec_open(pCodecCtx, pCodec)<0)
00081                 throw "could not open avi codec";
00082                                                                                 
00083         // Hack to correct wrong frame rates that seem to be generated by
00084         // some codecs
00085         if(pCodecCtx->frame_rate>1000 && pCodecCtx->frame_rate_base==1)
00086                 pCodecCtx->frame_rate_base=1000;
00087                                                                                 
00088         // Allocate video frame 
00089         pFrame=avcodec_alloc_frame();
00090 
00091         // Allocate an AVFrame structure
00092         pFrameRGB=avcodec_alloc_frame();
00093         if(pFrameRGB==NULL)
00094                 throw "cannot allocate aviframe structure";
00095                                                                                 
00096         // Determine required buffer size and allocate buffer
00097         numBytes=avpicture_get_size(PIX_FMT_RGB24, 
00098                                     pCodecCtx->width, 
00099                                     pCodecCtx->height);
00100         buffer=new uint8_t[numBytes];
00101                                                                                 
00102         // Assign appropriate parts of buffer to image planes in pFrameRGB
00103         avpicture_fill((AVPicture *)pFrameRGB, 
00104                         buffer, 
00105                         PIX_FMT_RGB24,
00106                         pCodecCtx->width, 
00107                         pCodecCtx->height);
00108 
00109 
00110 
00111 
00112         width  = pCodecCtx->width;
00113         height =  pCodecCtx->height; 
00114         frames = 0 ;
00115         framerate = pCodecCtx->frame_rate;
00116 
00117         // allocate memory for rgb rows
00118         buff = new (unsigned char*)[height];
00119         for (unsigned int i = 0; i < height - 1; i++)
00120                 buff[i] = new (unsigned char)[width*3];
00121         
00122         // last row need space for mmx scratch area
00123         buff[height - 1] = new (unsigned char)[width*3 + 4];
00124 
00125         // default palette type for this ImageSource is colour 
00126         type = Image::COLOUR;
00127 }
00128 
00129 AVISource::~AVISource()
00133 {
00134     // Free the RGB image
00135     delete [] buffer;
00136     av_free(pFrameRGB);
00137     
00138     // Free the YUV frame
00139     av_free(pFrame);
00140     
00141     // Close the codec
00142     avcodec_close(pCodecCtx);
00143     
00144     // Close the video file
00145     av_close_input_file(pFormatCtx);
00146         
00147         // free the memory for each of the rows
00148         for (unsigned int i = 0; i < height; i++)
00149                 delete [] buff[i];
00150         
00151         // free the rest of the memory
00152         delete [] buff;
00153 }
00154 
00155 
00156 ImageSource& AVISource::operator >> (ImageRGB& img) 
00162 {
00163     static AVPacket packet;
00164     static int      bytesRemaining=0;
00165     static uint8_t  *rawData;
00166     static bool     fFirstTime=true;
00167     int             bytesDecoded;
00168     int             frameFinished;
00169 
00170     // First time we're called, set packet.data to NULL to indicate it
00171     // doesn't have to be freed
00172     if(fFirstTime)
00173     {
00174         fFirstTime=false;
00175         packet.data=NULL;
00176     }
00177 
00178     // Decode packets until we have decoded a complete frame
00179     while(true)
00180     {
00181         // Work on the current packet until we have decoded all of it
00182         while(bytesRemaining > 0)
00183         {
00184             // Decode the next chunk of data
00185             bytesDecoded=avcodec_decode_video(pCodecCtx, pFrame,
00186                 &frameFinished, rawData, bytesRemaining);
00187 
00188             // Was there an error?
00189             if(bytesDecoded < 0)
00190             {
00191                  throw "Error while decoding frame";
00192                  //return false;
00193                  return *this ;
00194             }
00195 
00196             bytesRemaining-=bytesDecoded;
00197             rawData+=bytesDecoded;
00198 
00199             // Did we finish the current frame? Then we can return
00200             if(frameFinished)
00201                 //return true;
00202                 //cerr << "DEBUG: frameFinished == true" << endl;
00203                 //return *this;
00204                 goto conv_img;
00205         }
00206 
00207         // Read the next packet, skipping all packets that aren't for this
00208         // stream
00209         do
00210         {
00211             // Free old packet
00212             if(packet.data!=NULL)
00213                 av_free_packet(&packet);
00214 
00215             // Read new packet
00216             if(av_read_packet(pFormatCtx, &packet)<0)
00217                 goto loop_exit;
00218         } while(packet.stream_index!=videoStream);
00219 
00220         bytesRemaining=packet.size;
00221         rawData=packet.data;
00222     }
00223 
00224 loop_exit:
00225 
00226     // Decode the rest of the last frame
00227     bytesDecoded=avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, 
00228         rawData, bytesRemaining);
00229 
00230     // Free last packet
00231     if(packet.data!=NULL)
00232         av_free_packet(&packet);
00233 
00234     //return frameFinished!=0;
00235 
00236 conv_img:
00237 
00238 //start option B
00239         
00240 //    img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24, (AVPicture*)pFrame,
00241 //            pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
00242  
00243 
00244 //      unsigned char** rows = NULL;
00245 //      rows = new (unsigned char*)[height];
00246 //      for(unsigned int y=0; y<height; y++){
00247 //            rows[y] = pFrameRGB->data[0]+y*pFrameRGB->linesize[0];
00248 //      }
00249 //      conv_rgb24_rgb96(width, height, rows, img.data[0]);
00250 //      delete [] rows;
00251 
00252 //end option B
00253 
00254 //    AVPicture* curr_pframe = (AVPicture*) pFrameRGB;
00255 //    for (unsigned int i = 0; i < height; i++){
00256 //        for(unsigned int j = 0; j < width; j++){
00257 //                buff[i][j] = (unsigned char) curr_pframe->data[i*pFrame->linesize[0]+j];
00258 //        }
00259 //    }
00260 
00261   
00262 //start option A
00263 
00264         //This stores buffer in img.data
00265         //buffer appears to be *part* of the current frame, viz
00266         //compression stuff, think AVPicture* pFrameRGB contains image!
00267 
00268         uint8_t* s = buffer; 
00269         int*   d = (int*) img.data[0];
00270                                                                                                                                       
00271         for (unsigned int j = 0; j < height; j++) {
00272                 for (unsigned int i = 0; i < width; i++) {
00273                         *(d++) = (int) *(s++);
00274                         *(d++) = (int) *(s++);
00275                         *(d++) = (int) *(s++);
00276                 }
00277         }
00278 
00279 //end option A
00280 
00281 //    convert the frame to rgb96
00282 //    conv_rgb24_rgb96(width, height, buff, img.data[0]);
00283 
00284     return *this;
00285 }
00286 
00287 
00288 ImageSource& AVISource::operator >> (ImageGrey& img)
00295 {
00296         Image tmp((Image&)img);
00297         //SLOW HACK
00298         *this >> (ImageRGB&)tmp;
00299         tmp.update_brightness();
00300         img.copy((ImageGrey&)tmp);
00301         return *this;
00302 }
00303 
00304 ImageSource& AVISource::operator >> (Image& img) 
00313 {
00314         (type == Image::COLOUR) ? *this >> (ImageRGB&)img
00315                                 : *this >> (ImageGrey&)img;
00316                 
00317         return *this;
00318 }
00319 
00320 int  AVISource::get_no_frames()
00321 {
00322 return (int) frames;
00323 }
00324 
00325 void AVISource::get_size(unsigned int& w, unsigned int& h)
00332 {
00333         w = width; 
00334         h = height;
00335 }
00336 
00337 int AVISource::set_frame(long frame_no)
00343 {
00344 //    return mpeg3_set_frame(file, frame_no, 0) ;
00345         cerr << "NOT YET IMPLEMENTED AVISource::set_frame(long frame_no)" << endl;
00346         return false;
00347 }
00348 
00349 void AVISource::get_framerate(float& fr_rate)
00355 {
00356     fr_rate = framerate;
00357 }
00358 
00359 bool AVISource::eof() const
00364 {
00365     //return (bool)(mpeg3_end_of_video(file, 0));
00366     cerr << "NOT YET IMPLEMENTED AVISource::eof() const" << endl;
00367     return false;
00368 }
00369 

Generated at Fri Aug 13 17:29:20 2004 for libRTImage by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001