Panda3D
Loading...
Searching...
No Matches
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.
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.
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...
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:72
PTA_uchar modify_ram_image()
Returns a modifiable pointer to the system-RAM image.
Definition texture.I:1383
get_component_width
Returns the number of bytes stored for each color component of a texel.
Definition texture.h:365
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:53
get_y_size
Returns the height of the texture image in texels.
Definition texture.h:347
void set_pad_size(int x=0, int y=0, int z=0)
Sets the size of the pad region.
Definition texture.I:678
get_num_components
Returns the number of color components for each texel of the texture image.
Definition texture.h:364
get_x_size
Returns the width of the texture image in texels.
Definition texture.h:343
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:450
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:2155
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:473
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.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.