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