26 #if defined(OPENCV_VER_3)
28 #include <opencv2/core.hpp>
29 #include <opencv2/videoio/videoio_c.h>
32 #elif defined(OPENCV_VER_23)
34 #include <opencv2/core/core.hpp>
35 #include <opencv2/highgui/highgui.hpp>
44 #endif // OPENCV_VER_3
52 OpenCVTexture(
const std::string &name) :
70 if (this_frame != _last_frame_update) {
71 int frame = get_frame();
72 if (_current_frame != frame) {
74 do_update_frame(cdata, frame);
75 _current_frame = frame;
79 int max_z = std::max(cdata->_z_size, (
int)_pages.size());
80 for (
int z = 0; z < max_z; ++z) {
81 VideoPage &page = _pages[z];
82 if (!page._color.is_from_file() || !page._alpha.is_from_file()) {
83 do_update_frame(cdata, frame, z);
87 _last_frame_update = this_frame;
101 make_copy_impl()
const {
103 PT(OpenCVTexture) copy =
new OpenCVTexture(get_name());
105 copy->do_assign(cdata_copy_tex,
this, cdata_tex);
114 do_assign(Texture::CData *cdata_tex,
const OpenCVTexture *copy,
115 const Texture::CData *cdata_copy_tex) {
116 VideoTexture::do_assign(cdata_tex, copy, cdata_copy_tex);
117 _pages = copy->_pages;
130 from_camera(
int camera_index,
int z,
int alpha_file_channel,
133 if (!do_reconsider_z_size(cdata, z, options)) {
136 nassertr(z >= 0 && z < cdata->_z_size,
false);
138 cdata->_alpha_file_channel = alpha_file_channel;
140 VideoPage &page = do_modify_page(cdata, z);
141 if (alpha_file_channel == 0) {
144 if (!page._color.from_camera(camera_index)) {
148 if (!do_reconsider_video_properties(cdata, page._color, 3, z, options)) {
155 if (!page._alpha.from_camera(camera_index)) {
159 if (!do_reconsider_video_properties(cdata, page._alpha, 1, z, options)) {
163 do_set_format(cdata, F_alpha);
166 cdata->_loaded_from_image =
true;
167 clear_current_frame();
168 do_update_frame(cdata, 0);
177 OpenCVTexture::VideoPage &OpenCVTexture::
178 do_modify_page(
const Texture::CData *cdata,
int z) {
179 nassertr(z < cdata->_z_size, _pages[0]);
180 while (z >= (
int)_pages.size()) {
181 _pages.push_back(VideoPage());
191 do_reconsider_video_properties(Texture::CData *cdata,
192 const OpenCVTexture::VideoStream &stream,
193 int num_components,
int z,
195 double frame_rate = 0.0f;
198 if (stream.is_from_file()) {
199 frame_rate = cvGetCaptureProperty(stream._capture, CV_CAP_PROP_FPS);
200 num_frames = (int)cvGetCaptureProperty(stream._capture, CV_CAP_PROP_FRAME_COUNT);
201 if (vision_cat.is_debug()) {
203 <<
"Loaded " << stream._filename <<
", " << num_frames <<
" frames at "
204 << frame_rate <<
" fps\n";
209 if (vision_cat.is_debug()) {
211 <<
"Loaded camera stream\n";
215 int width = (int)cvGetCaptureProperty(stream._capture, CV_CAP_PROP_FRAME_WIDTH);
216 int height = (int)cvGetCaptureProperty(stream._capture, CV_CAP_PROP_FRAME_HEIGHT);
220 do_adjust_this_size(cdata, x_size, y_size, get_name(),
true);
222 if (vision_cat.is_debug()) {
224 <<
"Video stream is " << width <<
" by " << height
225 <<
" pixels; fitting in texture " << x_size <<
" by "
226 << y_size <<
" texels.\n";
229 if (!do_reconsider_image_properties(cdata, x_size, y_size, num_components,
230 T_unsigned_byte, z, options)) {
234 if (cdata->_loaded_from_image &&
235 (get_video_width() != width || get_video_height() != height ||
236 get_num_frames() != num_frames || get_frame_rate() != frame_rate)) {
238 <<
"Video properties have changed for texture " << get_name()
239 <<
" level " << z <<
".\n";
243 set_frame_rate(frame_rate);
244 set_num_frames(num_frames);
245 set_video_size(width, height);
259 return new OpenCVTexture;
266 do_update_frame(Texture::CData *cdata,
int frame) {
267 int max_z = std::max(cdata->_z_size, (
int)_pages.size());
268 for (
int z = 0; z < max_z; ++z) {
269 do_update_frame(cdata, frame, z);
277 do_update_frame(Texture::CData *cdata,
int frame,
int z) {
278 if (vision_cat.is_spam()) {
280 <<
"Updating OpenCVTexture page " << z <<
"\n";
283 VideoPage &page = _pages[z];
284 if (page._color.is_valid() || page._alpha.is_valid()) {
285 do_modify_ram_image(cdata);
286 ++(cdata->_image_modified);
288 int dest_x_pitch = cdata->_num_components * cdata->_component_width;
289 int dest_y_pitch = cdata->_x_size * dest_x_pitch;
291 if (page._color.is_valid()) {
292 nassertv(get_num_components() >= 3 && get_component_width() == 1);
294 const unsigned char *r, *g, *b;
295 int x_pitch, y_pitch;
296 if (page._color.get_frame_data(frame, r, g, b, x_pitch, y_pitch)) {
297 nassertv(get_video_width() <= cdata->_x_size && get_video_height() <= cdata->_y_size);
298 nassertv(!cdata->_ram_images.empty())
299 unsigned
char *dest = cdata->_ram_images[0]._image.p() + do_get_expected_ram_page_size(cdata) * z;
301 if (cdata->_num_components == 3 && x_pitch == 3) {
303 int copy_bytes = get_video_width() * dest_x_pitch;
304 nassertv(copy_bytes <= dest_y_pitch && copy_bytes <= abs(y_pitch));
306 for (
int y = 0; y < get_video_height(); ++y) {
307 memcpy(dest, r, copy_bytes);
308 dest += dest_y_pitch;
316 for (
int y = 0; y < get_video_height(); ++y) {
319 for (
int x = 0; x < get_video_width(); ++x) {
321 dest[dx + 1] = g[sx];
322 dest[dx + 2] = b[sx];
326 dest += dest_y_pitch;
334 if (page._alpha.is_valid()) {
335 nassertv(get_component_width() == 1);
337 const unsigned char *source[3];
338 int x_pitch, y_pitch;
339 if (page._alpha.get_frame_data(frame, source[0], source[1], source[2],
341 nassertv(get_video_width() <= cdata->_x_size && get_video_height() <= cdata->_y_size);
342 nassertv(!cdata->_ram_images.empty())
343 unsigned
char *dest = cdata->_ram_images[0]._image.p() + do_get_expected_ram_page_size(cdata) * z;
348 const
unsigned char *sch = source[0];
349 if (cdata->_alpha_file_channel >= 1 && cdata->_alpha_file_channel <= 3) {
350 sch = source[cdata->_alpha_file_channel - 1];
353 for (
int y = 0; y < get_video_height(); ++y) {
356 int dx = (cdata->_num_components - 1) * cdata->_component_width;
358 for (
int x = 0; x < get_video_width(); ++x) {
363 dest += dest_y_pitch;
375 do_read_one(Texture::CData *cdata,
377 int z,
int n,
int primary_file_num_channels,
int alpha_file_channel,
380 if (record !=
nullptr) {
384 nassertr(n == 0,
false);
385 nassertr(z >= 0 && z < cdata->_z_size,
false);
387 VideoPage &page = do_modify_page(cdata, z);
388 if (!page._color.read(fullpath)) {
390 <<
"OpenCV couldn't read " << fullpath <<
" as video.\n";
393 if (!alpha_fullpath.empty()) {
394 if (!page._alpha.read(alpha_fullpath)) {
396 <<
"OpenCV couldn't read " << alpha_fullpath <<
" as video.\n";
407 if (cdata->_filename.empty()) {
408 cdata->_filename = fullpath;
409 cdata->_alpha_filename = alpha_fullpath;
412 cdata->_fullpath = fullpath;
413 cdata->_alpha_fullpath = alpha_fullpath;
416 cdata->_primary_file_num_channels = 3;
417 cdata->_alpha_file_channel = 0;
419 if (alpha_fullpath.empty()) {
421 if (!do_reconsider_video_properties(cdata, page._color, 3, z, options)) {
428 cdata->_alpha_file_channel = alpha_file_channel;
430 if (!do_reconsider_video_properties(cdata, page._color, 4, z, options)) {
436 if (!do_reconsider_video_properties(cdata, page._alpha, 4, z, options)) {
443 set_loaded_from_image();
444 clear_current_frame();
445 do_update_frame(cdata, 0);
454 do_load_one(Texture::CData *cdata,
455 const PNMImage &pnmimage,
const std::string &name,
457 if (z <= (
int)_pages.size()) {
458 VideoPage &page = do_modify_page(cdata, z);
463 return Texture::do_load_one(cdata, pnmimage, name, z, n, options);
470 register_with_read_factory() {
486 OpenCVTexture::VideoStream::
497 OpenCVTexture::VideoStream::
498 VideoStream(
const OpenCVTexture::VideoStream ©) :
504 if (copy.is_valid()) {
505 if (copy.is_from_file()) {
506 read(copy._filename);
508 from_camera(copy._camera_index);
516 OpenCVTexture::VideoStream::
536 bool OpenCVTexture::VideoStream::
537 get_frame_data(
int frame,
538 const unsigned char *&r,
539 const unsigned char *&g,
540 const unsigned char *&b,
541 int &x_pitch,
int &y_pitch) {
542 nassertr(is_valid(),
false);
544 if (is_from_file() && _next_frame != frame) {
545 cvSetCaptureProperty(_capture, CV_CAP_PROP_POS_FRAMES, frame);
548 _next_frame = frame + 1;
549 IplImage *image = cvQueryFrame(_capture);
550 if (image ==
nullptr) {
554 r = (
const unsigned char *)image->imageData;
558 y_pitch = image->widthStep;
560 if (image->dataOrder == 1) {
564 g = r + image->height * y_pitch;
565 b = g + image->height * y_pitch;
568 if (image->origin == 0) {
573 r += (image->height - 1) * y_pitch;
574 g += (image->height - 1) * y_pitch;
575 b += (image->height - 1) * y_pitch;
586 bool OpenCVTexture::VideoStream::
591 _capture = cvCaptureFromFile(os_specific.c_str());
592 if (_capture ==
nullptr) {
595 _filename = filename;
603 bool OpenCVTexture::VideoStream::
604 from_camera(
int camera_index) {
607 _capture = cvCaptureFromCAM(camera_index);
608 if (_capture ==
nullptr) {
611 _camera_index = camera_index;
618 void OpenCVTexture::VideoStream::
620 if (_capture !=
nullptr) {
621 cvReleaseCapture(&_capture);
629 #endif // HAVE_OPENCV