Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

renamed newclassid to classid and newobjectlist to objectlist

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
32ObjectListDefinition(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.