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