Panda3D

movieVideoCursor.cxx

00001 // Filename: movieVideo.cxx
00002 // Created by: jyelon (02Jul07)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "movieVideoCursor.h"
00016 #include "config_movies.h"
00017 #include "pStatCollector.h"
00018 #include "pStatTimer.h"
00019 
00020 TypeHandle MovieVideoCursor::_type_handle;
00021 
00022 ////////////////////////////////////////////////////////////////////
00023 //     Function: MovieVideoCursor::Constructor
00024 //       Access: Public
00025 //  Description: This constructor returns a null video stream --- a
00026 //               stream of plain blue and white frames that last one
00027 //               second each. To get more interesting video, you need
00028 //               to construct a subclass of this class.
00029 ////////////////////////////////////////////////////////////////////
00030 MovieVideoCursor::
00031 MovieVideoCursor(MovieVideo *src) :
00032   _conversion_buffer(0),
00033   _source(src),
00034   _size_x(1),
00035   _size_y(1),
00036   _num_components(3),
00037   _length(1.0E10),
00038   _can_seek(true),
00039   _can_seek_fast(true),
00040   _aborted(false),
00041   _last_start(-1.0),
00042   _next_start(0.0),
00043   _streaming(false),
00044   _ready(false)
00045 {
00046 }
00047 
00048 ////////////////////////////////////////////////////////////////////
00049 //     Function: MovieVideoCursor::Destructor
00050 //       Access: Public, Virtual
00051 //  Description: 
00052 ////////////////////////////////////////////////////////////////////
00053 MovieVideoCursor::
00054 ~MovieVideoCursor() {
00055   if (_conversion_buffer != 0) {
00056     delete[] _conversion_buffer;
00057   }
00058 }
00059 
00060 ////////////////////////////////////////////////////////////////////
00061 //     Function: MovieVideoCursor::allocate_conversion_buffer
00062 //       Access: Private
00063 //  Description: The generic implementations of fetch_into_texture
00064 //               and fetch_into_alpha require the use of a conversion
00065 //               buffer.  This allocates the buffer.
00066 ////////////////////////////////////////////////////////////////////
00067 void MovieVideoCursor::
00068 allocate_conversion_buffer() {
00069   if (_conversion_buffer == 0) {
00070     _conversion_buffer = new unsigned char[size_x() * size_y() * 4];
00071   }
00072 }
00073   
00074 ////////////////////////////////////////////////////////////////////
00075 //     Function: MovieVideoCursor::setup_texture
00076 //       Access: Published
00077 //  Description: Set up the specified Texture object to contain
00078 //               content from this movie.  This should be called
00079 //               once, not every frame.
00080 ////////////////////////////////////////////////////////////////////
00081 void MovieVideoCursor::
00082 setup_texture(Texture *tex) const {
00083   int fullx = size_x();
00084   int fully = size_y();
00085   if (Texture::get_textures_power_2()) {
00086     fullx = Texture::up_to_power_2(fullx);
00087     fully = Texture::up_to_power_2(fully);
00088   }
00089   Texture::Format fmt = (get_num_components() == 4) ? Texture::F_rgba : Texture::F_rgb;
00090   tex->setup_texture(Texture::TT_2d_texture, fullx, fully, 1, Texture::T_unsigned_byte, fmt);
00091   tex->set_pad_size(fullx - size_x(), fully - size_y());
00092 }
00093 
00094 ////////////////////////////////////////////////////////////////////
00095 //     Function: MovieVideoCursor::fetch_into_bitbucket
00096 //       Access: Published, Virtual
00097 //  Description: Discards the next video frame.  Still sets
00098 //               last_start and next_start.
00099 //
00100 //               See fetch_into_buffer for more details.
00101 ////////////////////////////////////////////////////////////////////
00102 void MovieVideoCursor::
00103 fetch_into_bitbucket(double time) {
00104 
00105   // This generic implementation is layered on fetch_into_buffer.
00106   // It will work for any derived class, so it is never necessary to
00107   // redefine this.  It is probably possible to make a faster
00108   // implementation, but since this function is rarely used, it
00109   // probably isn't worth the trouble.
00110 
00111   allocate_conversion_buffer();
00112   fetch_into_buffer(time, _conversion_buffer, false);
00113 }
00114 
00115 ////////////////////////////////////////////////////////////////////
00116 //     Function: MovieVideoCursor::fetch_into_texture
00117 //       Access: Published, Virtual
00118 //  Description: Reads the specified video frame into 
00119 //               the specified texture.
00120 //
00121 //               See fetch_into_buffer for more details.
00122 ////////////////////////////////////////////////////////////////////
00123 static PStatCollector fetch_into_texture_collector("*:Decode Video into Texture");
00124 void MovieVideoCursor::
00125 fetch_into_texture(double time, Texture *t, int page) {
00126   PStatTimer timer(fetch_into_texture_collector);
00127 
00128   // This generic implementation is layered on fetch_into_buffer.
00129   // It will work for any derived class, so it is never necessary to
00130   // redefine this.  However, it may be possible to make a faster
00131   // implementation that uses fewer intermediate copies, depending
00132   // on the capabilities of the underlying codec software.
00133 
00134   nassertv(t->get_x_size() >= size_x());
00135   nassertv(t->get_y_size() >= size_y());
00136   nassertv((t->get_num_components() == 3) || (t->get_num_components() == 4));
00137   nassertv(t->get_component_width() == 1);
00138   nassertv(page < t->get_z_size());
00139   
00140   PTA_uchar img = t->modify_ram_image();
00141   
00142   unsigned char *data = img.p() + page * t->get_expected_ram_page_size();
00143 
00144   if (t->get_x_size() == size_x()) {
00145     fetch_into_buffer(time, data, t->get_num_components() == 4);
00146   } else {
00147     allocate_conversion_buffer();
00148     fetch_into_buffer(time, _conversion_buffer, t->get_num_components() == 4);
00149     int src_stride = size_x() * t->get_num_components();
00150     int dst_stride = t->get_x_size() * t->get_num_components();
00151     unsigned char *p = _conversion_buffer;
00152     for (int y=0; y<size_y(); y++) {
00153       memcpy(data, p, src_stride);
00154       data += dst_stride;
00155       p += src_stride;
00156     }
00157   }
00158 }
00159 
00160 ////////////////////////////////////////////////////////////////////
00161 //     Function: MovieVideoCursor::fetch_into_texture_alpha
00162 //       Access: Published, Virtual
00163 //  Description: Reads the specified video frame into 
00164 //               the alpha channel of the supplied texture.  The
00165 //               RGB channels of the texture are not touched.
00166 //
00167 //               See fetch_into_buffer for more details.
00168 ////////////////////////////////////////////////////////////////////
00169 void MovieVideoCursor::
00170 fetch_into_texture_alpha(double time, Texture *t, int page, int alpha_src) {
00171 
00172   // This generic implementation is layered on fetch_into_buffer.
00173   // It will work for any derived class, so it is never necessary to
00174   // redefine this.  However, it may be possible to make a faster
00175   // implementation that uses fewer intermediate copies, depending
00176   // on the capabilities of the underlying codec software.
00177 
00178   nassertv(t->get_x_size() >= size_x());
00179   nassertv(t->get_y_size() >= size_y());
00180   nassertv(t->get_num_components() == 4);
00181   nassertv(t->get_component_width() == 1);
00182   nassertv(page < t->get_z_size());
00183   nassertv((alpha_src >= 0) && (alpha_src <= 4));
00184 
00185   allocate_conversion_buffer();
00186   
00187   fetch_into_buffer(time, _conversion_buffer, true);
00188   
00189   PTA_uchar img = t->modify_ram_image();
00190   
00191   unsigned char *data = img.p() + page * t->get_expected_ram_page_size();
00192   
00193   int src_stride = size_x() * 4;
00194   int dst_stride = t->get_x_size() * 4;
00195   if (alpha_src == 0) {
00196     unsigned char *p = _conversion_buffer;
00197     for (int y=0; y<size_y(); y++) {
00198       for (int x=0; x<size_x(); x++) {
00199         data[x*4+3] = (p[x*4+0] + p[x*4+1] + p[x*4+2]) / 3;
00200       }
00201       data += dst_stride;
00202       p += src_stride;
00203     }
00204   } else {
00205     alpha_src -= 1;
00206     unsigned char *p = _conversion_buffer;
00207     for (int y=0; y<size_y(); y++) {
00208       for (int x=0; x<size_x(); x++) {
00209         data[x*4+3] = p[x*4+alpha_src];
00210       }
00211       data += dst_stride;
00212       p += src_stride;
00213     }
00214   }
00215 }
00216 
00217 ////////////////////////////////////////////////////////////////////
00218 //     Function: MovieVideoCursor::fetch_into_texture_rgb
00219 //       Access: Published, Virtual
00220 //  Description: Reads the specified video frame into
00221 //               the RGB channels of the supplied texture.  The alpha
00222 //               channel of the texture is not touched.
00223 //
00224 //               See fetch_into_buffer for more details.
00225 ////////////////////////////////////////////////////////////////////
00226 void MovieVideoCursor::
00227 fetch_into_texture_rgb(double time, Texture *t, int page) {
00228 
00229   // This generic implementation is layered on fetch_into_buffer.
00230   // It will work for any derived class, so it is never necessary to
00231   // redefine this.  However, it may be possible to make a faster
00232   // implementation that uses fewer intermediate copies, depending
00233   // on the capabilities of the underlying codec software.
00234 
00235   nassertv(t->get_x_size() >= size_x());
00236   nassertv(t->get_y_size() >= size_y());
00237   nassertv(t->get_num_components() == 4);
00238   nassertv(t->get_component_width() == 1);
00239   nassertv(page < t->get_z_size());
00240 
00241   allocate_conversion_buffer();
00242   
00243   fetch_into_buffer(time, _conversion_buffer, true);
00244   
00245   PTA_uchar img = t->modify_ram_image();
00246   
00247   unsigned char *data = img.p() + page * t->get_expected_ram_page_size();
00248   
00249   int src_stride = size_x() * 4;
00250   int dst_stride = t->get_x_size() * 4;
00251   unsigned char *p = _conversion_buffer;
00252   for (int y=0; y<size_y(); y++) {
00253     for (int x=0; x<size_x(); x++) {
00254       data[x*4+0] = p[x*4+0];
00255       data[x*4+1] = p[x*4+1];
00256       data[x*4+2] = p[x*4+2];
00257     }
00258     data += dst_stride;
00259     p += src_stride;
00260   }
00261 }
00262 
00263 ////////////////////////////////////////////////////////////////////
00264 //     Function: MovieVideoCursor::fetch_into_buffer
00265 //       Access: Published, Virtual
00266 //  Description: Reads the specified video frame into the supplied
00267 //               BGR or BGRA buffer.  The frame's begin and end
00268 //               times are stored in last_start and next_start.
00269 //
00270 //               If the movie reports that it can_seek, you may
00271 //               also specify a timestamp less than next_start.
00272 //               Otherwise, you may only specify a timestamp
00273 //               greater than or equal to next_start.
00274 //
00275 //               If the movie reports that it can_seek, it doesn't
00276 //               mean that it can do so quickly.  It may have to
00277 //               rewind the movie and then fast forward to the
00278 //               desired location.  Only if can_seek_fast returns
00279 //               true can it seek rapidly.
00280 ////////////////////////////////////////////////////////////////////
00281 void MovieVideoCursor::
00282 fetch_into_buffer(double time, unsigned char *data, bool bgra) {
00283   
00284   // The following is the implementation of the null video stream, ie,
00285   // a stream of blinking red and blue frames.  This method must be
00286   // overridden by the subclass.
00287   
00288   _last_start = floor(time);
00289   _next_start = _last_start + 1;
00290 
00291   if (((int)_last_start) & 1) {
00292     data[0] = 255;
00293     data[1] = 128;
00294     data[2] = 128;
00295   } else {
00296     data[0] = 128;
00297     data[1] = 128;
00298     data[2] = 255;
00299   }
00300   if (bgra) {
00301     data[3] = 255;
00302   }
00303 }
00304 
 All Classes Functions Variables Enumerations