Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/avi_play/src/lib/graphics/importer/movie_player.cc @ 6373

Last change on this file since 6373 was 6373, checked in by hdavid, 18 years ago

branches\avi_play: different texture creation

File size: 12.0 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11### File Specific:
12   main-programmer: David Hasenfratz
13   co-programmer:
14*/
15
16
17
18/* this is for debug output. It just says, that all calls to PRINT() belong to the DEBUG_MODULE_MEDIA module
19   For more information refere to https://www.orxonox.net/cgi-bin/trac.cgi/wiki/DebugOutput
20*/
21#define DEBUG_MODULE_MEDIA
22
23
24// include your own header
25#include "movie_player.h"
26
27// header for debug output
28#include "debug.h"
29
30
31MoviePlayer::MoviePlayer(const char* filename)
32{
33  this->init();
34
35  if (filename != NULL)
36    this->loadMovie(filename);
37}
38
39MoviePlayer::MoviePlayer()
40{
41  this->init();
42}
43
44MoviePlayer::~MoviePlayer()
45{
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
60avcodec_default_free_buffers(codec_context);
61
62  // Close the codec
63  avcodec_close(codec_context);
64
65  // Close the video file
66  av_close_input_file(format_context);
67}
68
69void MoviePlayer::init()
70{
71  // set the class id for the base object
72  this->setClassID(CL_MOVIE_PLAYER, "MoviePlayer");
73
74  status = STOP;
75  timer = 0;
76  frame_number = 0;
77  speed = 1;
78
79  material = new Material;
80  material->setDiffuseMap("maps/radialTransparency.png");
81
82  model = new PrimitiveModel(PRIM_PLANE, 10.0);
83
84  LightManager* lightMan = LightManager::getInstance();
85  lightMan->setAmbientColor(.1,.1,.1);
86  (new Light())->setAbsCoor(5.0, 10.0, 40.0);
87  (new Light())->setAbsCoor(-10, -20, -100);
88}
89
90void MoviePlayer::loadMovie(const char* filename)
91{
92  // register all formats and codecs
93  av_register_all();
94
95  // Open video file
96  if (av_open_input_file(&format_context, filename, NULL, 0, NULL) !=0 )
97    PRINTF(1)("Could not open %s\n", filename);
98
99  // Retrieve stream information
100  if (av_find_stream_info(format_context) < 0)
101    PRINTF(1)("Could not find stream information in %s\n", filename);
102
103  // Find the first video stream and take it
104  video_stream = -1;
105  for(int i = 0; i < format_context->nb_streams; i++)
106  {
107    // NOTE: different code for the 0.4.9-pre1 release of ffmpeg (tardis)
108    // if(format_context->streams[i]->codec.codec_type == CODEC_TYPE_VIDEO)
109    if(format_context->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO)
110    {
111      video_stream = i;
112      break;
113    }
114  }
115
116  if(video_stream == -1)
117    PRINTF(1)("Could not find a video stream in %s\n", filename);
118
119  // Get a pointer to the codec context for the video stream
120  // NOTE: different code for the 0.4.9-pre1 release of ffmpeg (tardis)
121  // codec_context = &format_context->streams[video_stream]->codec;
122  codec_context = format_context->streams[video_stream]->codec;
123
124  // Find the decoder for the video stream
125  codec = avcodec_find_decoder(codec_context->codec_id);
126  if (codec == NULL)
127    PRINTF(1)("Could not find codec\n");
128
129  // Open codec
130  if (avcodec_open(codec_context, codec) < 0)
131    PRINTF(1)("Could not open codec\n");
132
133  // Allocate video frame
134  frame = avcodec_alloc_frame();
135  RGB_frame = avcodec_alloc_frame();
136
137  // Determine required buffer size and allocate buffer
138  num_bytes = avpicture_get_size(PIX_FMT_RGB24, codec_context->width, codec_context->height);
139  buffer=new uint8_t[num_bytes];
140
141  // Assign appropriate parts of buffer to image planes in RGB_frame
142  avpicture_fill((AVPicture *)RGB_frame, buffer, PIX_FMT_RGB24, codec_context->width, codec_context->height);
143
144  // Calculate fps
145  fps = av_q2d(format_context->streams[video_stream]->r_frame_rate);
146
147  // duration
148  duration = format_context->duration / 1000000LL;
149
150  // create texture
151  glGenTextures(1, &texture);
152  glBindTexture(GL_TEXTURE_2D, texture);
153  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
154  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
155  glTexImage2D(GL_TEXTURE_2D,
156              0,
157              GL_RGB,
158              0, 0,
159              0,
160              GL_RGB,
161              GL_UNSIGNED_BYTE,
162              NULL);
163  glBindTexture(GL_TEXTURE_2D, 0);
164}
165
166void MoviePlayer::getNextFrame()
167{
168  // get next frame
169  if(av_read_frame(format_context, &packet) >= 0)
170  {
171    // Is this a packet from the video stream?
172    if(packet.stream_index == video_stream)
173    {
174      int frame_finished;
175      // Decode video frame
176      avcodec_decode_video(codec_context, frame, &frame_finished,
177                           packet.data, packet.size);
178
179      // Free the packet that was allocated by av_read_frame
180      av_free_packet(&packet);
181     
182      // Did we get a video frame?
183      if(frame_finished)
184      {
185        frame_number++;
186        //PRINTF(0)("frame_number: %i\n", frame_number);
187        // Conversion from YUV to RGB
188        // Most codecs return images in YUV 420 format
189        // (one luminance and two chrominance channels, with the chrominance
190        // channels samples at half the spatial resolution of the luminance channel)
191        img_convert((AVPicture*)RGB_frame, PIX_FMT_RGB24, (AVPicture*)frame,
192                    codec_context->pix_fmt, codec_context->width, codec_context->height);
193
194        data = 0;
195        data = new uint8_t[codec_context->width*codec_context->height*3*sizeof(uint8_t)];
196        for(int i = 0; i < codec_context->height; i++)
197          memcpy(&data[i*codec_context->width*3], ((AVPicture*)RGB_frame)->data[0]+i *
198                 ((AVPicture*)RGB_frame)->linesize[0],
199                 codec_context->width*sizeof(uint8_t)*3);
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
234        glBindTexture(GL_TEXTURE_2D, texture);
235        // update the texture
236        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
237                          codec_context->width, codec_context->height,
238                          GL_RGB, GL_UNSIGNED_BYTE,
239                          data);
240        // build the MipMaps
241        gluBuild2DMipmaps(GL_TEXTURE_2D,
242                        GL_RGB,
243                        codec_context->width,
244                        codec_context->height,
245                        GL_RGB,
246                        GL_UNSIGNED_BYTE,
247                        data);
248        glBindTexture(GL_TEXTURE_2D, 0);
249
250        //avcodec_flush_buffers(codec_context);
251
252      }
253      else
254      {
255        av_free_packet(&packet);
256        this->getNextFrame();
257      }
258    }
259    else
260    {
261      av_free_packet(&packet);
262      this->getNextFrame();
263    }
264  }
265  else
266    this->stop();
267}
268
269void MoviePlayer::skipFrame(int frames)
270{
271 
272  while(frames != 0)
273  {
274    if(av_read_frame(format_context, &packet) < 0)
275      break;
276    if(packet.stream_index == video_stream)
277    {
278      int frame_finished;
279      // We have to decode the frame to not get ugly fragments
280      avcodec_decode_video(codec_context, frame, &frame_finished,
281                            packet.data, packet.size);
282       
283      // Did we get a video frame?
284      if(frame_finished)
285      {
286        frames--;
287        frame_number++;
288      }
289    }
290    av_free_packet(&packet);
291  }
292 
293  this->getNextFrame();
294
295}
296
297void MoviePlayer::gotoFrame(int frames)
298{
299  // seek doesnt work for the first two frames
300  // you will get ugly fragments
301  if(frames < 2)
302  {
303    // go to the begin of the video
304    av_seek_frame(format_context, video_stream, 0, AVSEEK_FLAG_BACKWARD);
305    frame_number = 0;
306  }
307  else
308  {
309    // seeks to the nearest keyframe
310    // NOTE: there is only about every 5s a keyframe!
311    av_seek_frame(format_context, video_stream, frames, AVSEEK_FLAG_BACKWARD);
312   
313    // go from the keyframe to the exact position
314    codec_context->hurry_up = 1;
315    do {
316      av_read_frame(format_context, &packet);
317      if(packet.pts >= frames-1)
318        break;
319      int frame_finished;
320      avcodec_decode_video(codec_context, frame, &frame_finished, packet.data, packet.size);
321      av_free_packet(&packet);
322    } while(1);
323    codec_context->hurry_up = 0;
324 
325    frame_number = frames;
326  }
327}
328
329void MoviePlayer::start(unsigned int start_time)
330{
331  status = PLAY;
332  timer = 0;
333
334  this->gotoFrame(start_time * fps);
335
336   PRINTF(0)("start\n");
337}
338
339void MoviePlayer::resume()
340{
341  if(status == STOP)
342    this->start(0);
343  else
344    status = PLAY;
345
346   PRINTF(0)("resume\n");
347}
348
349void MoviePlayer::pause()
350{
351  if(status != STOP)
352    status = PAUSE;
353
354  PRINTF(0)("pause\n");
355}
356
357void MoviePlayer::stop()
358{
359  status = STOP;
360
361  PRINTF(0)("stop\n");
362}
363
364void MoviePlayer::tick(float dt)
365{
366  if(status == PLAY)
367  {
368    timer += dt;
369    actual_frame = timer * fps * speed;
370
371    if(actual_frame != frame_number)
372    {
373      if(actual_frame - frame_number == 1)
374        this->getNextFrame();
375      else
376        this->skipFrame(actual_frame - frame_number - 1);
377    }   
378    //PRINTF(0)("frame_number: %i\n", frame_number);
379  }
380}
381
382const void MoviePlayer::draw()
383{
384  material->select();
385  glBindTexture(GL_TEXTURE_2D, texture);
386  model->draw();
387
388  LightManager::getInstance()->draw();
389}
390
391void MoviePlayer::setSpeed(float speed)
392{
393  if(speed > 0)
394    this->speed = speed;
395}
396
397float MoviePlayer::getSpeed()
398{
399  return this->speed;
400}
401
402const MP_STATUS MoviePlayer::getStatus()
403{
404  return this->status;
405}
406
407void MoviePlayer::printInformation()
408{
409  PRINTF(0)("========================\n");
410  PRINTF(0)("========================\n");
411  PRINTF(0)("=    MEDIACONTAINER    =\n");
412  PRINTF(0)("========================\n");
413  PRINTF(0)("========================\n");
414  PRINTF(0)("=    AVFormatContext   =\n");
415  PRINTF(0)("========================\n");
416  PRINTF(0)("filename: %s\n", format_context->filename);
417  PRINTF(0)("nb_streams: %i\n", format_context->nb_streams);
418  PRINTF(0)("duration: (%02d:%02d:%02d)\n", duration/3600, (duration%3600)/60, duration%60);
419  PRINTF(0)("file_size: %ikb\n", format_context->file_size/1024);
420  PRINTF(0)("bit_rate: %ikb/s\n", format_context->bit_rate/1000);
421  PRINTF(0)("nb_frames: %i\n", format_context->streams[video_stream]->nb_frames);
422  PRINTF(0)("r_frame_rate: %i\n", format_context->streams[video_stream]->r_frame_rate.num);
423  PRINTF(0)("fps: %0.2f\n", av_q2d(format_context->streams[video_stream]->r_frame_rate));
424  PRINTF(0)("========================\n");
425  PRINTF(0)("=    AVCodecContext    =\n");
426  PRINTF(0)("========================\n");
427  PRINTF(0)("width: %i\n", codec_context->width);
428  PRINTF(0)("height: %i\n", codec_context->height);
429  PRINTF(0)("time_base.den: %i\n", codec_context->time_base.den);
430  PRINTF(0)("time_base.num: %i\n", codec_context->time_base.num);
431  PRINTF(0)("========================\n");
432  PRINTF(0)("=       AVCodec        =\n");
433  PRINTF(0)("========================\n");
434  PRINTF(0)("codec name: %s\n", codec->name);
435  PRINTF(0)("========================\n");
436  PRINTF(0)("========================\n");
437}
Note: See TracBrowser for help on using the repository browser.