Credit Andrew for build mods and cineform format
[goodguy/cinelerra.git] / cinelerra-5.1 / plugins / motion-hv / motioncache-hv.C
1 /*
2  * CINELERRA
3  * Copyright (C) 2016 Adam Williams <broadcast at earthling dot net>
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  * 
19  */
20
21
22
23 // store previously scaled images here for operations 
24 // with multiple motion scans on the same frame.
25
26
27 #include "bcsignals.h"
28 #include "clip.h"
29 #include "motioncache-hv.h"
30 #include "mutex.h"
31 #include <stdint.h>
32 #include "vframe.h"
33
34
35 MotionHVCacheItem::MotionHVCacheItem()
36 {
37 }
38
39 MotionHVCacheItem::~MotionHVCacheItem()
40 {
41 //printf("MotionHVCacheItem::~MotionHVCacheItem %d image=%p\n", __LINE__, image);
42         if(image)
43         {
44                 delete image;
45         }
46 }
47
48
49
50 MotionHVCache::MotionHVCache()
51 {
52         lock = new Mutex("MotionHVCache::lock");
53 }
54
55 MotionHVCache::~MotionHVCache()
56 {
57 //printf("MotionHVCache::~MotionHVCache %d this=%p\n", __LINE__, this);
58
59         delete lock;
60         clear();
61 }
62
63 void MotionHVCache::clear()
64 {
65         images.remove_all_objects();
66 }
67
68
69
70 #define DOWNSAMPLE(type, temp_type, components, max) \
71 { \
72         temp_type r; \
73         temp_type g; \
74         temp_type b; \
75         temp_type a; \
76         type **in_rows = (type**)src->get_rows(); \
77         type **out_rows = (type**)dst->get_rows(); \
78  \
79         for(int i = 0; i < h; i += downsample) \
80         { \
81                 int y1 = MAX(i, 0); \
82                 int y2 = MIN(i + downsample, h); \
83  \
84  \
85                 for(int j = 0; \
86                         j < w; \
87                         j += downsample) \
88                 { \
89                         int x1 = MAX(j, 0); \
90                         int x2 = MIN(j + downsample, w); \
91  \
92                         temp_type scale = (x2 - x1) * (y2 - y1); \
93                         if(x2 > x1 && y2 > y1) \
94                         { \
95  \
96 /* Read in values */ \
97                                 r = 0; \
98                                 g = 0; \
99                                 b = 0; \
100                                 if(components == 4) a = 0; \
101  \
102                                 for(int k = y1; k < y2; k++) \
103                                 { \
104                                         type *row = in_rows[k] + x1 * components; \
105                                         for(int l = x1; l < x2; l++) \
106                                         { \
107                                                 r += *row++; \
108                                                 g += *row++; \
109                                                 b += *row++; \
110                                                 if(components == 4) a += *row++; \
111                                         } \
112                                 } \
113  \
114 /* Write average */ \
115                                 r /= scale; \
116                                 g /= scale; \
117                                 b /= scale; \
118                                 if(components == 4) a /= scale; \
119  \
120                                 type *row = out_rows[y1 / downsample] + \
121                                         x1 / downsample * components; \
122                                 *row++ = r; \
123                                 *row++ = g; \
124                                 *row++ = b; \
125                                 if(components == 4) *row++ = a; \
126                         } \
127                 } \
128 /*printf("DOWNSAMPLE 3 %d\n", i);*/ \
129         } \
130 }
131
132
133
134
135 void MotionHVCache::downsample_frame(VFrame *dst, 
136         VFrame *src, 
137         int downsample)
138 {
139         int h = src->get_h();
140         int w = src->get_w();
141
142 //PRINT_TRACE
143 //printf("downsample=%d w=%d h=%d dst=%d %d\n", downsample, w, h, dst->get_w(), dst->get_h());
144         switch(src->get_color_model())
145         {
146                 case BC_RGB888:
147                         DOWNSAMPLE(uint8_t, int64_t, 3, 0xff)
148                         break;
149                 case BC_RGB_FLOAT:
150                         DOWNSAMPLE(float, float, 3, 1.0)
151                         break;
152                 case BC_RGBA8888:
153                         DOWNSAMPLE(uint8_t, int64_t, 4, 0xff)
154                         break;
155                 case BC_RGBA_FLOAT:
156                         DOWNSAMPLE(float, float, 4, 1.0)
157                         break;
158                 case BC_YUV888:
159                         DOWNSAMPLE(uint8_t, int64_t, 3, 0xff)
160                         break;
161                 case BC_YUVA8888:
162                         DOWNSAMPLE(uint8_t, int64_t, 4, 0xff)
163                         break;
164         }
165 //PRINT_TRACE
166 }
167
168 VFrame* MotionHVCache::get_image(int ratio, 
169         int is_previous,
170         int downsampled_w,
171         int downsampled_h,
172         VFrame *src)
173 {
174         lock->lock("MotionHVCache::get_image 1");
175         
176         for(int i = 0; i < images.size(); i++)
177         {
178                 if(images.get(i)->ratio == ratio &&
179                         images.get(i)->is_previous == is_previous)
180                 {
181                         VFrame *result = images.get(i)->image;
182                         lock->unlock();
183                         return result;
184                 }
185         }
186
187
188 //PRINT_TRACE
189         VFrame *result =
190                 new VFrame(downsampled_w+1, downsampled_h+1, src->get_color_model(), 0);
191         downsample_frame(result, src, ratio);
192         
193         MotionHVCacheItem *item = new MotionHVCacheItem();
194         item->image = result;
195         item->is_previous = is_previous;
196         item->ratio = ratio;
197         images.append(item);
198
199         lock->unlock();
200         
201         return result;
202 }
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221