From 9861d44f82f5d36ff9662325c09756302c177253 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 15 Jan 2009 18:34:58 +0000 Subject: [PATCH] Changes to get OpenCV webcam working --- panda/src/gobj/videoTexture.h | 4 +- panda/src/grutil/openCVTexture.I | 29 +++++++ panda/src/grutil/openCVTexture.cxx | 123 ++++++++++++++++------------- panda/src/grutil/openCVTexture.h | 2 + 4 files changed, 100 insertions(+), 58 deletions(-) diff --git a/panda/src/gobj/videoTexture.h b/panda/src/gobj/videoTexture.h index e34f57fb3c..680d8bf943 100644 --- a/panda/src/gobj/videoTexture.h +++ b/panda/src/gobj/videoTexture.h @@ -52,11 +52,11 @@ protected: virtual void reconsider_dirty(); virtual void do_reload_ram_image(); - INLINE void consider_update(); + virtual INLINE void consider_update(); INLINE void clear_current_frame(); virtual void update_frame(int frame)=0; -private: +protected: int _video_width; int _video_height; int _last_frame_update; diff --git a/panda/src/grutil/openCVTexture.I b/panda/src/grutil/openCVTexture.I index 583da35d9a..57b61efa75 100644 --- a/panda/src/grutil/openCVTexture.I +++ b/panda/src/grutil/openCVTexture.I @@ -64,3 +64,32 @@ VideoPage(const OpenCVTexture::VideoPage ©) : INLINE OpenCVTexture::VideoPage:: ~VideoPage() { } + +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::consider_update +// Access: Protected +// Description: Calls update_frame() if the current frame has +// changed. +//////////////////////////////////////////////////////////////////// +INLINE void OpenCVTexture:: +consider_update() { + int this_frame = ClockObject::get_global_clock()->get_frame_count(); + if (this_frame != _last_frame_update) { + int frame = get_frame(); + if (_current_frame != frame) { + update_frame(frame); + _current_frame = frame; + } else { + // Loop through the pages to see if there's any camera stream to update. + int max_z = max(_z_size, (int)_pages.size()); + for (int z = 0; z < max_z; ++z) { + VideoPage &page = _pages[z]; + if (!page._color.is_from_file() || !page._alpha.is_from_file()) { + update_frame(frame, z); + } + } + } + _last_frame_update = this_frame; + } +} + diff --git a/panda/src/grutil/openCVTexture.cxx b/panda/src/grutil/openCVTexture.cxx index aaaf917e9a..3a7d49d8fe 100644 --- a/panda/src/grutil/openCVTexture.cxx +++ b/panda/src/grutil/openCVTexture.cxx @@ -224,71 +224,55 @@ make_texture() { //////////////////////////////////////////////////////////////////// void OpenCVTexture:: update_frame(int frame) { - grutil_cat.spam() << "OpenCVTexture::update_frame called\n"; int max_z = max(_z_size, (int)_pages.size()); for (int z = 0; z < max_z; ++z) { - VideoPage &page = _pages[z]; - if (page._color.is_valid() || page._alpha.is_valid()) { - modify_ram_image(); - } - if (page._color.is_valid()) { - nassertv(get_num_components() >= 3 && get_component_width() == 1); + update_frame(frame, z); + } +} - const unsigned char *source = page._color.get_frame_data(frame); - if (source != NULL) { - nassertv(get_video_width() <= _x_size && get_video_height() <= _y_size); - unsigned char *dest = _ram_images[0]._image.p() + get_expected_ram_page_size() * z; +//////////////////////////////////////////////////////////////////// +// Function: OpenCVTexture::update_frame +// Access: Protected, Virtual +// Description: This variant of update_frame updates the +// indicated page only. +//////////////////////////////////////////////////////////////////// +void OpenCVTexture:: +update_frame(int frame, int z) { + grutil_cat.spam() << "Updating OpenCVTexture page " << z << "\n"; + VideoPage &page = _pages[z]; + if (page._color.is_valid() || page._alpha.is_valid()) { + modify_ram_image(); + } + if (page._color.is_valid()) { + nassertv(get_num_components() >= 3 && get_component_width() == 1); - int dest_row_width = (_x_size * _num_components * _component_width); - int source_row_width = get_video_width() * 3; + const unsigned char *source = page._color.get_frame_data(frame); + if (source != NULL) { + nassertv(get_video_width() <= _x_size && get_video_height() <= _y_size); + unsigned char *dest = _ram_images[0]._image.p() + get_expected_ram_page_size() * z; - if (get_num_components() == 3) { - // The easy case--copy the whole thing in, row by row. - for (int y = 0; y < get_video_height(); ++y) { - memcpy(dest, source, source_row_width); - dest += dest_row_width; - source += source_row_width; - } + int dest_row_width = (_x_size * _num_components * _component_width); + int source_row_width = get_video_width() * 3; - } else { - // The harder case--interleave the color in with the alpha, - // pixel by pixel. - nassertv(get_num_components() == 4); - for (int y = 0; y < get_video_height(); ++y) { - int dx = 0; - int sx = 0; - for (int x = 0; x < get_video_width(); ++x) { - dest[dx] = source[sx]; - dest[dx + 1] = source[sx + 1]; - dest[dx + 2] = source[sx + 2]; - dx += 4; - sx += 3; - } - dest += dest_row_width; - source += source_row_width; - } - } - } - } - if (page._alpha.is_valid()) { - nassertv(get_num_components() == 4 && get_component_width() == 1); - - const unsigned char *source = page._alpha.get_frame_data(frame); - if (source != NULL) { - nassertv(get_video_width() <= _x_size && get_video_height() <= _y_size); - unsigned char *dest = _ram_images[0]._image.p() + get_expected_ram_page_size() * z; - - int dest_row_width = (_x_size * _num_components * _component_width); - int source_row_width = get_video_width() * 3; - - // Interleave the alpha in with the color, pixel by pixel. - // Even though the alpha will probably be a grayscale video, - // the OpenCV library presents it as RGB. + if (get_num_components() == 3) { + // The easy case--copy the whole thing in, row by row. for (int y = 0; y < get_video_height(); ++y) { - int dx = 3; - int sx = _alpha_file_channel; + memcpy(dest, source, source_row_width); + dest += dest_row_width; + source += source_row_width; + } + + } else { + // The harder case--interleave the color in with the alpha, + // pixel by pixel. + nassertv(get_num_components() == 4); + for (int y = 0; y < get_video_height(); ++y) { + int dx = 0; + int sx = 0; for (int x = 0; x < get_video_width(); ++x) { dest[dx] = source[sx]; + dest[dx + 1] = source[sx + 1]; + dest[dx + 2] = source[sx + 2]; dx += 4; sx += 3; } @@ -298,6 +282,33 @@ update_frame(int frame) { } } } + if (page._alpha.is_valid()) { + nassertv(get_num_components() == 4 && get_component_width() == 1); + + const unsigned char *source = page._alpha.get_frame_data(frame); + if (source != NULL) { + nassertv(get_video_width() <= _x_size && get_video_height() <= _y_size); + unsigned char *dest = _ram_images[0]._image.p() + get_expected_ram_page_size() * z; + + int dest_row_width = (_x_size * _num_components * _component_width); + int source_row_width = get_video_width() * 3; + + // Interleave the alpha in with the color, pixel by pixel. + // Even though the alpha will probably be a grayscale video, + // the OpenCV library presents it as RGB. + for (int y = 0; y < get_video_height(); ++y) { + int dx = 3; + int sx = _alpha_file_channel; + for (int x = 0; x < get_video_width(); ++x) { + dest[dx] = source[sx]; + dx += 4; + sx += 3; + } + dest += dest_row_width; + source += source_row_width; + } + } + } } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/grutil/openCVTexture.h b/panda/src/grutil/openCVTexture.h index f501cb2256..40de158a30 100644 --- a/panda/src/grutil/openCVTexture.h +++ b/panda/src/grutil/openCVTexture.h @@ -46,10 +46,12 @@ public: static PT(Texture) make_texture(); protected: + virtual INLINE void consider_update(); virtual PT(Texture) do_make_copy(); void do_assign(const OpenCVTexture ©); virtual void update_frame(int frame); + virtual void update_frame(int frame, int z); virtual bool do_read_one(const Filename &fullpath, const Filename &alpha_fullpath, int z, int n, int primary_file_num_channels, int alpha_file_channel,