Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/new_class_id/src/lib/graphics/importer/media_container.cc @ 9685

Last change on this file since 9685 was 9685, checked in by bensch, 18 years ago

adapted many classes to the new ClassID System, now comes the hard part… Scripting… then Network… wow this will be so bad :/

File size: 6.7 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, Stephan Lienhard
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_SPECIAL_MODULE DEBUG_MODULE_GRAPHICS
22
23
24/* include your own header */
25#include "media_container.h"
26
27#include "util/loading/resource_manager.h"
28
29/* header for debug output */
30#include "debug.h"
31
32NewObjectListDefinition(MediaContainer);
33
34/**
35 * Default constructor
36 */
37MediaContainer::MediaContainer(const std::string& filename)
38{
39  // set the class id for the base object
40  this->registerObject(this, MediaContainer::_objectList);
41
42  fps = 0;
43  mediaLoaded = false;
44  if (!filename.empty())
45    this->loadMedia(filename);
46}
47
48/**
49 * Default destructor
50 */
51MediaContainer::~MediaContainer()
52{
53  this->unloadMedia();
54}
55
56void MediaContainer::unloadMedia()
57{
58  // check whether a movie is already loaded
59  if(!mediaLoaded)
60    return;
61
62  fps = 0;
63
64  // clear texturelist
65  this->clearLists();
66
67  if (glIsTexture(texture))
68  glDeleteTextures(1, &texture);
69
70  // Free the RGB image
71  delete [] buffer;
72  av_free(RGB_frame);
73
74  // Free the frame
75  av_free(frame);
76
77  // Close the codec
78  avcodec_close(codec_context);
79
80  // Close the video file
81  av_close_input_file(format_context);
82
83  mediaLoaded = false;
84
85}
86
87bool MediaContainer::loadMedia(const std::string& filename)
88{
89  this->unloadMedia();
90
91  if(filename.empty())
92    return false;
93  // check whether file exists
94  if(!ResourceManager::isInDataDir(filename))
95  {
96    PRINTF(1)("Could not find %s\n", filename.c_str());
97    return false;
98  }
99
100  // register all formats and codecs
101  av_register_all();
102
103  // Open video file
104  if (av_open_input_file(&format_context, ResourceManager::getFullName(filename).c_str(), NULL, 0, NULL) !=0 )
105  {
106    PRINTF(1)("Could not open %s\n", ResourceManager::getFullName(filename).c_str());
107    return false;
108  }
109
110  // Retrieve stream information
111  if (av_find_stream_info(format_context) < 0)
112  {
113    PRINTF(1)("Could not find stream information in %s\n", ResourceManager::getFullName(filename).c_str());
114    return false;
115  }
116
117  // Find the first video stream and take it
118  video_stream = av_find_default_stream_index(format_context);
119
120  if(video_stream == -1)
121  {
122    PRINTF(1)("Could not find a video stream in %s\n", ResourceManager::getFullName(filename).c_str());
123    return false;
124  }
125
126  // Get a pointer to the codec context for the video stream
127  codec_context = format_context->streams[video_stream]->codec;
128
129  // Find the decoder for the video stream
130  codec = avcodec_find_decoder(codec_context->codec_id);
131  if (codec == NULL)
132  {
133    PRINTF(1)("Could not find codec\n");
134    return false;
135  }
136
137  // Open codec
138  if (avcodec_open(codec_context, codec) < 0)
139  {
140    PRINTF(1)("Could not open codec\n");
141    return false;
142  }
143
144  // Allocate video frame
145  frame = avcodec_alloc_frame();
146  RGB_frame = avcodec_alloc_frame();
147
148  // Determine required buffer size and allocate buffer
149  num_bytes = avpicture_get_size(PIX_FMT_RGB24, codec_context->width, codec_context->height);
150  buffer=new uint8_t[num_bytes];
151
152  // data buffer for the texture
153  data = new uint8_t[codec_context->width*codec_context->height*3*sizeof(uint8_t)];
154
155  // Assign appropriate parts of buffer to image planes in RGB_frame
156  avpicture_fill((AVPicture *)RGB_frame, buffer, PIX_FMT_RGB24, codec_context->width, codec_context->height);
157
158  // Calculate fps
159  fps = av_q2d(format_context->streams[video_stream]->r_frame_rate);
160  // NOTE: fix this fps problem!!
161  if(fps < 0 || fps > 1000)
162    fps = 30;
163
164  // read the frames and save them in a sequence as textures
165  this->loadFrames();
166  mediaLoaded = true;
167
168  return true;
169}
170
171double MediaContainer::getFPS()
172{
173  return this->fps;
174}
175
176void MediaContainer::loadFrames()
177{
178  // empty texture list
179  this->clearLists();
180
181  // go to the begin of the video
182  av_seek_frame(format_context, video_stream, 0, AVSEEK_FLAG_BACKWARD);
183
184  // get all the frames and save them in the sequence
185  while(this->addFrame(this->getNextFrame()) != 0);
186}
187
188
189GLuint MediaContainer::getNextFrame()
190{
191
192  // get next frame
193  if(av_read_frame(format_context, &packet) >= 0)
194  {
195    // Is this a packet from the video stream?
196    if(packet.stream_index == video_stream)
197    {
198      int frame_finished;
199      // Decode video frame
200      avcodec_decode_video(codec_context, frame, &frame_finished,
201                           packet.data, packet.size);
202
203      // Free the packet that was allocated by av_read_frame
204      av_free_packet(&packet);
205
206      // Did we get a video frame?
207      if(frame_finished)
208      {
209        // Conversion from YUV to RGB
210        // Most codecs return images in YUV 420 format
211        // (one luminance and two chrominance channels, with the chrominance
212        // channels samples at half the spatial resolution of the luminance channel)
213        img_convert((AVPicture*)RGB_frame, PIX_FMT_RGB24, (AVPicture*)frame,
214                    codec_context->pix_fmt, codec_context->width, codec_context->height);
215
216        for(int i = 0; i < codec_context->height; i++)
217          memcpy(&data[i*codec_context->width*3],
218                 ((AVPicture*)RGB_frame)->data[0]+i *
219                 ((AVPicture*)RGB_frame)->linesize[0],
220                  codec_context->width*sizeof(uint8_t)*3);
221
222        // Create an OpenGL texture
223        glGenTextures(1, &texture);
224        glBindTexture(GL_TEXTURE_2D, texture);
225        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
226        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
227        // create the texture
228        glTexImage2D(GL_TEXTURE_2D,
229                    0,
230                    GL_RGB,
231                    codec_context->width, codec_context->height,
232                    0,
233                    GL_RGB,
234                    GL_UNSIGNED_BYTE,
235                    data);
236        // build the MipMaps
237        gluBuild2DMipmaps(GL_TEXTURE_2D,
238                        GL_RGB,
239                        codec_context->width,
240                        codec_context->height,
241                        GL_RGB,
242                        GL_UNSIGNED_BYTE,
243                        data);
244        glBindTexture(GL_TEXTURE_2D, 0);
245
246        return texture;
247      }
248      else
249      {
250        av_free_packet(&packet);
251        return this->getNextFrame();
252      }
253    }
254    else
255    {
256      av_free_packet(&packet);
257      return this->getNextFrame();
258    }
259  }
260  else
261    return 0;
262}
Note: See TracBrowser for help on using the repository browser.