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 |