contrib/mul/mvl2/mvl2_video_from_avi_linux.cxx
Go to the documentation of this file.
00001 #include "mvl2_video_from_avi_linux.h"
00002 //:
00003 // \file
00004 // \brief A class for reading video files on linux platform
00005 // \author Franck Bettinger
00006 
00007 #include <avifile.h>
00008 #include <videodecoder.h>
00009 #include <infotypes.h>
00010 #include <avm_except.h>
00011 #include <version.h>
00012 #include <avm_default.h>
00013 #include <avm_fourcc.h>
00014 #include <vcl_cstring.h>
00015 #include <vcl_cstdlib.h> // malloc()
00016 
00017 mvl2_video_from_avi::mvl2_video_from_avi()
00018 {
00019   is_initialized_=false;
00020   current_frame_=0;
00021   buffer_=NULL;
00022 }
00023 
00024 mvl2_video_from_avi::~mvl2_video_from_avi()
00025 {
00026   uninitialize();
00027   if (buffer_) delete buffer_;
00028 }
00029 
00030 vcl_string mvl2_video_from_avi::is_a() const
00031 {
00032   return vcl_string("mvl2_video_from_avi");
00033 }
00034 
00035 mvl2_video_reader* mvl2_video_from_avi::clone() const
00036 {
00037   return new mvl2_video_from_avi(*this);
00038 }
00039 
00040 // possible options : Grey
00041 bool mvl2_video_from_avi::initialize( int width, int height,
00042                                       vcl_string format, vcl_string file_name)
00043 {
00044   firstcall_=true;
00045   current_frame_=0;
00046 
00047   moviefile_=CreateIAviReadFile(file_name.c_str());
00048   if (moviefile_==NULL || moviefile_->VideoStreamCount()==0) return false;
00049   moviestream_=moviefile_->GetStream(0,AviStream::Video);
00050   if (moviestream_==NULL) return false;
00051 
00052   BITMAPINFOHEADER bh;
00053   moviestream_->GetVideoFormat(&bh, sizeof(bh));
00054   width_ = bh.biWidth;
00055   height_ = bh.biHeight;
00056   frame_rate_=(double)moviestream_->GetLength()/moviestream_->GetLengthTime();
00057 
00058   moviestream_->StartStreaming();
00059   use_colour_=true;
00060   if (!format.find(vcl_string("Grey"))) use_colour_=false;
00061   is_initialized_=true;
00062 
00063   return is_initialized_;
00064 }
00065 
00066 void mvl2_video_from_avi::uninitialize()
00067 {
00068   if (!is_initialized_) return;
00069   moviestream_->StopStreaming();
00070   delete moviefile_;
00071   is_initialized_=false;
00072 }
00073 
00074 int mvl2_video_from_avi::next_frame()
00075 {
00076   if (!is_initialized_) return -1;
00077 
00078   moviestream_->ReadFrame();
00079 
00080   // hack for GetPos bug with MJPG codec
00081   current_frame_= moviestream_->GetPos()==0 ? current_frame_+1 : moviestream_->GetPos();
00082   return current_frame_;
00083 }
00084 
00085 bool mvl2_video_from_avi::get_frame(vil_image_view<vxl_byte>& image)
00086 {
00087   if (!is_initialized_) return false;
00088 
00089   CImage* cim;
00090 
00091   cim=moviestream_->GetFrame();
00092 
00093   if (cim==0) return false;
00094   CImage* im24;
00095   if (cim->Depth()==24)
00096   {
00097     im24=cim;
00098   }
00099   else
00100   {
00101     im24=new CImage(cim,24);
00102   }
00103   if (firstcall_)
00104   {
00105     if (buffer_) delete buffer_;
00106     buffer_=NULL;
00107     firstcall_=false;
00108   }
00109   if (!buffer_) buffer_=(vxl_byte*)malloc(sizeof(vxl_byte)*im24->Bytes());
00110   if (use_colour_)
00111   {
00112     image.set_size(im24->Width(),im24->Height(),3);
00113     vcl_memcpy(buffer_,im24->At(0,0),sizeof(vxl_byte)*im24->Bytes());
00114     image.set_to_memory(buffer_+2,im24->Width(),im24->Height(),3,
00115                         3,3*im24->Width(),-1);
00116   }
00117   else
00118   {
00119     image.set_size(im24->Width(),im24->Height(),1);
00120       // takes the Y component in the YUV space
00121     for (unsigned int y=0;y<image.nj();++y)
00122       for (unsigned int x=0;x<image.ni();++x)
00123         image(x,y,0) = (int)(0.299*(double)im24->At(x,y)[1]+
00124             0.587*(double)im24->At(x,y)[2]+
00125             0.114*(double)im24->At(x,y)[0]);
00126   }
00127   if (cim->Depth()!=24) delete im24;
00128   return true;
00129 }
00130 
00131 void mvl2_video_from_avi::reset_frame()
00132 {
00133   if (!is_initialized_) return;
00134 
00135   current_frame_=0;
00136   moviestream_->Seek(current_frame_);
00137 }
00138 
00139 void mvl2_video_from_avi::set_frame_rate(double /*frame_rate*/)
00140 {
00141 }
00142 
00143 double mvl2_video_from_avi::get_frame_rate() const
00144 {
00145   return frame_rate_;
00146 }
00147 
00148 int mvl2_video_from_avi::get_width() const
00149 {
00150   return width_;
00151 }
00152 
00153 int mvl2_video_from_avi::get_height() const
00154 {
00155   return height_;
00156 }
00157 
00158 void mvl2_video_from_avi::set_capture_size(int /*width*/,int /*height*/)
00159 {
00160 }
00161 
00162 int mvl2_video_from_avi::length()
00163 {
00164   if (!is_initialized_) return -1;
00165 
00166   return moviestream_->GetLength();
00167 }
00168 
00169 int mvl2_video_from_avi::seek(unsigned int frame_number)
00170 {
00171   if (!is_initialized_ || frame_number>moviestream_->GetLength())
00172     return -1;
00173   if (frame_number==0)
00174   {
00175     reset_frame();
00176     next_frame();
00177     current_frame_=0;
00178     return 0;
00179   }
00180   if (frame_number==current_frame_) return current_frame_;
00181   if (frame_number==current_frame_+1) return next_frame();
00182 
00183   moviestream_->Seek(frame_number);
00184   moviestream_->SeekToPrevKeyFrame();
00185   unsigned int key_frame=moviestream_->GetPos();
00186   vcl_cout << "[mvl2_video_from_avi::seek] key frame " << key_frame
00187            << "  -> decompress " << frame_number-key_frame << " frames\n";
00188   for (unsigned int i=key_frame; i<frame_number; ++i)
00189   {
00190     moviestream_->ReadFrame();
00191     /* CImage* cim = */ moviestream_->GetFrame();
00192   }
00193   moviestream_->ReadFrame();
00194   current_frame_ = moviestream_->GetPos();
00195   // hack for GetPos bug with MJPG codec
00196   if (current_frame_ == 0) current_frame_ = frame_number;
00197   return current_frame_;
00198 }