Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Dec 30, 2005, 8:34:22 PM (18 years ago)
Author:
hdavid
Message:

branches\avi_play: MoviePlayer works again

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/avi_play/src/lib/graphics/importer/movie_player.cc

    r6339 r6353  
    1818/* this is for debug output. It just says, that all calls to PRINT() belong to the DEBUG_MODULE_MEDIA module
    1919   For more information refere to https://www.orxonox.net/cgi-bin/trac.cgi/wiki/DebugOutput
    20 *//*
     20*/
    2121#define DEBUG_MODULE_MEDIA
    2222
     
    2929
    3030
    31 //
    32 // Default constructor
    33 //
    3431MoviePlayer::MoviePlayer(const char* filename)
    3532{
    36   media_container = new MediaContainer(filename);
    37 
    3833  this->init();
     34
     35  if (filename != NULL)
     36    this->loadMovie(filename);
    3937}
    4038
    4139MoviePlayer::MoviePlayer()
    4240{
    43   media_container = new MediaContainer();
    44 
    4541  this->init();
    4642}
     
    4844MoviePlayer::~MoviePlayer()
    4945{
    50   delete media_container;
     46  delete material;
     47  delete model;
     48
     49  if (glIsTexture(texture))
     50    glDeleteTextures(1, &texture);
     51  SDL_FreeSurface(surface);
     52
     53  // Free the RGB image
     54  delete [] buffer;
     55  av_free(RGB_frame);
     56
     57  // Free the frame
     58  av_free(frame);
     59
     60  // Close the codec
     61  avcodec_close(codec_context);
     62
     63  // Close the video file
     64  av_close_input_file(format_context);
    5165}
    5266
    5367void MoviePlayer::init()
    5468{
     69  // set the class id for the base object
     70  this->setClassID(CL_MOVIE_PLAYER, "MoviePlayer");
     71
    5572  status = STOP;
    5673  timer = 0;
     74  frame_number = 0;
    5775  speed = 1;
    5876
    5977  material = new Material;
    60 
    6178  material->setDiffuseMap("maps/radialTransparency.png");
    6279
     
    7188void MoviePlayer::loadMovie(const char* filename)
    7289{
    73   media_container->loadMedia(filename);
    74 }
    75 
    76 void MoviePlayer::printInformation()
    77 {
    78   media_container->printMediaInformation();
     90  // register all formats and codecs
     91  av_register_all();
     92
     93  // Open video file
     94  if (av_open_input_file(&format_context, filename, NULL, 0, NULL) !=0 )
     95    PRINTF(1)("Could not open %s\n", filename);
     96
     97  // Retrieve stream information
     98  if (av_find_stream_info(format_context) < 0)
     99    PRINTF(1)("Could not find stream information in %s\n", filename);
     100
     101  // Find the first video stream and take it
     102  video_stream = -1;
     103  for(int i = 0; i < format_context->nb_streams; i++)
     104  {
     105    // NOTE: different code for the 0.4.9-pre1 release of ffmpeg (tardis)
     106    // if(format_context->streams[i]->codec.codec_type == CODEC_TYPE_VIDEO)
     107    if(format_context->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO)
     108    {
     109      video_stream = i;
     110      break;
     111    }
     112  }
     113
     114  if(video_stream == -1)
     115    PRINTF(1)("Could not find a video stream in %s\n", filename);
     116
     117  // Get a pointer to the codec context for the video stream
     118  // NOTE: different code for the 0.4.9-pre1 release of ffmpeg (tardis)
     119  // codec_context = &format_context->streams[video_stream]->codec;
     120  codec_context = format_context->streams[video_stream]->codec;
     121
     122  // Find the decoder for the video stream
     123  codec = avcodec_find_decoder(codec_context->codec_id);
     124  if (codec == NULL)
     125    PRINTF(1)("Could not find codec\n");
     126
     127  // Open codec
     128  if (avcodec_open(codec_context, codec) < 0)
     129    PRINTF(1)("Could not open codec\n");
     130
     131  // Allocate video frame
     132  frame = avcodec_alloc_frame();
     133  RGB_frame = avcodec_alloc_frame();
     134
     135  // Determine required buffer size and allocate buffer
     136  num_bytes = avpicture_get_size(PIX_FMT_RGB24, codec_context->width, codec_context->height);
     137  buffer=new uint8_t[num_bytes];
     138
     139  // Assign appropriate parts of buffer to image planes in RGB_frame
     140  avpicture_fill((AVPicture *)RGB_frame, buffer, PIX_FMT_RGB24, codec_context->width, codec_context->height);
     141
     142  // Calculate fps
     143  fps = av_q2d(format_context->streams[video_stream]->r_frame_rate);
     144
     145  // duration
     146  duration = format_context->duration / 1000000LL;
     147
     148  // create texture
     149  glGenTextures(1, &texture);
     150  glBindTexture(GL_TEXTURE_2D, texture);
     151  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     152  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     153  glTexImage2D(GL_TEXTURE_2D,
     154              0,
     155              GL_RGB,
     156              0, 0,
     157              0,
     158              GL_RGB,
     159              GL_UNSIGNED_BYTE,
     160              NULL);
     161  glBindTexture(GL_TEXTURE_2D, 0);
     162}
     163
     164void MoviePlayer::getNextFrame()
     165{
     166  // get next frame
     167  if(av_read_frame(format_context, &packet) >= 0)
     168  {
     169    // Is this a packet from the video stream?
     170    if(packet.stream_index == video_stream)
     171    {
     172      int frame_finished;
     173      // Decode video frame
     174      avcodec_decode_video(codec_context, frame, &frame_finished,
     175                           packet.data, packet.size);
     176
     177      // Free the packet that was allocated by av_read_frame
     178      av_free_packet(&packet);
     179     
     180      // Did we get a video frame?
     181      if(frame_finished)
     182      {
     183        frame_number++;
     184        //PRINTF(0)("frame_number: %i\n", frame_number);
     185        // Conversion from YUV to RGB
     186        // Most codecs return images in YUV 420 format
     187        // (one luminance and two chrominance channels, with the chrominance
     188        // channels samples at half the spatial resolution of the luminance channel)
     189        img_convert((AVPicture*)RGB_frame, PIX_FMT_RGB24, (AVPicture*)frame,
     190                    codec_context->pix_fmt, codec_context->width, codec_context->height);
     191
     192        data = 0;
     193        data = new uint8_t[codec_context->width*codec_context->height*3*sizeof(uint8_t)];
     194        for(int i = 0; i < codec_context->height; i++)
     195          memcpy(&data[i*codec_context->width*3], ((AVPicture*)RGB_frame)->data[0]+i *
     196                 ((AVPicture*)RGB_frame)->linesize[0],
     197                 codec_context->width*sizeof(uint8_t)*3);
     198
     199//avcodec_flush_buffers(codec_context);
     200
     201        surface = SDL_CreateRGBSurfaceFrom(data, codec_context->width,
     202                                           codec_context->height,24,
     203                                           codec_context->width*sizeof(uint8_t)*3,
     204#if SDL_BYTEORDER == SDL_LIL_ENDIAN // OpenGL RGBA masks
     205                                           0x000000FF,
     206                                           0x0000FF00,
     207                                           0x00FF0000,
     208                                           0
     209#else
     210                                           0xFF000000,
     211                                           0x00FF0000,
     212                                           0x0000FF00,
     213                                           0
     214#endif
     215                                            );
     216
     217        glBindTexture(GL_TEXTURE_2D, texture);
     218        // update the texture
     219        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
     220                          surface->w, surface->h,
     221                          GL_RGB, GL_UNSIGNED_BYTE,
     222                          surface->pixels);
     223        // build the MipMaps
     224        gluBuild2DMipmaps(GL_TEXTURE_2D,
     225                        GL_RGB,
     226                        surface->w,
     227                        surface->h,
     228                        GL_RGB,
     229                        GL_UNSIGNED_BYTE,
     230                        surface->pixels);
     231        glBindTexture(GL_TEXTURE_2D, 0);
     232      }
     233      else
     234      {
     235        av_free_packet(&packet);
     236        this->getNextFrame();
     237      }
     238    }
     239    else
     240    {
     241      av_free_packet(&packet);
     242      this->getNextFrame();
     243    }
     244  }
     245  else
     246    this->stop();
     247}
     248
     249void MoviePlayer::skipFrame(int frames)
     250{
     251 
     252  while(frames != 0)
     253  {
     254    if(av_read_frame(format_context, &packet) < 0)
     255      break;
     256    if(packet.stream_index == video_stream)
     257    {
     258      int frame_finished;
     259      // We have to decode the frame to not get ugly fragments
     260      avcodec_decode_video(codec_context, frame, &frame_finished,
     261                            packet.data, packet.size);
     262       
     263      // Did we get a video frame?
     264      if(frame_finished)
     265      {
     266        frames--;
     267        frame_number++;
     268      }
     269    }
     270    av_free_packet(&packet);
     271  }
     272 
     273  this->getNextFrame();
     274
     275}
     276
     277void MoviePlayer::gotoFrame(int frames)
     278{
     279  // seek doesnt work for the first two frames
     280  // you will get ugly fragments
     281  if(frames < 2)
     282  {
     283    // go to the begin of the video
     284    av_seek_frame(format_context, video_stream, 0, AVSEEK_FLAG_BACKWARD);
     285    frame_number = 0;
     286  }
     287  else
     288  {
     289    // seeks to the nearest keyframe
     290    // NOTE: there is only about every 5s a keyframe!
     291    av_seek_frame(format_context, video_stream, frames, AVSEEK_FLAG_BACKWARD);
     292   
     293    // go from the keyframe to the exact position
     294    codec_context->hurry_up = 1;
     295    do {
     296      av_read_frame(format_context, &packet);
     297      if(packet.pts >= frames-1)
     298        break;
     299      int frame_finished;
     300      avcodec_decode_video(codec_context, frame, &frame_finished, packet.data, packet.size);
     301      av_free_packet(&packet);
     302    } while(1);
     303    codec_context->hurry_up = 0;
     304 
     305    frame_number = frames;
     306  }
    79307}
    80308
     
    83311  status = PLAY;
    84312  timer = 0;
    85   fps = media_container->getFPS();
    86 
    87   media_container->gotoFrame(start_time * fps);
    88 
    89    PRINTF(0)("start (start_time: %0.2f)\n", start_time * fps);
     313
     314  this->gotoFrame(start_time * fps);
     315
     316   PRINTF(0)("start\n");
    90317}
    91318
     
    111338{
    112339  status = STOP;
    113   texture = NULL;
    114340
    115341  PRINTF(0)("stop\n");
     
    120346  if(status == PLAY)
    121347  {
    122     current_frame = media_container->getFrameNumber();
    123348    timer += dt;
    124349    actual_frame = timer * fps * speed;
    125350
    126     if(actual_frame != current_frame)
     351    if(actual_frame != frame_number)
    127352    {
    128       if(actual_frame - current_frame == 1)
    129         texture = media_container->getNextFrame();
     353      if(actual_frame - frame_number == 1)
     354        this->getNextFrame();
    130355      else
    131         texture = media_container->skipFrame(actual_frame - current_frame - 1);
     356        this->skipFrame(actual_frame - frame_number - 1);
    132357    }   
    133     //PRINTF(0)("frame_number: %i\n", media_container->getFrameNumber());
    134 
    135     if(texture == NULL && current_frame != 0)
    136       this->stop();
     358    //PRINTF(0)("frame_number: %i\n", frame_number);
    137359  }
    138360}
     
    162384  return this->status;
    163385}
    164 */
     386
     387void MoviePlayer::printInformation()
     388{
     389  PRINTF(0)("========================\n");
     390  PRINTF(0)("========================\n");
     391  PRINTF(0)("=    MEDIACONTAINER    =\n");
     392  PRINTF(0)("========================\n");
     393  PRINTF(0)("========================\n");
     394  PRINTF(0)("=    AVFormatContext   =\n");
     395  PRINTF(0)("========================\n");
     396  PRINTF(0)("filename: %s\n", format_context->filename);
     397  PRINTF(0)("nb_streams: %i\n", format_context->nb_streams);
     398  PRINTF(0)("duration: (%02d:%02d:%02d)\n", duration/3600, (duration%3600)/60, duration%60);
     399  PRINTF(0)("file_size: %ikb\n", format_context->file_size/1024);
     400  PRINTF(0)("bit_rate: %ikb/s\n", format_context->bit_rate/1000);
     401  PRINTF(0)("nb_frames: %i\n", format_context->streams[video_stream]->nb_frames);
     402  PRINTF(0)("r_frame_rate: %i\n", format_context->streams[video_stream]->r_frame_rate.num);
     403  PRINTF(0)("fps: %0.2f\n", av_q2d(format_context->streams[video_stream]->r_frame_rate));
     404  PRINTF(0)("========================\n");
     405  PRINTF(0)("=    AVCodecContext    =\n");
     406  PRINTF(0)("========================\n");
     407  PRINTF(0)("width: %i\n", codec_context->width);
     408  PRINTF(0)("height: %i\n", codec_context->height);
     409  PRINTF(0)("time_base.den: %i\n", codec_context->time_base.den);
     410  PRINTF(0)("time_base.num: %i\n", codec_context->time_base.num);
     411  PRINTF(0)("========================\n");
     412  PRINTF(0)("=       AVCodec        =\n");
     413  PRINTF(0)("========================\n");
     414  PRINTF(0)("codec name: %s\n", codec->name);
     415  PRINTF(0)("========================\n");
     416  PRINTF(0)("========================\n");
     417}
Note: See TracChangeset for help on using the changeset viewer.