Panda3D
 All Classes Functions Variables Enumerations
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 #include "bamReader.h"
00020 #include "bamWriter.h"
00021 
00022 PStatCollector MovieVideoCursor::_copy_pcollector("*:Copy Video into Texture");
00023 PStatCollector MovieVideoCursor::_copy_pcollector_ram("*:Copy Video into Texture:modify_ram_image");
00024 PStatCollector MovieVideoCursor::_copy_pcollector_copy("*:Copy Video into Texture:copy");
00025 
00026 TypeHandle MovieVideoCursor::_type_handle;
00027 TypeHandle MovieVideoCursor::Buffer::_type_handle;
00028 
00029 ////////////////////////////////////////////////////////////////////
00030 //     Function: MovieVideoCursor::Default Constructor
00031 //       Access: Protected
00032 //  Description: This is a virtual base class and should not be
00033 //               created directly.  Instead, create a more specialized
00034 //               class.
00035 ////////////////////////////////////////////////////////////////////
00036 MovieVideoCursor::
00037 MovieVideoCursor(MovieVideo *src) :
00038   _source(src),
00039   _size_x(1),
00040   _size_y(1),
00041   _num_components(3),
00042   _length(1.0E10),
00043   _can_seek(true),
00044   _can_seek_fast(true),
00045   _aborted(false),
00046   _streaming(false),
00047   _ready(false)
00048 {
00049 }
00050 
00051 ////////////////////////////////////////////////////////////////////
00052 //     Function: MovieVideoCursor::Destructor
00053 //       Access: Public, Virtual
00054 //  Description: 
00055 ////////////////////////////////////////////////////////////////////
00056 MovieVideoCursor::
00057 ~MovieVideoCursor() {
00058 }
00059   
00060 ////////////////////////////////////////////////////////////////////
00061 //     Function: MovieVideoCursor::setup_texture
00062 //       Access: Published
00063 //  Description: Set up the specified Texture object to contain
00064 //               content from this movie.  This should be called
00065 //               once, not every frame.
00066 ////////////////////////////////////////////////////////////////////
00067 void MovieVideoCursor::
00068 setup_texture(Texture *tex) const {
00069   int fullx = size_x();
00070   int fully = size_y();
00071   tex->adjust_this_size(fullx, fully, tex->get_name(), true);
00072   Texture::Format fmt = (get_num_components() == 4) ? Texture::F_rgba : Texture::F_rgb;
00073   tex->setup_texture(Texture::TT_2d_texture, fullx, fully, 1, Texture::T_unsigned_byte, fmt);
00074   tex->set_pad_size(fullx - size_x(), fully - size_y());
00075 }
00076 
00077 ////////////////////////////////////////////////////////////////////
00078 //     Function: MovieVideoCursor::set_time
00079 //       Access: Published, Virtual
00080 //  Description: Updates the cursor to the indicated time.  If
00081 //               loop_count >= 1, the time is clamped to the movie's
00082 //               length * loop_count.  If loop_count <= 0, the time is
00083 //               understood to be modulo the movie's length.
00084 //
00085 //               Returns true if a new frame is now available, false
00086 //               otherwise.  If this returns true, you should
00087 //               immediately follow this with exactly *one* call to
00088 //               fetch_buffer().
00089 //
00090 //               If the movie reports that it can_seek, you may also
00091 //               specify a time value less than the previous value you
00092 //               passed to set_time().  Otherwise, you may only
00093 //               specify a time value greater than or equal to
00094 //               the previous value.
00095 //
00096 //               If the movie reports that it can_seek, it doesn't
00097 //               mean that it can do so quickly.  It may have to
00098 //               rewind the movie and then fast forward to the
00099 //               desired location.  Only if can_seek_fast returns
00100 //               true can it seek rapidly.
00101 ////////////////////////////////////////////////////////////////////
00102 bool MovieVideoCursor::
00103 set_time(double timestamp, int loop_count) {
00104   return true;
00105 }
00106 
00107 ////////////////////////////////////////////////////////////////////
00108 //     Function: MovieVideoCursor::fetch_buffer
00109 //       Access: Published, Virtual
00110 //  Description: Gets the current video frame (as specified by
00111 //               set_time()) from the movie and returns it in a
00112 //               pre-allocated buffer.  You may simply let the buffer
00113 //               dereference and delete itself when you are done with
00114 //               it.
00115 //
00116 //               This may return NULL (even if set_time() returned
00117 //               true) if the frame is not available for some reason.
00118 ////////////////////////////////////////////////////////////////////
00119 PT(MovieVideoCursor::Buffer) MovieVideoCursor::
00120 fetch_buffer() {
00121   return NULL;
00122 }
00123 
00124 ////////////////////////////////////////////////////////////////////
00125 //     Function: MovieVideoCursor::apply_to_texture
00126 //       Access: Published, Virtual
00127 //  Description: Stores this buffer's contents in the indicated texture.
00128 ////////////////////////////////////////////////////////////////////
00129 void MovieVideoCursor::
00130 apply_to_texture(const Buffer *buffer, Texture *t, int page) {
00131   if (buffer == NULL) {
00132     return;
00133   }
00134 
00135   PStatTimer timer(_copy_pcollector);
00136 
00137   nassertv(t->get_x_size() >= size_x());
00138   nassertv(t->get_y_size() >= size_y());
00139   nassertv((t->get_num_components() == 3) || (t->get_num_components() == 4));
00140   nassertv(t->get_component_width() == 1);
00141   nassertv(page < t->get_num_pages());
00142   
00143   PTA_uchar img;
00144   {
00145     PStatTimer timer2(_copy_pcollector_ram);
00146     t->set_keep_ram_image(true);
00147     img = t->modify_ram_image();
00148   }
00149   
00150   unsigned char *data = img.p() + page * t->get_expected_ram_page_size();
00151 
00152   PStatTimer timer2(_copy_pcollector_copy);
00153   if (t->get_x_size() == size_x() && t->get_num_components() == get_num_components()) {
00154     memcpy(data, buffer->_block, size_x() * size_y() * get_num_components());
00155     
00156   } else {
00157     unsigned char *p = buffer->_block;
00158     if (t->get_num_components() == get_num_components()) {
00159       int src_stride = size_x() * get_num_components();
00160       int dst_stride = t->get_x_size() * t->get_num_components();
00161       for (int y=0; y<size_y(); y++) {
00162         memcpy(data, p, src_stride);
00163         data += dst_stride;
00164         p += src_stride;
00165       }
00166     } else {
00167       int src_width = get_num_components();
00168       int dst_width = t->get_num_components();
00169       for (int y = 0; y < size_y(); ++y) {
00170         for (int x = 0; x < size_x(); ++x) {
00171           data[0] = p[0];
00172           data[1] = p[1];
00173           data[2] = p[2];
00174           data += dst_width;
00175           p += src_width;
00176         }
00177       }
00178     }
00179   }
00180 }
00181 
00182 ////////////////////////////////////////////////////////////////////
00183 //     Function: MovieVideoCursor::apply_to_texture_alpha
00184 //       Access: Published, Virtual
00185 //  Description: Copies this buffer's contents into the alpha channel
00186 //               of the supplied texture.  The RGB channels of the
00187 //               texture are not touched.
00188 ////////////////////////////////////////////////////////////////////
00189 void MovieVideoCursor::
00190 apply_to_texture_alpha(const Buffer *buffer, Texture *t, int page, int alpha_src) {
00191   if (buffer == NULL) {
00192     return;
00193   }
00194 
00195   PStatTimer timer(_copy_pcollector);
00196 
00197   nassertv(t->get_x_size() >= size_x());
00198   nassertv(t->get_y_size() >= size_y());
00199   nassertv(t->get_num_components() == 4);
00200   nassertv(t->get_component_width() == 1);
00201   nassertv(page < t->get_z_size());
00202   nassertv((alpha_src >= 0) && (alpha_src <= get_num_components()));
00203 
00204   PTA_uchar img;
00205   {
00206     PStatTimer timer2(_copy_pcollector_ram);
00207     t->set_keep_ram_image(true);
00208     img = t->modify_ram_image();
00209   }
00210   
00211   unsigned char *data = img.p() + page * t->get_expected_ram_page_size();
00212   
00213   PStatTimer timer2(_copy_pcollector_copy);
00214   int src_stride = size_x() * get_num_components();
00215   int dst_stride = t->get_x_size() * 4;
00216   if (alpha_src == 0) {
00217     unsigned char *p = buffer->_block;
00218     for (int y=0; y<size_y(); y++) {
00219       for (int x=0; x<size_x(); x++) {
00220         data[x*4+3] = (p[x*4+0] + p[x*4+1] + p[x*4+2]) / 3;
00221       }
00222       data += dst_stride;
00223       p += src_stride;
00224     }
00225   } else {
00226     alpha_src -= 1;
00227     unsigned char *p = buffer->_block;
00228     int src_width = get_num_components();
00229     for (int y=0; y<size_y(); y++) {
00230       for (int x=0; x<size_x(); x++) {
00231         data[x*4+3] = p[x *src_width + alpha_src];
00232       }
00233       data += dst_stride;
00234       p += src_stride;
00235     }
00236   }
00237 }
00238 
00239 ////////////////////////////////////////////////////////////////////
00240 //     Function: MovieVideoCursor::apply_to_texture_rgb
00241 //       Access: Published, Virtual
00242 //  Description: Copies this buffer's contents into the RGB channels
00243 //               of the supplied texture.  The alpha channel of the
00244 //               texture is not touched.
00245 ////////////////////////////////////////////////////////////////////
00246 void MovieVideoCursor::
00247 apply_to_texture_rgb(const Buffer *buffer, Texture *t, int page) {
00248   if (buffer == NULL) {
00249     return;
00250   }
00251 
00252   PStatTimer timer(_copy_pcollector);
00253 
00254   nassertv(t->get_x_size() >= size_x());
00255   nassertv(t->get_y_size() >= size_y());
00256   nassertv(t->get_num_components() == 4);
00257   nassertv(t->get_component_width() == 1);
00258   nassertv(page < t->get_z_size());
00259   
00260   PTA_uchar img;
00261   {
00262     PStatTimer timer2(_copy_pcollector_ram);
00263     t->set_keep_ram_image(true);
00264     img = t->modify_ram_image();
00265   }
00266   
00267   unsigned char *data = img.p() + page * t->get_expected_ram_page_size();
00268   
00269   PStatTimer timer2(_copy_pcollector_copy);
00270   int src_stride = size_x() * get_num_components();
00271   int src_width = get_num_components();
00272   int dst_stride = t->get_x_size() * 4;
00273   unsigned char *p = buffer->_block;
00274   for (int y=0; y<size_y(); y++) {
00275     for (int x=0; x<size_x(); x++) {
00276       data[x * 4 + 0] = p[x * src_width + 0];
00277       data[x * 4 + 1] = p[x * src_width + 1];
00278       data[x * 4 + 2] = p[x * src_width + 2];
00279     }
00280     data += dst_stride;
00281     p += src_stride;
00282   }
00283 }
00284 
00285 ////////////////////////////////////////////////////////////////////
00286 //     Function: MovieVideoCursor::get_standard_buffer
00287 //       Access: Protected
00288 //  Description: May be called by a derived class to return a single
00289 //               standard Buffer object to easily implement
00290 //               fetch_buffer().
00291 ////////////////////////////////////////////////////////////////////
00292 MovieVideoCursor::Buffer *MovieVideoCursor::
00293 get_standard_buffer() {
00294   if (_standard_buffer == NULL) {
00295     _standard_buffer = make_new_buffer();
00296   }
00297   return _standard_buffer;
00298 }
00299 
00300 ////////////////////////////////////////////////////////////////////
00301 //     Function: MovieVideoCursor::make_new_buffer
00302 //       Access: Protected, Virtual
00303 //  Description: May be called by a derived class to allocate a new
00304 //               Buffer object.
00305 ////////////////////////////////////////////////////////////////////
00306 PT(MovieVideoCursor::Buffer) MovieVideoCursor::
00307 make_new_buffer() {
00308   return new Buffer(size_x() * size_y() * get_num_components());
00309 }
00310 
00311 ////////////////////////////////////////////////////////////////////
00312 //     Function: MovieVideoCursor::write_datagram
00313 //       Access: Public, Virtual
00314 //  Description: Writes the contents of this object to the datagram
00315 //               for shipping out to a Bam file.
00316 ////////////////////////////////////////////////////////////////////
00317 void MovieVideoCursor::
00318 write_datagram(BamWriter *manager, Datagram &dg) {
00319   TypedWritableReferenceCount::write_datagram(manager, dg);
00320 
00321   manager->write_pointer(dg, _source);
00322 }
00323 
00324 ////////////////////////////////////////////////////////////////////
00325 //     Function: MovieVideoCursor::complete_pointers
00326 //       Access: Public, Virtual
00327 //  Description: Receives an array of pointers, one for each time
00328 //               manager->read_pointer() was called in fillin().
00329 //               Returns the number of pointers processed.
00330 ////////////////////////////////////////////////////////////////////
00331 int MovieVideoCursor::
00332 complete_pointers(TypedWritable **p_list, BamReader *manager) {
00333   int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager);
00334 
00335   _source = DCAST(MovieVideo, p_list[pi++]);
00336 
00337   return pi;
00338 }
00339 
00340 ////////////////////////////////////////////////////////////////////
00341 //     Function: MovieVideoCursor::fillin
00342 //       Access: Protected
00343 //  Description: This internal function is called by make_from_bam to
00344 //               read in all of the relevant data from the BamFile for
00345 //               the new MovieVideoCursor.
00346 ////////////////////////////////////////////////////////////////////
00347 void MovieVideoCursor::
00348 fillin(DatagramIterator &scan, BamReader *manager) {
00349   TypedWritableReferenceCount::fillin(scan, manager);
00350 
00351   manager->read_pointer(scan);  // _source
00352 }
00353 
00354 ////////////////////////////////////////////////////////////////////
00355 //     Function: MovieVideoCursor::Buffer::Constructor
00356 //       Access: Public
00357 //  Description: 
00358 ////////////////////////////////////////////////////////////////////
00359 MovieVideoCursor::Buffer::
00360 Buffer(size_t block_size) :
00361   _block_size(block_size)
00362 {
00363   _deleted_chain = memory_hook->get_deleted_chain(_block_size);
00364   _block = (unsigned char *)_deleted_chain->allocate(_block_size, get_class_type());
00365 }
00366 
00367 ////////////////////////////////////////////////////////////////////
00368 //     Function: MovieVideoCursor::Buffer::Destructor
00369 //       Access: Published, Virtual
00370 //  Description: 
00371 ////////////////////////////////////////////////////////////////////
00372 MovieVideoCursor::Buffer::
00373 ~Buffer() {
00374   _deleted_chain->deallocate(_block, get_class_type());
00375 }
00376 
00377 ////////////////////////////////////////////////////////////////////
00378 //     Function: MovieVideoCursor::Buffer::compare_timestamp
00379 //       Access: Published, Virtual
00380 //  Description: Used to sort different buffers to ensure they
00381 //               correspond to the same source frame, particularly
00382 //               important when synchronizing the different pages of a
00383 //               multi-page texture.
00384 //
00385 //               Returns 0 if the two buffers are of the same frame,
00386 //               <0 if this one comes earlier than the other one, and
00387 //               >0 if the other one comes earlier.
00388 ////////////////////////////////////////////////////////////////////
00389 int MovieVideoCursor::Buffer::
00390 compare_timestamp(const Buffer *other) const {
00391   return 0;
00392 }
00393 
00394 ////////////////////////////////////////////////////////////////////
00395 //     Function: MovieVideoCursor::Buffer::get_timestamp
00396 //       Access: Published, Virtual
00397 //  Description: Returns the nearest timestamp value of this
00398 //               particular buffer.  Ideally,
00399 //               MovieVideoCursor::set_time() for this timestamp would
00400 //               return this buffer again.  This need be defined only
00401 //               if compare_timestamp() is also defined.
00402 ////////////////////////////////////////////////////////////////////
00403 double MovieVideoCursor::Buffer::
00404 get_timestamp() const {
00405   return 0.0;
00406 }
 All Classes Functions Variables Enumerations