Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/avi_play_merge/src/lib/graphics/importer/media_container.cc @ 6486

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

orxonox/branches/avi_play_merge: merged the trunk, commit for testing

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