Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/avi_play/src/lib/graphics/importer/media_container.cc @ 6704

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

branches/avi_play: MediaContainer is dummy-safe

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