merged hv7 mod
[goodguy/history.git] / cinelerra-5.1 / plugins / motion-hv / motioncache-hv.C
diff --git a/cinelerra-5.1/plugins/motion-hv/motioncache-hv.C b/cinelerra-5.1/plugins/motion-hv/motioncache-hv.C
new file mode 100644 (file)
index 0000000..98722de
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * CINELERRA
+ * Copyright (C) 2016 Adam Williams <broadcast at earthling dot net>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+
+
+// store previously scaled images here for operations 
+// with multiple motion scans on the same frame.
+
+
+#include "bcsignals.h"
+#include "clip.h"
+#include "motioncache-hv.h"
+#include "mutex.h"
+#include <stdint.h>
+#include "vframe.h"
+
+
+MotionHVCacheItem::MotionHVCacheItem()
+{
+}
+
+MotionHVCacheItem::~MotionHVCacheItem()
+{
+//printf("MotionHVCacheItem::~MotionHVCacheItem %d image=%p\n", __LINE__, image);
+       if(image)
+       {
+               delete image;
+       }
+}
+
+
+
+MotionHVCache::MotionHVCache()
+{
+       lock = new Mutex("MotionHVCache::lock");
+}
+
+MotionHVCache::~MotionHVCache()
+{
+//printf("MotionHVCache::~MotionHVCache %d this=%p\n", __LINE__, this);
+
+       delete lock;
+       clear();
+}
+
+void MotionHVCache::clear()
+{
+       images.remove_all_objects();
+}
+
+
+
+#define DOWNSAMPLE(type, temp_type, components, max) \
+{ \
+       temp_type r; \
+       temp_type g; \
+       temp_type b; \
+       temp_type a; \
+       type **in_rows = (type**)src->get_rows(); \
+       type **out_rows = (type**)dst->get_rows(); \
+ \
+       for(int i = 0; i < h; i += downsample) \
+       { \
+               int y1 = MAX(i, 0); \
+               int y2 = MIN(i + downsample, h); \
+ \
+ \
+               for(int j = 0; \
+                       j < w; \
+                       j += downsample) \
+               { \
+                       int x1 = MAX(j, 0); \
+                       int x2 = MIN(j + downsample, w); \
+ \
+                       temp_type scale = (x2 - x1) * (y2 - y1); \
+                       if(x2 > x1 && y2 > y1) \
+                       { \
+ \
+/* Read in values */ \
+                               r = 0; \
+                               g = 0; \
+                               b = 0; \
+                               if(components == 4) a = 0; \
+ \
+                               for(int k = y1; k < y2; k++) \
+                               { \
+                                       type *row = in_rows[k] + x1 * components; \
+                                       for(int l = x1; l < x2; l++) \
+                                       { \
+                                               r += *row++; \
+                                               g += *row++; \
+                                               b += *row++; \
+                                               if(components == 4) a += *row++; \
+                                       } \
+                               } \
+ \
+/* Write average */ \
+                               r /= scale; \
+                               g /= scale; \
+                               b /= scale; \
+                               if(components == 4) a /= scale; \
+ \
+                               type *row = out_rows[y1 / downsample] + \
+                                       x1 / downsample * components; \
+                               *row++ = r; \
+                               *row++ = g; \
+                               *row++ = b; \
+                               if(components == 4) *row++ = a; \
+                       } \
+               } \
+/*printf("DOWNSAMPLE 3 %d\n", i);*/ \
+       } \
+}
+
+
+
+
+void MotionHVCache::downsample_frame(VFrame *dst, 
+       VFrame *src, 
+       int downsample)
+{
+       int h = src->get_h();
+       int w = src->get_w();
+
+//PRINT_TRACE
+//printf("downsample=%d w=%d h=%d dst=%d %d\n", downsample, w, h, dst->get_w(), dst->get_h());
+       switch(src->get_color_model())
+       {
+               case BC_RGB888:
+                       DOWNSAMPLE(uint8_t, int64_t, 3, 0xff)
+                       break;
+               case BC_RGB_FLOAT:
+                       DOWNSAMPLE(float, float, 3, 1.0)
+                       break;
+               case BC_RGBA8888:
+                       DOWNSAMPLE(uint8_t, int64_t, 4, 0xff)
+                       break;
+               case BC_RGBA_FLOAT:
+                       DOWNSAMPLE(float, float, 4, 1.0)
+                       break;
+               case BC_YUV888:
+                       DOWNSAMPLE(uint8_t, int64_t, 3, 0xff)
+                       break;
+               case BC_YUVA8888:
+                       DOWNSAMPLE(uint8_t, int64_t, 4, 0xff)
+                       break;
+       }
+//PRINT_TRACE
+}
+
+VFrame* MotionHVCache::get_image(int ratio, 
+       int is_previous,
+       int downsampled_w,
+       int downsampled_h,
+       VFrame *src)
+{
+       lock->lock("MotionHVCache::get_image 1");
+       
+       for(int i = 0; i < images.size(); i++)
+       {
+               if(images.get(i)->ratio == ratio &&
+                       images.get(i)->is_previous == is_previous)
+               {
+                       VFrame *result = images.get(i)->image;
+                       lock->unlock();
+                       return result;
+               }
+       }
+
+
+//PRINT_TRACE
+       VFrame *result = new VFrame();
+       result->set_use_shm(0);
+       result->reallocate(0, 
+               -1,
+               0,
+               0,
+               0,
+               downsampled_w + 1, 
+               downsampled_h + 1, 
+               src->get_color_model(), 
+               -1);
+       downsample_frame(result, 
+               src, 
+               ratio);
+       
+       
+       MotionHVCacheItem *item = new MotionHVCacheItem();
+       item->image = result;
+       item->is_previous = is_previous;
+       item->ratio = ratio;
+       images.append(item);
+
+       lock->unlock();
+       
+       return result;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+