15 #include "pandabase.h" 19 #include "movieVideo.h" 20 #include "movieVideoCursor.h" 21 #include "movieTypeRegistry.h" 22 #include "movieTexture.h" 23 #include "clockObject.h" 24 #include "config_gobj.h" 25 #include "config_grutil.h" 26 #include "bamCacheRecord.h" 27 #include "bamReader.h" 28 #include "bamWriter.h" 30 #include "audioSound.h" 41 MovieTexture(
const string &name) :
56 do_load_one(cdata_tex, video->open(), NULL, 0,
LoaderOptions());
83 CData(
const CData ©) :
85 _video_width(copy._video_width),
86 _video_height(copy._video_height),
87 _video_length(copy._video_length),
103 return new CData(*
this);
113 MovieTexture(
const MovieTexture ©) :
147 ensure_loader_type(
const Filename &filename) {
152 PT(
MovieVideo) video = reg->make_video(filename);
163 return new MovieTexture(
"");
176 do_recalculate_image_properties(CData *cdata, Texture::CData *cdata_tex,
const LoaderOptions &options) {
182 for (
size_t i = 0; i < cdata->_pages.size(); ++i) {
185 if (t->size_x() > x_max) x_max = t->size_x();
186 if (t->size_y() > y_max) y_max = t->size_y();
187 if (t->length() > len) len = t->length();
188 if (t->get_num_components() == 4) alpha=
true;
190 t = cdata->_pages[i]._alpha;
192 if (t->size_x() > x_max) x_max = t->size_x();
193 if (t->size_y() > y_max) y_max = t->size_y();
194 if (t->length() > len) len = t->length();
199 cdata->_video_width = x_max;
200 cdata->_video_height = y_max;
201 cdata->_video_length = len;
203 do_adjust_this_size(cdata_tex, x_max, y_max, get_name(),
true);
205 do_reconsider_image_properties(cdata_tex, x_max, y_max, alpha?4:3,
206 T_unsigned_byte, cdata->_pages.size(),
208 cdata_tex->_orig_file_x_size = cdata->_video_width;
209 cdata_tex->_orig_file_y_size = cdata->_video_height;
211 do_set_pad_size(cdata_tex,
212 max(cdata_tex->_x_size - cdata_tex->_orig_file_x_size, 0),
213 max(cdata_tex->_y_size - cdata_tex->_orig_file_y_size, 0),
225 do_adjust_this_size(
const Texture::CData *cdata_tex,
226 int &x_size,
int &y_size,
const string &name,
227 bool for_padding)
const {
228 AutoTextureScale ats = do_get_auto_texture_scale(cdata_tex);
229 if (ats != ATS_none) {
233 return adjust_size(x_size, y_size, name, for_padding, ats);
244 do_read_one(Texture::CData *cdata_tex,
246 int z,
int n,
int primary_file_num_channels,
int alpha_file_channel,
249 nassertr(n == 0,
false);
250 if (!do_reconsider_z_size(cdata_tex, z, options)) {
253 nassertr(z >= 0 && z < cdata_tex->_z_size * cdata_tex->_num_views,
false);
262 color = MovieVideo::get(fullpath)->open();
266 if (!alpha_fullpath.empty()) {
267 alpha = MovieVideo::get(alpha_fullpath)->open();
278 if (cdata_tex->_filename.empty()) {
279 cdata_tex->_filename = fullpath;
280 cdata_tex->_alpha_filename = alpha_fullpath;
283 cdata_tex->_fullpath = fullpath;
284 cdata_tex->_alpha_fullpath = alpha_fullpath;
287 cdata_tex->_primary_file_num_channels = primary_file_num_channels;
288 cdata_tex->_alpha_file_channel = alpha_file_channel;
290 if (!do_load_one(cdata_tex, color, alpha, z, options)) {
294 cdata_tex->_loaded_from_image =
true;
306 do_load_one(Texture::CData *cdata_tex,
309 CDWriter cdata(_cycler);
310 cdata->_pages.resize(z + 1);
311 cdata->_pages[z]._color = color;
312 cdata->_pages[z]._alpha = alpha;
313 do_recalculate_image_properties(cdata, cdata_tex, options);
317 PTA_uchar image = make_ram_image();
318 memset(image.p(), 0, image.size());
330 do_load_one(Texture::CData *cdata_tex,
331 const PNMImage &pnmimage,
const string &name,
int z,
int n,
333 grutil_cat.error() <<
"You cannot load a static image into a MovieTexture\n";
347 do_allocate_pages(Texture::CData *cdata_tex) {
362 has_cull_callback()
const {
378 CDReader cdata(_cycler);
380 if (!cdata->_has_offset) {
384 int true_loop_count = 1;
385 if (cdata->_synchronize != 0) {
386 offset = cdata->_synchronize->get_time();
390 offset = cdata->_clock;
391 if (cdata->_playing) {
392 offset += now * cdata->_play_rate;
394 true_loop_count = cdata->_loop_count;
396 ((CData *)cdata.p())->_offset = offset;
397 ((CData *)cdata.p())->_true_loop_count = true_loop_count;
398 ((CData *)cdata.p())->_has_offset =
true;
401 bool in_sync = do_update_frames(cdata);
405 in_sync = do_update_frames(cdata);
410 Pages::const_iterator pi;
411 for (pi = cdata->_pages.begin(); pi != cdata->_pages.end(); ++pi) {
412 const VideoPage &page = (*pi);
415 size_t i = pi - cdata->_pages.begin();
417 if (color != NULL && alpha != NULL) {
421 }
else if (color != NULL) {
425 ((VideoPage &)page)._cbuffer.clear();
426 ((VideoPage &)page)._abuffer.clear();
430 ((CData *)cdata.p())->_has_offset =
false;
452 CDReader cdata(_cycler);
453 PT(MovieTexture) copy =
new MovieTexture(get_name());
455 CDWriter cdata_copy(copy->_cycler,
true);
456 copy->do_assign(cdata_copy, cdata_copy_tex,
this, cdata, cdata_tex);
467 do_assign(CData *cdata, Texture::CData *cdata_tex,
const MovieTexture *copy,
468 const CData *cdata_copy,
const Texture::CData *cdata_copy_tex) {
469 Texture::do_assign(cdata_tex, copy, cdata_copy_tex);
473 color.resize(cdata_copy->_pages.size());
474 alpha.resize(cdata_copy->_pages.size());
475 for (
int i=0; i<(int)(color.size()); i++) {
476 color[i] = cdata_copy->_pages[i]._color;
477 alpha[i] = cdata_copy->_pages[i]._alpha;
480 cdata->_pages.resize(color.size());
481 for (
int i=0; i<(int)(color.size()); i++) {
483 cdata->_pages[i]._color = color[i]->get_source()->open();
486 cdata->_pages[i]._alpha = alpha[i]->get_source()->open();
489 do_recalculate_image_properties(cdata, cdata_tex,
LoaderOptions());
500 do_reload_ram_image(Texture::CData *cdata,
bool allow_compression) {
513 get_keep_ram_image()
const {
528 do_has_bam_rawdata(
const Texture::CData *cdata)
const {
539 do_get_bam_rawdata(Texture::CData *cdata) {
552 do_can_reload(
const Texture::CData *cdata)
const {
565 CDWriter cdata(_cycler);
566 if (!cdata->_playing) {
568 cdata->_clock = cdata->_clock - (now * cdata->_play_rate);
569 cdata->_playing =
true;
582 CDWriter cdata(_cycler);
583 if (cdata->_playing) {
585 cdata->_clock = cdata->_clock + (now * cdata->_play_rate);
586 cdata->_playing =
false;
597 CDWriter cdata(_cycler);
599 cdata->_clock = 0.0 - (now * cdata->_play_rate);
600 cdata->_playing =
true;
610 CDWriter cdata(_cycler);
611 t = min(cdata->_video_length, max(0.0, t));
612 if (cdata->_playing) {
614 cdata->_clock = t - (now * cdata->_play_rate);
630 double MovieTexture::
632 CDReader cdata(_cycler);
633 double clock = cdata->_clock;
634 if (cdata->_playing) {
636 clock += (now * cdata->_play_rate);
648 set_loop(
bool loop) {
649 set_loop_count(loop ? 0:1);
660 CDReader cdata(_cycler);
661 return (cdata->_loop_count == 0);
670 set_loop_count(
int n) {
671 CDWriter cdata(_cycler);
672 cdata->_loop_count = n;
681 get_loop_count()
const {
682 CDReader cdata(_cycler);
683 return cdata->_loop_count;
694 set_play_rate(
double rate) {
695 CDWriter cdata(_cycler);
696 if (cdata->_playing) {
698 cdata->_clock += (now * cdata->_play_rate);
699 cdata->_play_rate = rate;
700 cdata->_clock -= (now * cdata->_play_rate);
702 cdata->_play_rate = rate;
711 double MovieTexture::
712 get_play_rate()
const {
713 CDReader cdata(_cycler);
714 return cdata->_play_rate;
724 CDReader cdata(_cycler);
725 return cdata->_playing;
737 CDWriter cdata(_cycler);
738 cdata->_synchronize = s;
748 CDWriter cdata(_cycler);
749 cdata->_synchronize = 0;
762 do_update_frames(
const CData *cdata)
const {
766 nassertr(cdata->_has_offset,
false);
769 Pages::const_iterator pi;
770 for (pi = cdata->_pages.begin(); pi != cdata->_pages.end(); ++pi) {
771 const VideoPage &page = (*pi);
775 if (color != NULL && page._cbuffer == NULL) {
776 if (color->
set_time(cdata->_offset, cdata->_true_loop_count)) {
777 ((VideoPage &)page)._cbuffer = color->fetch_buffer();
780 if (alpha != NULL && page._abuffer == NULL) {
781 if (alpha->
set_time(cdata->_offset, cdata->_true_loop_count)) {
782 ((VideoPage &)page)._abuffer = alpha->fetch_buffer();
787 if (!movies_sync_pages) {
796 bool any_frames =
false;
797 bool any_dropped =
false;
799 for (pi = cdata->_pages.begin(); pi != cdata->_pages.end(); ++pi) {
800 const VideoPage &page = (*pi);
801 if (page._cbuffer == NULL) {
802 if (page._color != NULL) {
807 nassertr(page._color != NULL,
true);
809 if (newest == NULL) {
810 newest = page._cbuffer;
812 int ref = newest->compare_timestamp(page._cbuffer);
818 newest = page._cbuffer;
823 if (page._abuffer == NULL) {
824 if (page._alpha != NULL) {
828 nassertr(page._alpha != NULL,
true);
830 if (newest == NULL) {
831 newest = page._abuffer;
833 int ref = newest->compare_timestamp(page._abuffer);
838 newest = page._abuffer;
853 if (newest != NULL) {
854 Pages::const_iterator pi;
855 for (pi = cdata->_pages.begin(); pi != cdata->_pages.end(); ++pi) {
856 const VideoPage &page = (*pi);
857 if (page._cbuffer != NULL && newest->compare_timestamp(page._cbuffer) > 0) {
858 ((VideoPage &)page)._cbuffer.clear();
861 if (page._abuffer != NULL && newest->compare_timestamp(page._abuffer) > 0) {
862 ((VideoPage &)page)._abuffer.clear();
872 ((CData *)cdata)->_offset = newest->get_timestamp();
886 register_with_read_factory() {
897 PT(MovieTexture) dummy =
new MovieTexture(
"");
898 return dummy->make_this_from_bam(params);
912 CDWriter cdata(_cycler);
913 size_t num_pages = cdata->_pages.size();
914 for (
size_t n = 0; n < num_pages; ++n) {
915 VideoPage &page = cdata->_pages[n];
930 do_write_datagram_rawdata(Texture::CData *cdata_tex,
BamWriter *manager,
Datagram &dg) {
931 CDReader cdata(_cycler);
935 nassertv(cdata->_pages.size() == (size_t)(cdata_tex->_z_size * cdata_tex->_num_views));
936 for (
size_t n = 0; n < cdata->_pages.size(); ++n) {
937 const VideoPage &page = cdata->_pages[n];
951 CDWriter cdata(_cycler);
954 cdata_tex->_num_views = 1;
959 size_t num_pages = (size_t)(cdata_tex->_z_size * cdata_tex->_num_views);
960 cdata->_pages.reserve(num_pages);
961 for (
size_t n = 0; n < num_pages; ++n) {
962 cdata->_pages.push_back(VideoPage());
983 CDWriter cdata(_cycler);
986 size_t num_pages = cdata->_pages.size();
987 for (
size_t n = 0; n < num_pages; ++n) {
988 VideoPage &page = cdata->_pages[n];
993 do_recalculate_image_properties(cdata, cdata_tex,
LoaderOptions());
995 set_loaded_from_image();
1000 #endif // HAVE_AUDIO static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Specifies parameters that may be passed to the loader.
A single page of data maintained by a PipelineCycler.
This class records the different types of MovieAudio and MovieVideo that are available for loading...
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Base class for objects that can be written to and read from Bam files.
This collects together the pieces of data that are accumulated for each node while walking the scene ...
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
double get_frame_time(Thread *current_thread=Thread::get_current_thread()) const
Returns the time in seconds as of the last time tick() was called (typically, this will be as of the ...
virtual void apply_to_texture_rgb(const Buffer *buffer, Texture *t, int page)
Copies this buffer's contents into the RGB channels of the supplied texture.
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
PN_uint16 get_uint16()
Extracts an unsigned 16-bit integer.
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
This is our own Panda specialization on the default STL vector.
virtual bool set_time(double timestamp, int loop_count)
Updates the cursor to the indicated time.
The name of a file, such as a texture file or an Egg file.
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin()...
An instance of this class is written to the front of a Bam or Txo file to make the file a cached inst...
A MovieVideo is actually any source that provides a sequence of video frames.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
virtual void apply_to_texture(const Buffer *buffer, Texture *t, int page)
Stores this buffer's contents in the indicated texture.
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
string get_basename_wo_extension() const
Returns the basename part of the filename, without the file extension.
void finalize_now(TypedWritable *whom)
Forces the finalization of a particular object.
void register_factory(TypeHandle handle, CreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
void add_uint16(PN_uint16 value)
Adds an unsigned 16-bit integer to the datagram.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
static MovieTypeRegistry * get_global_ptr()
Returns a pointer to the global MovieTypeRegistry instance.
A MovieVideo is actually any source that provides a sequence of video frames.
virtual void apply_to_texture_alpha(const Buffer *buffer, Texture *t, int page, int alpha_src)
Copies this buffer's contents into the alpha channel of the supplied texture.
void add_dependent_file(const Filename &pathname)
Adds the indicated file to the list of files that will be loaded to generate the data in this record...
A class to retrieve the individual data elements previously stored in a Datagram. ...
TypeHandle is the identifier used to differentiate C++ class types.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling...
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
void read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.