Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

branches/avi_play: frames are displayed correct and fast…took me only 3 days to find out that the only faut was wrong number in the SDL_CreateRGBSurfaceFrom call :-/

File size: 8.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  /* register all formats and codecs */
40  av_register_all();
41
42  fps = 0;
43
44  /* SDL interprets each pixel as a 32-bit number, so our masks must depend
45     on the endianness (byte order) of the machine */
46#if SDL_BYTEORDER == SDL_BIG_ENDIAN
47  rmask = 0xff000000;
48  gmask = 0x00ff0000;
49  bmask = 0x0000ff00;
50#else
51  rmask = 0x000000ff;
52  gmask = 0x0000ff00;
53  bmask = 0x00ff0000;
54#endif
55
56  if (filename != NULL)
57    this->loadMedia(filename);
58
59}
60
61/**
62 * Default destructor
63 */
64MediaContainer::~MediaContainer()
65{
66
67  // Free the RGB image
68  delete [] buffer;
69  av_free(RGB_frame);
70
71  /* Free the frame */
72  av_free(frame);
73
74  /* Close the codec */
75  avcodec_close(codec_context);
76
77  /* Close the video file */
78  av_close_input_file(format_context);
79
80}
81
82SDL_Surface* MediaContainer::getFrame(int frame_number)
83{
84
85}
86
87SDL_Surface* MediaContainer::getNextFrame()
88{
89  /* get next frame */
90  if(av_read_frame(format_context, &packet) >= 0)
91  {
92    //this->printPacketInformation();
93
94    /* Is this a packet from the video stream? */
95    if(packet.stream_index == video_stream)
96    {
97      int frame_finished;
98      // Decode video frame
99      avcodec_decode_video(codec_context, frame, &frame_finished, packet.data, packet.size);
100
101      // Did we get a video frame?
102      if(frame_finished)
103      {
104        PRINTF(1)("frame_number: %i\n", codec_context->frame_number);
105
106        // Conversion from YUV to RGB
107        // Most codecs return images in YUV 420 format
108        // (one luminance and two chrominance channels, with the chrominance
109        // channels samples at half the spatial resolution of the luminance channel)
110        img_convert((AVPicture*)RGB_frame, PIX_FMT_RGB24, (AVPicture*)frame, codec_context->pix_fmt,
111                                        codec_context->width, codec_context->height);
112
113        picture = (AVPicture*)RGB_frame;
114
115
116        data = 0;
117        data = new uint8_t[codec_context->width*codec_context->height*3*sizeof(uint8_t)];
118        for(int i = 0; i < codec_context->height; i++)
119          memcpy(&data[i*codec_context->width*3], picture->data[0]+i * picture->linesize[0],codec_context->width*sizeof(uint8_t)*3);
120
121        surface = SDL_CreateRGBSurfaceFrom(data, codec_context->width, codec_context->height,
122                                           24, codec_context->width*sizeof(uint8_t)*3, rmask, gmask, bmask, 0);
123
124        return surface;
125      }
126    }
127    // Free the packet that was allocated by av_read_frame
128    av_free_packet(&packet);
129  }
130  else
131    return NULL;
132}
133
134void MediaContainer::saveCurrentFrame()
135{
136  FILE *file;
137  char filename[32];
138  int  y;
139
140  // Open file
141  sprintf(filename, "frame%i.ppm", codec_context->frame_number);
142  file = fopen(filename, "wb");
143  if(file == NULL)
144        return;
145
146  // Write header
147  fprintf(file, "P6\n%d %d\n255\n", codec_context->width, codec_context->height);
148  // Write pixel data
149  for(y = 0; y < codec_context->height; y++)
150    fwrite(picture->data[0]+y * picture->linesize[0], 1, codec_context->width*3, file);
151  // Close file
152  fclose(file);
153
154  PRINTF(1)("created file: %s\n", filename);
155}
156
157void MediaContainer::loadMedia(const char* filename)
158{
159  /* Open video file */
160  if (av_open_input_file(&format_context, filename, NULL, 0, NULL) !=0 )
161    PRINTF(1)("Could not open %s\n", filename);
162
163  /* Retrieve stream information */
164  if (av_find_stream_info(format_context) < 0)
165    PRINTF(1)("Could not find stream information in %s\n", filename);
166
167  // Dump information about file onto standard error
168  //dump_format(pFormatCtx, 0, argv[1], false);
169
170  /* Find the first video stream and take it */
171  video_stream = -1;
172  for(int i = 0; i < format_context->nb_streams; i++)
173  {
174    // NOTE: different code for the 0.4.9-pre1 release of ffmpeg (tardis)
175    // if(format_context->streams[i]->codec.codec_type == CODEC_TYPE_VIDEO)
176    if(format_context->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO)
177    {
178      video_stream = i;
179      break;
180    }
181  }
182
183  if(video_stream == -1)
184    PRINTF(1)("Could not find a video stream in %s\n", filename);
185
186  /* Get a pointer to the codec context for the video stream */
187  // NOTE: different code for the 0.4.9-pre1 release of ffmpeg (tardis)
188  // codec_context = &format_context->streams[video_stream]->codec;
189  codec_context = format_context->streams[video_stream]->codec;
190
191  /* Find the decoder for the video stream */
192  codec = avcodec_find_decoder(codec_context->codec_id);
193  if (codec == NULL)
194    PRINTF(1)("Could not find codec\n");
195
196  /* Open codec */
197  if (avcodec_open(codec_context, codec) < 0)
198    PRINTF(1)("Could not open codec\n");
199
200  // Allocate video frame
201  frame = avcodec_alloc_frame();
202        RGB_frame = avcodec_alloc_frame();
203
204  // Determine required buffer size and allocate buffer
205  num_bytes = avpicture_get_size(PIX_FMT_RGB24, codec_context->width, codec_context->height);
206  buffer=new uint8_t[num_bytes];
207
208  // Assign appropriate parts of buffer to image planes in pFrameRGB
209  avpicture_fill((AVPicture *)RGB_frame, buffer, PIX_FMT_RGB24, codec_context->width, codec_context->height);
210
211  // Calculate fps
212  fps = av_q2d(format_context->streams[video_stream]->r_frame_rate);
213}
214
215int MediaContainer::getHeight()
216{
217  return codec_context->height;
218}
219
220int MediaContainer::getWidth()
221{
222  return codec_context->width;
223}
224
225int MediaContainer::getFrameNumber()
226{
227  return codec_context->frame_number;
228}
229
230double MediaContainer::getFPS()
231{
232  return this->fps;
233}
234
235void MediaContainer::printMediaInformation()
236{
237  PRINTF(1)("========================\n");
238  PRINTF(1)("========================\n");
239  PRINTF(1)("=    MEDIACONTAINER    =\n");
240  PRINTF(1)("========================\n");
241  PRINTF(1)("========================\n");
242  PRINTF(1)("=    AVFormatContext   =\n");
243  PRINTF(1)("========================\n");
244  PRINTF(1)("filename: %s\n", format_context->filename);
245  PRINTF(1)("nb_streams: %i\n", format_context->nb_streams);
246  PRINTF(1)("duration: %fs\n", format_context->duration/1000000.);
247  PRINTF(1)("file_size: %ikb\n", format_context->file_size/1024);
248  PRINTF(1)("bit_rate: %ikb/s\n", format_context->bit_rate/1000);
249  PRINTF(1)("nb_frames: %i\n", format_context->streams[video_stream]->nb_frames);
250  PRINTF(1)("r_frame_rate: %i\n", format_context->streams[video_stream]->r_frame_rate.num);
251  PRINTF(1)("FPS: %f\n", av_q2d(format_context->streams[video_stream]->r_frame_rate));
252  PRINTF(1)("========================\n");
253  PRINTF(1)("=    AVCodecContext    =\n");
254  PRINTF(1)("========================\n");
255  PRINTF(1)("width: %i\n", codec_context->width);
256  PRINTF(1)("height: %i\n", codec_context->height);
257  PRINTF(1)("time_base.den: %i\n", codec_context->time_base.den);
258  PRINTF(1)("time_base.num: %i\n", codec_context->time_base.num);
259  PRINTF(1)("========================\n");
260  PRINTF(1)("=       AVCodec        =\n");
261  PRINTF(1)("========================\n");
262  PRINTF(1)("codec name: %s\n", codec->name);
263  PRINTF(1)("========================\n");
264  PRINTF(1)("========================\n");
265}
266
267void MediaContainer::printPacketInformation()
268{
269  PRINTF(1)("========================\n");
270  PRINTF(1)("========================\n");
271  PRINTF(1)("=       AVPacket       =\n");
272  PRINTF(1)("========================\n");
273  PRINTF(1)("pts: %i\n", packet.pts);
274  PRINTF(1)("dts: %i\n", packet.dts);
275  PRINTF(1)("size: %i\n", packet.size);
276  PRINTF(1)("stream_index: %i\n", packet.stream_index);
277  PRINTF(1)("duration: %i\n", packet.duration);
278  PRINTF(1)("pos: %i\n", packet.pos);
279  PRINTF(1)("========================\n");
280  PRINTF(1)("========================\n");
281}
Note: See TracBrowser for help on using the repository browser.