Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/graphics/importer/media_container.cc @ 7903

Last change on this file since 7903 was 7221, checked in by bensch, 19 years ago

orxonox/trunk: merged the std-branche back, it runs on windows and Linux

svn merge https://svn.orxonox.net/orxonox/branches/std . -r7202:HEAD

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