Panda3D
|
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 }