Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

branches\avi_play: removed memory leak

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