Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

AvcodecTest.cpp

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------
00002     Phission : 
00003         Realtime Vision Processing System
00004     
00005     Copyright (C) 2003 Philip D.S. Thoren (pthoren@cs.uml.edu)
00006     University of Massachusetts at Lowell,
00007     Laboratory for Artificial Intelligence and Robotics
00008     
00009     This file is part of Phission.
00010 
00011  ---------------------------------------------------------------------------*/
00012 #include <avcodec.h>
00013 #include <avformat.h>
00014 #include <math.h>
00015 #include <stdio.h>
00016 
00017 #include <phission.h>
00018 
00019 /* ------------------------------------------------------------------------ */
00020 int glbl_disable_displays = 0;
00021 int glbl_preload_images = 1;
00022 
00023 /* ------------------------------------------------------------------------ */
00024 int usage()
00025 {
00026     printf("\n\nUsage:\n");
00027     printf("\t--delay <value:us>        Delay between frame updates\n");
00028     printf("\t--fps <fps>               Frames per second speed for the displaying of the video.\n");
00029     printf("\t--loop <value>            Loop the video <value> times; -1 for infinity\n");
00030     printf("\t--help                    Display usage\n");
00031     printf("\t--nodisplay               Disable the allocation, opening or any use of a display.\n");
00032     printf("\t--test <value>            Load 'value' number of frames/files/images\n");
00033     printf("\t--file <avi_data_file>    avi source (required)\n");
00034     printf("\n\n");
00035     exit(1);
00036 }
00037 
00038 /* ------------------------------------------------------------------------ */
00039 /* GetNextFrame
00040  *
00041  *   retrieves a frame from the AVI stream
00042  *
00043  */
00044 /* ------------------------------------------------------------------------ */
00045 bool GetNextFrame(AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx, int videoStream, AVFrame *pFrame)
00046 {
00047   static AVPacket packet;
00048   static int      bytesRemaining = 0;
00049   static uint8_t  *rawData;
00050   static bool     fFirstTime = true;
00051   int             bytesDecoded;
00052   int             frameFinished;
00053 
00054   // First time through, set packet data to NULL
00055   if (fFirstTime)
00056     {
00057       fFirstTime = false;
00058       packet.data = NULL;
00059     }
00060  
00061   // decode packets until we have a complete frame
00062   while(true)
00063     {
00064       // make sure we get all of the current packet
00065       while (bytesRemaining > 0)
00066         {
00067           // decode the next chunk of the packet
00068           bytesDecoded = avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, rawData, bytesRemaining);
00069           
00070           // error?
00071           if (bytesDecoded < 0)
00072             {
00073               fprintf(stderr, "Error while decoding frame\n");
00074               return false;
00075             }
00076 
00077           bytesRemaining -= bytesDecoded;
00078           rawData += bytesDecoded;
00079 
00080           // if the frame is finished then we're all done, otherwise keep on chunking...
00081           if (frameFinished)
00082             return true;
00083         }
00084 
00085       // read the next packet, but skip it if it isn't owned by the current stream
00086       do
00087         {
00088           // first free the old packet
00089           if (packet.data != NULL)
00090             {
00091               av_free_packet(&packet);
00092             }
00093 
00094           // now read a new packet
00095           if (av_read_packet(pFormatCtx, &packet) < 0)
00096             goto loop_exit;
00097 
00098         } while (packet.stream_index != videoStream);
00099 
00100       bytesRemaining = packet.size;
00101       rawData = packet.data;
00102     }
00103 
00104  loop_exit:
00105   
00106   // decode the rest of the last frame
00107   bytesDecoded = avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, rawData, bytesRemaining);
00108 
00109   // make sure to free the last packet
00110   if (packet.data != NULL)
00111     {
00112       av_free_packet(&packet);
00113     }
00114 
00115   return (frameFinished != 0);
00116 }
00117 
00118 
00119 /* ------------------------------------------------------------------------ */
00120 int main(int argc, char *argv[] )
00121 {
00122     phFUNCTION("main")
00123 
00124     phImage         image;
00125 
00126     int             displaysOpen= 1;
00127     
00128     unsigned int    i           = 0;
00129     unsigned int    image_count = 50;
00130     char*           filename = NULL;
00131     phImage         *input_images = NULL;
00132 
00133     phDisplayInterface *display = NULL;
00134     
00135     /* Utility class to ease the starting and stopping of displays, captures and
00136      * pipelines */
00137     phSystem        system;
00138    
00139     /* Remove the code below when using this code as an example.
00140      * 
00141      * This just checks whether "--test" has been specified with
00142      * a time value argument. It's for testing all the examples
00143      * without the need for human intervention. */
00144     int             test = 0;
00145 
00146     /* Stuff added to support avi decoding using avicodec */
00147     AVFormatContext *pFormatCtx     = NULL;
00148     int             videoStream;
00149     int             numBytes;
00150     AVCodecContext  *pCodecCtx      = NULL;
00151     AVCodec         *pCodec         = NULL;
00152     AVFrame         *pFrame         = NULL;
00153     AVFrame         *pFrameRGB      = NULL;
00154     AVStream        *pStream        = NULL;
00155     int             avcodec_format  = PIX_FMT_RGBA32;
00156     int32_t         phission_format = phImageBGRA32;
00157 
00158     int             delay           = 0;
00159     uint8_t         *buffer         = NULL;
00160 
00161     /* Timer routines to get desired framerate */
00162     phTimeInterval  timer;
00163     int             first_image = 1;
00164     unsigned int    sleeptime   = 0;
00165     unsigned int    fps         = 0;
00166     unsigned int    timeleft    = 0;
00167     double          frate       = 0.0;
00168     double          frate_base  = 0.0;
00169     
00170     /* Returned value from GetNextFrame and a loop count */
00171     bool            brc         = false;
00172     int             loop        = 0;
00173 
00174     int width = 0;
00175     int height = 0;
00176 
00177     phArgTable *arg_parser = new phArgTable();
00178 
00179     /* Setup and parse all the arguments */
00180     rc = arg_parser->add("--delay", &delay, phARG_INT);
00181     phCHECK_RC(rc, NULL, "arg_parser->add");
00182     rc = arg_parser->add("--fps", &fps, phARG_INT);
00183     phCHECK_RC(rc, NULL, "arg_parser->add");
00184     rc = arg_parser->add("--file", &filename, phARG_CHAR);
00185     phCHECK_RC(rc, NULL, "arg_parser->add");
00186     rc = arg_parser->add("--test", &test, phARG_INT);
00187     phCHECK_RC(rc,NULL,"arg_parser->add");
00188     rc = arg_parser->add("--nodisplay", (void *)&glbl_disable_displays, phARG_BOOL);
00189     phCHECK_RC(rc,NULL,"arg_parser->add");
00190     rc = arg_parser->add("--loop",&loop, phARG_INT);
00191     phCHECK_RC(rc,NULL,"arg_parser->add");
00192     rc = arg_parser->add("--help",(void *)&usage, phARG_FUNC);
00193     phCHECK_RC(rc,NULL,"arg_parser->add");
00194     
00195     rc = arg_parser->parse(argc,argv);
00196     phCHECK_RC(rc,NULL,"arg_parser->parse");
00197 
00198     if (filename == NULL)
00199     {
00200         phCHECK_PTR(filename,NULL,"filename not given");
00201     }
00202     
00203     /* register all formats and codecs */
00204     av_register_all();
00205 
00206     /* open the file */
00207     rc = av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL);
00208     phCHECK_RC(rc,NULL,"av_open_input_file");
00209 
00210     /* retrieve the stream information */
00211     rc = av_find_stream_info(pFormatCtx);
00212     /* no stream information in there */
00213     phCHECK_RC(rc,NULL,"av_find_stream_info");
00214     
00215     /* dump the file information to stderr */
00216     dump_format(pFormatCtx, 0, filename, false);
00217     
00218     /* we want the first video stream */
00219     videoStream = -1;
00220     for (i=0; i < (unsigned int)pFormatCtx->nb_streams; i++)
00221     {
00222 #if LIBAVFORMAT_BUILD < 4629
00223         if (pFormatCtx->streams[i]->codec.codec_type == CODEC_TYPE_VIDEO)
00224 #else
00225         if (pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO)
00226 #endif
00227         {
00228             videoStream = i;
00229             break;
00230         }
00231     }
00232     /* no video stream in there... */
00233     phCHECK_RC(videoStream,NULL,"no video stream");
00234     
00235     pStream   = pFormatCtx->streams[videoStream];
00236     
00237     /* get a pointer to the codec context for the video stream */
00238 #if LIBAVFORMAT_BUILD < 4629
00239     pCodecCtx = &(pStream->codec);
00240 #else
00241     pCodecCtx = pStream->codec;
00242 #endif
00243     /* we need to save the width and height because it sometimes changes 
00244      * in the GetNextFrame function after a call to avcodec_decode_video */
00245     width = pCodecCtx->width;
00246     height = pCodecCtx->height;
00247     
00248     /* get the super secret decoder ring for the video 
00249      * stream (include 5 box tops) */
00250     pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
00251     /* no decoder ring in the box, ask for your money back! */
00252     phCHECK_PTR(pCodec,NULL,"avcodec_find_decoder");
00253     
00254     /* tell the decoder that truncated bitstreams are doable */
00255     if (pCodec->capabilities & CODEC_CAP_TRUNCATED)
00256     {
00257         pCodecCtx->flags |= CODEC_FLAG_TRUNCATED;
00258     }
00259     
00260     /* open the codec */
00261     rc = avcodec_open(pCodecCtx, pCodec);
00262     /* something bad happened and the codec wouldn't open */
00263     phCHECK_RC(rc,NULL,"avcodec_open");
00264 #if LIBAVFORMAT_BUILD > 4627
00265     /* Figure out how much to sleep */
00266     frate       = pStream->r_frame_rate.num;
00267     frate_base  = pStream->r_frame_rate.den;
00268 #else
00269     /* Figure out how much to sleep */
00270     frate       = pCodecCtx->frame_rate;
00271     frate_base  = pCodecCtx->frame_rate_base;
00272 #endif
00273     
00274     if ((fps == 0) && (delay == 0))
00275     {
00276         /* set the frame rate for cases where the frame rate gets a 
00277          * bad value from some codecs */
00278         if (((frate         >= 1000) && (frate_base    == 1)) || 
00279             ((frate         == 1) &&    (frate_base    == 1)))
00280             /* 30 fps... it's a guess */
00281             sleeptime = 33366;
00282         else
00283             /* Calculate the sleep time from the frate and base */
00284             sleeptime = (int)((1.0/(frate / frate_base))*1000000.0);
00285     }
00286     /* if the user specified a fps value, calc the sleeptime based on it */
00287     if (fps != 0)       sleeptime = (int)((1.0 / fps) * 1000000.0);
00288     /* if the user gave a delay time, use it */
00289     if (delay != 0)     sleeptime = delay;
00290     /* if for some reason the sleeptime is <=0, set it to 30 fps */
00291     if (sleeptime <= 0) sleeptime = 33366;
00292 
00293     /* get a video frame ready */
00294     pFrame = avcodec_alloc_frame();
00295     phCHECK_PTR(pFrame,NULL,"avcodec_alloc_frame");
00296 
00297     pFrameRGB = avcodec_alloc_frame();
00298     phCHECK_PTR(pFrameRGB,NULL,"avcodec_alloc_frame");
00299 
00300     // determine how big our buffer needs to be and oh yeah, allocate the darn thing...
00301     numBytes = avpicture_get_size(avcodec_format, 
00302                                   width, 
00303                                   height);
00304     
00305     buffer = new uint8_t[numBytes];
00306     phCHECK_PTR(buffer,"new","new uint8_t[numBytes]");
00307 
00308     avpicture_fill((AVPicture *)pFrameRGB, 
00309                     buffer, 
00310                     avcodec_format, 
00311                     width, 
00312                     height);
00313 
00314     if (glbl_disable_displays == 0)
00315     {
00316         display = new X11Display(width * 2, 
00317                                  height * 2,
00318                                  "phImageReadTest");
00319         phCHECK_PTR(display,"new","new X11Display failed.");
00320         
00321         /* Link the image to the display. Loading a new image
00322          * will generate a live source signal */
00323         display->setLiveSourceInput(&image);
00324         
00325         rc = system.addDisplay(display);
00326     }
00327 
00328     /* startup */
00329     rc = system.startup();
00330     phPRINT_RC(rc,NULL,"system.startup()");
00331     
00332     // now loop continuously for as long as we have a display open and a frame available from the avi file
00333     while (displaysOpen)
00334     {
00335         brc = GetNextFrame(pFormatCtx, pCodecCtx, videoStream, pFrame);
00336 
00337         rc = img_convert((AVPicture *)pFrameRGB, 
00338                          avcodec_format,
00339                          (AVPicture *)pFrame,
00340                          pCodecCtx->pix_fmt, 
00341                          width, 
00342                          height);
00343         phCHECK_RC(rc,NULL,"img_convert");
00344 
00345         rc = image.setImage(width, 
00346                             height,
00347                             phission_format, 
00348                             0, 
00349                             pFrameRGB->data[0]);
00350         phCHECK_RC(rc,NULL,"image.setImage");
00351 
00352         /* Get a time stop stamp */
00353         timer.stop();
00354         /* Figure out the time to sleep */
00355         /* The very first elapsed() value will be 0 */
00356         timeleft = sleeptime - timer.elapsed().getMicroseconds();
00357         /* sleep for an amount to achieve the desired frame rate */
00358         if (timeleft > 0) phUSleep(timeleft);
00359         /* get a time start stamp */
00360         timer.start();
00361         
00362         if (glbl_disable_displays == 0)
00363         {
00364             displaysOpen = 0;
00365             if (display->isOpen() && (brc))
00366             {
00367                 displaysOpen = 1;
00368             }
00369         }
00370         
00371         /* Remove this if block when using this code as an example */
00372         /* Set the loop control value to end the loop when testing */
00373         if (test > 0)
00374         { 
00375             /* loop once through for this test */
00376             if (i == (image_count - 1))
00377             {
00378                 displaysOpen = 0;
00379             }
00380         }
00381     }
00382     
00383  error:
00384     rc = system.shutdown();
00385     phPRINT_RC(rc,NULL,"system.shutdown()");
00386     
00387     phDelete(display);
00388 
00389     // free up the filename string allocation
00390     phFree(filename);
00391 
00392     phDelete(arg_parser);
00393 
00394     // free up the image buffer allocation
00395     phDeleteArray(buffer);
00396 
00397     // free up the YUV frame
00398     if (pFrame != NULL)
00399     {
00400         av_free(pFrame);
00401     }
00402 
00403     // close the codec
00404     if ((pCodecCtx != NULL) && (pCodec != NULL))
00405     {
00406         avcodec_close(pCodecCtx);
00407     }
00408 
00409     // close the video file
00410     if (pFormatCtx != NULL)
00411     {
00412         av_close_input_file(pFormatCtx);
00413     }
00414     
00415     return phSUCCESS;
00416 }




Copyright (C) 2002 - 2007 Philip D.S. Thoren ( pthoren@users.sourceforge.net )
University Of Massachusetts at Lowell
Robotics Lab
SourceForge.net Logo

Generated on Sat Jun 16 02:44:04 2007 for phission by  doxygen 1.4.4