Panda3D
movieVideoCursor.cxx
1 // Filename: movieVideo.cxx
2 // Created by: jyelon (02Jul07)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "movieVideoCursor.h"
16 #include "config_movies.h"
17 #include "pStatCollector.h"
18 #include "pStatTimer.h"
19 #include "bamReader.h"
20 #include "bamWriter.h"
21 
22 PStatCollector MovieVideoCursor::_copy_pcollector("*:Copy Video into Texture");
23 PStatCollector MovieVideoCursor::_copy_pcollector_ram("*:Copy Video into Texture:modify_ram_image");
24 PStatCollector MovieVideoCursor::_copy_pcollector_copy("*:Copy Video into Texture:copy");
25 
26 TypeHandle MovieVideoCursor::_type_handle;
27 TypeHandle MovieVideoCursor::Buffer::_type_handle;
28 
29 ////////////////////////////////////////////////////////////////////
30 // Function: MovieVideoCursor::Default Constructor
31 // Access: Protected
32 // Description: This is a virtual base class and should not be
33 // created directly. Instead, create a more specialized
34 // class.
35 ////////////////////////////////////////////////////////////////////
36 MovieVideoCursor::
37 MovieVideoCursor(MovieVideo *src) :
38  _source(src),
39  _size_x(1),
40  _size_y(1),
41  _num_components(3),
42  _length(1.0E10),
43  _can_seek(true),
44  _can_seek_fast(true),
45  _aborted(false),
46  _streaming(false),
47  _ready(false)
48 {
49 }
50 
51 ////////////////////////////////////////////////////////////////////
52 // Function: MovieVideoCursor::Destructor
53 // Access: Public, Virtual
54 // Description:
55 ////////////////////////////////////////////////////////////////////
56 MovieVideoCursor::
57 ~MovieVideoCursor() {
58 }
59 
60 ////////////////////////////////////////////////////////////////////
61 // Function: MovieVideoCursor::setup_texture
62 // Access: Published
63 // Description: Set up the specified Texture object to contain
64 // content from this movie. This should be called
65 // once, not every frame.
66 ////////////////////////////////////////////////////////////////////
68 setup_texture(Texture *tex) const {
69  int fullx = size_x();
70  int fully = size_y();
71  tex->adjust_this_size(fullx, fully, tex->get_name(), true);
72  Texture::Format fmt = (get_num_components() == 4) ? Texture::F_rgba : Texture::F_rgb;
73  tex->setup_texture(Texture::TT_2d_texture, fullx, fully, 1, Texture::T_unsigned_byte, fmt);
74  tex->set_pad_size(fullx - size_x(), fully - size_y());
75 }
76 
77 ////////////////////////////////////////////////////////////////////
78 // Function: MovieVideoCursor::set_time
79 // Access: Published, Virtual
80 // Description: Updates the cursor to the indicated time. If
81 // loop_count >= 1, the time is clamped to the movie's
82 // length * loop_count. If loop_count <= 0, the time is
83 // understood to be modulo the movie's length.
84 //
85 // Returns true if a new frame is now available, false
86 // otherwise. If this returns true, you should
87 // immediately follow this with exactly *one* call to
88 // fetch_buffer().
89 //
90 // If the movie reports that it can_seek, you may also
91 // specify a time value less than the previous value you
92 // passed to set_time(). Otherwise, you may only
93 // specify a time value greater than or equal to
94 // the previous value.
95 //
96 // If the movie reports that it can_seek, it doesn't
97 // mean that it can do so quickly. It may have to
98 // rewind the movie and then fast forward to the
99 // desired location. Only if can_seek_fast returns
100 // true can it seek rapidly.
101 ////////////////////////////////////////////////////////////////////
103 set_time(double timestamp, int loop_count) {
104  return true;
105 }
106 
107 ////////////////////////////////////////////////////////////////////
108 // Function: MovieVideoCursor::fetch_buffer
109 // Access: Published, Virtual
110 // Description: Gets the current video frame (as specified by
111 // set_time()) from the movie and returns it in a
112 // pre-allocated buffer. You may simply let the buffer
113 // dereference and delete itself when you are done with
114 // it.
115 //
116 // This may return NULL (even if set_time() returned
117 // true) if the frame is not available for some reason.
118 ////////////////////////////////////////////////////////////////////
119 PT(MovieVideoCursor::Buffer) MovieVideoCursor::
120 fetch_buffer() {
121  return NULL;
122 }
123 
124 ////////////////////////////////////////////////////////////////////
125 // Function: MovieVideoCursor::apply_to_texture
126 // Access: Published, Virtual
127 // Description: Stores this buffer's contents in the indicated texture.
128 ////////////////////////////////////////////////////////////////////
130 apply_to_texture(const Buffer *buffer, Texture *t, int page) {
131  if (buffer == NULL) {
132  return;
133  }
134 
135  PStatTimer timer(_copy_pcollector);
136 
137  nassertv(t->get_x_size() >= size_x());
138  nassertv(t->get_y_size() >= size_y());
139  nassertv((t->get_num_components() == 3) || (t->get_num_components() == 4));
140  nassertv(t->get_component_width() == 1);
141  nassertv(page < t->get_num_pages());
142 
143  PTA_uchar img;
144  {
145  PStatTimer timer2(_copy_pcollector_ram);
146  t->set_keep_ram_image(true);
147  img = t->modify_ram_image();
148  }
149 
150  unsigned char *data = img.p() + page * t->get_expected_ram_page_size();
151 
152  PStatTimer timer2(_copy_pcollector_copy);
153  if (t->get_x_size() == size_x() && t->get_num_components() == get_num_components()) {
154  memcpy(data, buffer->_block, size_x() * size_y() * get_num_components());
155 
156  } else {
157  unsigned char *p = buffer->_block;
158  if (t->get_num_components() == get_num_components()) {
159  int src_stride = size_x() * get_num_components();
160  int dst_stride = t->get_x_size() * t->get_num_components();
161  for (int y=0; y<size_y(); y++) {
162  memcpy(data, p, src_stride);
163  data += dst_stride;
164  p += src_stride;
165  }
166  } else {
167  int src_width = get_num_components();
168  int dst_width = t->get_num_components();
169  for (int y = 0; y < size_y(); ++y) {
170  for (int x = 0; x < size_x(); ++x) {
171  data[0] = p[0];
172  data[1] = p[1];
173  data[2] = p[2];
174  data += dst_width;
175  p += src_width;
176  }
177  }
178  }
179  }
180 }
181 
182 ////////////////////////////////////////////////////////////////////
183 // Function: MovieVideoCursor::apply_to_texture_alpha
184 // Access: Published, Virtual
185 // Description: Copies this buffer's contents into the alpha channel
186 // of the supplied texture. The RGB channels of the
187 // texture are not touched.
188 ////////////////////////////////////////////////////////////////////
190 apply_to_texture_alpha(const Buffer *buffer, Texture *t, int page, int alpha_src) {
191  if (buffer == NULL) {
192  return;
193  }
194 
195  PStatTimer timer(_copy_pcollector);
196 
197  nassertv(t->get_x_size() >= size_x());
198  nassertv(t->get_y_size() >= size_y());
199  nassertv(t->get_num_components() == 4);
200  nassertv(t->get_component_width() == 1);
201  nassertv(page < t->get_z_size());
202  nassertv((alpha_src >= 0) && (alpha_src <= get_num_components()));
203 
204  PTA_uchar img;
205  {
206  PStatTimer timer2(_copy_pcollector_ram);
207  t->set_keep_ram_image(true);
208  img = t->modify_ram_image();
209  }
210 
211  unsigned char *data = img.p() + page * t->get_expected_ram_page_size();
212 
213  PStatTimer timer2(_copy_pcollector_copy);
214  int src_width = get_num_components();
215  int src_stride = size_x() * src_width;
216  int dst_stride = t->get_x_size() * 4;
217  unsigned char *p = buffer->_block;
218  if (alpha_src == 0) {
219  for (int y=0; y<size_y(); y++) {
220  for (int x=0; x<size_x(); x++) {
221  unsigned char *pp = &p[x * src_width];
222  data[x*4+3] = (pp[0] + pp[1] + pp[2]) / 3;
223  }
224  data += dst_stride;
225  p += src_stride;
226  }
227  } else {
228  alpha_src -= 1;
229  for (int y=0; y<size_y(); y++) {
230  for (int x=0; x<size_x(); x++) {
231  data[x*4+3] = p[x * src_width + alpha_src];
232  }
233  data += dst_stride;
234  p += src_stride;
235  }
236  }
237 }
238 
239 ////////////////////////////////////////////////////////////////////
240 // Function: MovieVideoCursor::apply_to_texture_rgb
241 // Access: Published, Virtual
242 // Description: Copies this buffer's contents into the RGB channels
243 // of the supplied texture. The alpha channel of the
244 // texture is not touched.
245 ////////////////////////////////////////////////////////////////////
247 apply_to_texture_rgb(const Buffer *buffer, Texture *t, int page) {
248  if (buffer == NULL) {
249  return;
250  }
251 
252  PStatTimer timer(_copy_pcollector);
253 
254  nassertv(t->get_x_size() >= size_x());
255  nassertv(t->get_y_size() >= size_y());
256  nassertv(t->get_num_components() == 4);
257  nassertv(t->get_component_width() == 1);
258  nassertv(page < t->get_z_size());
259 
260  PTA_uchar img;
261  {
262  PStatTimer timer2(_copy_pcollector_ram);
263  t->set_keep_ram_image(true);
264  img = t->modify_ram_image();
265  }
266 
267  unsigned char *data = img.p() + page * t->get_expected_ram_page_size();
268 
269  PStatTimer timer2(_copy_pcollector_copy);
270  int src_stride = size_x() * get_num_components();
271  int src_width = get_num_components();
272  int dst_stride = t->get_x_size() * 4;
273  unsigned char *p = buffer->_block;
274  for (int y=0; y<size_y(); y++) {
275  for (int x=0; x<size_x(); x++) {
276  data[x * 4 + 0] = p[x * src_width + 0];
277  data[x * 4 + 1] = p[x * src_width + 1];
278  data[x * 4 + 2] = p[x * src_width + 2];
279  }
280  data += dst_stride;
281  p += src_stride;
282  }
283 }
284 
285 ////////////////////////////////////////////////////////////////////
286 // Function: MovieVideoCursor::get_standard_buffer
287 // Access: Protected
288 // Description: May be called by a derived class to return a single
289 // standard Buffer object to easily implement
290 // fetch_buffer().
291 ////////////////////////////////////////////////////////////////////
292 MovieVideoCursor::Buffer *MovieVideoCursor::
293 get_standard_buffer() {
294  if (_standard_buffer == NULL) {
295  _standard_buffer = make_new_buffer();
296  }
297  return _standard_buffer;
298 }
299 
300 ////////////////////////////////////////////////////////////////////
301 // Function: MovieVideoCursor::make_new_buffer
302 // Access: Protected, Virtual
303 // Description: May be called by a derived class to allocate a new
304 // Buffer object.
305 ////////////////////////////////////////////////////////////////////
306 PT(MovieVideoCursor::Buffer) MovieVideoCursor::
307 make_new_buffer() {
308  return new Buffer(size_x() * size_y() * get_num_components());
309 }
310 
311 ////////////////////////////////////////////////////////////////////
312 // Function: MovieVideoCursor::write_datagram
313 // Access: Public, Virtual
314 // Description: Writes the contents of this object to the datagram
315 // for shipping out to a Bam file.
316 ////////////////////////////////////////////////////////////////////
320 
321  manager->write_pointer(dg, _source);
322 }
323 
324 ////////////////////////////////////////////////////////////////////
325 // Function: MovieVideoCursor::complete_pointers
326 // Access: Public, Virtual
327 // Description: Receives an array of pointers, one for each time
328 // manager->read_pointer() was called in fillin().
329 // Returns the number of pointers processed.
330 ////////////////////////////////////////////////////////////////////
333  int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager);
334 
335  _source = DCAST(MovieVideo, p_list[pi++]);
336 
337  return pi;
338 }
339 
340 ////////////////////////////////////////////////////////////////////
341 // Function: MovieVideoCursor::fillin
342 // Access: Protected
343 // Description: This internal function is called by make_from_bam to
344 // read in all of the relevant data from the BamFile for
345 // the new MovieVideoCursor.
346 ////////////////////////////////////////////////////////////////////
347 void MovieVideoCursor::
348 fillin(DatagramIterator &scan, BamReader *manager) {
350 
351  manager->read_pointer(scan); // _source
352 }
353 
354 ////////////////////////////////////////////////////////////////////
355 // Function: MovieVideoCursor::Buffer::Constructor
356 // Access: Public
357 // Description:
358 ////////////////////////////////////////////////////////////////////
359 MovieVideoCursor::Buffer::
360 Buffer(size_t block_size) :
361  _block_size(block_size)
362 {
363  _deleted_chain = memory_hook->get_deleted_chain(_block_size);
364  _block = (unsigned char *)_deleted_chain->allocate(_block_size, get_class_type());
365 }
366 
367 ////////////////////////////////////////////////////////////////////
368 // Function: MovieVideoCursor::Buffer::Destructor
369 // Access: Published, Virtual
370 // Description:
371 ////////////////////////////////////////////////////////////////////
372 MovieVideoCursor::Buffer::
373 ~Buffer() {
374  _deleted_chain->deallocate(_block, get_class_type());
375 }
376 
377 ////////////////////////////////////////////////////////////////////
378 // Function: MovieVideoCursor::Buffer::compare_timestamp
379 // Access: Published, Virtual
380 // Description: Used to sort different buffers to ensure they
381 // correspond to the same source frame, particularly
382 // important when synchronizing the different pages of a
383 // multi-page texture.
384 //
385 // Returns 0 if the two buffers are of the same frame,
386 // <0 if this one comes earlier than the other one, and
387 // >0 if the other one comes earlier.
388 ////////////////////////////////////////////////////////////////////
390 compare_timestamp(const Buffer *other) const {
391  return 0;
392 }
393 
394 ////////////////////////////////////////////////////////////////////
395 // Function: MovieVideoCursor::Buffer::get_timestamp
396 // Access: Published, Virtual
397 // Description: Returns the nearest timestamp value of this
398 // particular buffer. Ideally,
399 // MovieVideoCursor::set_time() for this timestamp would
400 // return this buffer again. This need be defined only
401 // if compare_timestamp() is also defined.
402 ////////////////////////////////////////////////////////////////////
404 get_timestamp() const {
405  return 0.0;
406 }
DeletedBufferChain * get_deleted_chain(size_t buffer_size)
Returns a pointer to a global DeletedBufferChain object suitable for allocating arrays of the indicat...
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:122
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition: texture.h:75
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:37
void setup_texture(TextureType texture_type, int x_size, int y_size, int z_size, ComponentType component_type, Format format)
Sets the texture to the indicated type and dimensions, presumably in preparation for calling read() o...
Definition: texture.I:62
void setup_texture(Texture *tex) const
Set up the specified Texture object to contain content from this movie.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:34
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:73
int get_component_width() const
Returns the number of bytes stored for each color component of a texel.
Definition: texture.I:848
void * allocate(size_t size, TypeHandle type_handle)
Allocates the memory for a new buffer of the indicated size (which must be no greater than the fixed ...
virtual void apply_to_texture_rgb(const Buffer *buffer, Texture *t, int page)
Copies this buffer&#39;s contents into the RGB channels of the supplied texture.
virtual void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is intended to be called by each class&#39;s make_from_bam() method to read in all...
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
A lightweight class that represents a single element that may be timed and/or counted via stats...
virtual int complete_pointers(TypedWritable **plist, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin()...
virtual bool set_time(double timestamp, int loop_count)
Updates the cursor to the indicated time.
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()...
void set_pad_size(int x=0, int y=0, int z=0)
Sets the size of the pad region.
Definition: texture.I:779
void deallocate(void *ptr, TypeHandle type_handle)
Frees the memory for a buffer previously allocated via allocate().
void set_keep_ram_image(bool keep_ram_image)
Sets the flag that indicates whether this Texture is eligible to have its main RAM copy of the textur...
Definition: texture.I:1731
virtual int compare_timestamp(const Buffer *other) const
Used to sort different buffers to ensure they correspond to the same source frame, particularly important when synchronizing the different pages of a multi-page texture.
virtual void apply_to_texture(const Buffer *buffer, Texture *t, int page)
Stores this buffer&#39;s contents in the indicated texture.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
int get_y_size() const
Returns the height of the texture image in texels.
Definition: texture.I:650
A MovieVideo is actually any source that provides a sequence of video frames.
Definition: movieVideo.h:42
virtual void apply_to_texture_alpha(const Buffer *buffer, Texture *t, int page, int alpha_src)
Copies this buffer&#39;s contents into the alpha channel of the supplied texture.
A class to retrieve the individual data elements previously stored in a Datagram. ...
int get_num_components() const
Returns the number of color components for each texel of the texture image.
Definition: texture.I:835
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
PTA_uchar modify_ram_image()
Returns a modifiable pointer to the system-RAM image.
Definition: texture.I:1640
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:43
bool adjust_this_size(int &x_size, int &y_size, const string &name, bool for_padding) const
Works like adjust_size, but also considers the texture class.
Definition: texture.I:2604
size_t get_expected_ram_page_size() const
Returns the number of bytes that should be used per each Z page of the 3-d texture.
Definition: texture.I:1574
int get_x_size() const
Returns the width of the texture image in texels.
Definition: texture.I:638
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
Definition: bamWriter.cxx:279
void read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
Definition: bamReader.cxx:658
virtual double get_timestamp() const
Returns the nearest timestamp value of this particular buffer.