1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2014 Blender Foundation.
17  * All rights reserved.
18  */
19 
20 #include "intern/frame_accessor.h"
21 #include "intern/image.h"
22 #include "intern/utildefines.h"
23 #include "libmv/autotrack/frame_accessor.h"
24 #include "libmv/autotrack/region.h"
25 #include "libmv/image/image.h"
26 
27 namespace {
28 
29 using libmv::FloatImage;
30 using mv::FrameAccessor;
31 using mv::Region;
32 
33 struct LibmvFrameAccessor : public FrameAccessor {
LibmvFrameAccessor__anonfcb9564d0111::LibmvFrameAccessor34   LibmvFrameAccessor(libmv_FrameAccessorUserData* user_data,
35                      libmv_GetImageCallback get_image_callback,
36                      libmv_ReleaseImageCallback release_image_callback,
37                      libmv_GetMaskForTrackCallback get_mask_for_track_callback,
38                      libmv_ReleaseMaskCallback release_mask_callback)
39     : user_data_(user_data),
40       get_image_callback_(get_image_callback),
41       release_image_callback_(release_image_callback),
42       get_mask_for_track_callback_(get_mask_for_track_callback),
43       release_mask_callback_(release_mask_callback) { }
44 
~LibmvFrameAccessor__anonfcb9564d0111::LibmvFrameAccessor45   virtual ~LibmvFrameAccessor() {
46   }
47 
get_libmv_input_mode__anonfcb9564d0111::LibmvFrameAccessor48   libmv_InputMode get_libmv_input_mode(InputMode input_mode) {
49     switch (input_mode) {
50 #define CHECK_INPUT_MODE(mode) \
51       case mode: \
52         return LIBMV_IMAGE_MODE_ ## mode;
53       CHECK_INPUT_MODE(MONO)
54       CHECK_INPUT_MODE(RGBA)
55 #undef CHECK_INPUT_MODE
56     }
57     assert(!"unknown input mode passed from Libmv.");
58     // TODO(sergey): Proper error handling here in the future.
59     return LIBMV_IMAGE_MODE_MONO;
60   }
61 
get_libmv_region__anonfcb9564d0111::LibmvFrameAccessor62   void get_libmv_region(const Region& region,
63                         libmv_Region* libmv_region) {
64     libmv_region->min[0] = region.min(0);
65     libmv_region->min[1] = region.min(1);
66     libmv_region->max[0] = region.max(0);
67     libmv_region->max[1] = region.max(1);
68   }
69 
GetImage__anonfcb9564d0111::LibmvFrameAccessor70   Key GetImage(int clip,
71                int frame,
72                InputMode input_mode,
73                int downscale,
74                const Region* region,
75                const Transform* transform,
76                FloatImage* destination) {
77     float *float_buffer;
78     int width, height, channels;
79     libmv_Region libmv_region;
80     if (region) {
81       get_libmv_region(*region, &libmv_region);
82     }
83     Key cache_key = get_image_callback_(user_data_,
84                                         clip,
85                                         frame,
86                                         get_libmv_input_mode(input_mode),
87                                         downscale,
88                                         region != NULL ? &libmv_region : NULL,
89                                         (libmv_FrameTransform*) transform,
90                                         &float_buffer,
91                                         &width,
92                                         &height,
93                                         &channels);
94 
95     // TODO(sergey): Dumb code for until we can set data directly.
96     FloatImage temp_image(float_buffer,
97                           height,
98                           width,
99                           channels);
100     destination->CopyFrom(temp_image);
101 
102     return cache_key;
103   }
104 
ReleaseImage__anonfcb9564d0111::LibmvFrameAccessor105   void ReleaseImage(Key cache_key) {
106     release_image_callback_(cache_key);
107   }
108 
GetMaskForTrack__anonfcb9564d0111::LibmvFrameAccessor109   Key GetMaskForTrack(int clip,
110                       int frame,
111                       int track,
112                       const Region* region,
113                       FloatImage* destination) {
114     float *float_buffer;
115     int width, height;
116     libmv_Region libmv_region;
117     if (region) {
118       get_libmv_region(*region, &libmv_region);
119     }
120     Key cache_key = get_mask_for_track_callback_(
121         user_data_,
122         clip,
123         frame,
124         track,
125         region != NULL ? &libmv_region : NULL,
126         &float_buffer,
127         &width,
128         &height);
129 
130     if (cache_key == NULL) {
131       // No mask for the given track.
132       return NULL;
133     }
134 
135     // TODO(sergey): Dumb code for until we can set data directly.
136     FloatImage temp_image(float_buffer,
137                           height,
138                           width,
139                           1);
140     destination->CopyFrom(temp_image);
141 
142     return cache_key;
143   }
144 
ReleaseMask__anonfcb9564d0111::LibmvFrameAccessor145   void ReleaseMask(Key key) {
146     release_mask_callback_(key);
147   }
148 
GetClipDimensions__anonfcb9564d0111::LibmvFrameAccessor149   bool GetClipDimensions(int /*clip*/, int * /*width*/, int * /*height*/) {
150     return false;
151   }
152 
NumClips__anonfcb9564d0111::LibmvFrameAccessor153   int NumClips() {
154     return 1;
155   }
156 
NumFrames__anonfcb9564d0111::LibmvFrameAccessor157   int NumFrames(int /*clip*/) {
158     return 0;
159   }
160 
161   libmv_FrameAccessorUserData* user_data_;
162   libmv_GetImageCallback get_image_callback_;
163   libmv_ReleaseImageCallback release_image_callback_;
164   libmv_GetMaskForTrackCallback get_mask_for_track_callback_;
165   libmv_ReleaseMaskCallback release_mask_callback_;
166 };
167 
168 }  // namespace
169 
libmv_FrameAccessorNew(libmv_FrameAccessorUserData * user_data,libmv_GetImageCallback get_image_callback,libmv_ReleaseImageCallback release_image_callback,libmv_GetMaskForTrackCallback get_mask_for_track_callback,libmv_ReleaseMaskCallback release_mask_callback)170 libmv_FrameAccessor* libmv_FrameAccessorNew(
171     libmv_FrameAccessorUserData* user_data,
172     libmv_GetImageCallback get_image_callback,
173     libmv_ReleaseImageCallback release_image_callback,
174     libmv_GetMaskForTrackCallback get_mask_for_track_callback,
175     libmv_ReleaseMaskCallback release_mask_callback) {
176   return (libmv_FrameAccessor*) LIBMV_OBJECT_NEW(LibmvFrameAccessor,
177                                                  user_data,
178                                                  get_image_callback,
179                                                  release_image_callback,
180                                                  get_mask_for_track_callback,
181                                                  release_mask_callback);
182 }
183 
libmv_FrameAccessorDestroy(libmv_FrameAccessor * frame_accessor)184 void libmv_FrameAccessorDestroy(libmv_FrameAccessor* frame_accessor) {
185   LIBMV_OBJECT_DELETE(frame_accessor, LibmvFrameAccessor);
186 }
187 
libmv_frameAccessorgetTransformKey(const libmv_FrameTransform * transform)188 int64_t libmv_frameAccessorgetTransformKey(const libmv_FrameTransform *transform) {
189   return ((FrameAccessor::Transform*) transform)->key();
190 }
191 
libmv_frameAccessorgetTransformRun(const libmv_FrameTransform * transform,const libmv_FloatImage * input_image,libmv_FloatImage * output_image)192 void libmv_frameAccessorgetTransformRun(const libmv_FrameTransform *transform,
193                                         const libmv_FloatImage *input_image,
194                                         libmv_FloatImage *output_image) {
195   const FloatImage input(input_image->buffer,
196                          input_image->height,
197                          input_image->width,
198                          input_image->channels);
199 
200   FloatImage output;
201   ((FrameAccessor::Transform*) transform)->run(input,
202                                                &output);
203 
204   int num_pixels = output.Width() *output.Height() * output.Depth();
205   output_image->buffer = new float[num_pixels];
206   memcpy(output_image->buffer, output.Data(), num_pixels * sizeof(float));
207   output_image->width = output.Width();
208   output_image->height = output.Height();
209   output_image->channels = output.Depth();
210 }
211