a7d969af05b95be1e1c0ddb75db2d08fbf1454e2
[blender.git] / extern / libmv / intern / frame_accessor.cc
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2014 Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation,
22  *                 Sergey Sharybin
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 #include "intern/frame_accessor.h"
28 #include "intern/image.h"
29 #include "intern/utildefines.h"
30 #include "libmv/autotrack/frame_accessor.h"
31 #include "libmv/autotrack/region.h"
32 #include "libmv/image/image.h"
33
34 namespace {
35
36 using libmv::FloatImage;
37 using mv::FrameAccessor;
38 using mv::Region;
39
40 struct LibmvFrameAccessor : public FrameAccessor {
41   LibmvFrameAccessor(libmv_FrameAccessorUserData* user_data,
42                      libmv_GetImageCallback get_image_callback,
43                      libmv_ReleaseImageCallback release_image_callback)
44     : user_data_(user_data),
45       get_image_callback_(get_image_callback),
46       release_image_callback_(release_image_callback) { }
47
48   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
62   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
70   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
105   void ReleaseImage(Key cache_key) {
106     release_image_callback_(cache_key);
107   }
108
109   bool GetClipDimensions(int clip, int *width, int *height) {
110     return false;
111   }
112
113   int NumClips() {
114     return 1;
115   }
116
117   int NumFrames(int clip) {
118     return 0;
119   }
120
121   libmv_FrameAccessorUserData* user_data_;
122   libmv_GetImageCallback get_image_callback_;
123   libmv_ReleaseImageCallback release_image_callback_;
124 };
125
126 }  // namespace
127
128 libmv_FrameAccessor* libmv_FrameAccessorNew(
129     libmv_FrameAccessorUserData* user_data,
130     libmv_GetImageCallback get_image_callback,
131     libmv_ReleaseImageCallback release_image_callback) {
132   return (libmv_FrameAccessor*) LIBMV_OBJECT_NEW(LibmvFrameAccessor,
133                                                  user_data,
134                                                  get_image_callback,
135                                                  release_image_callback);
136 }
137
138 void libmv_FrameAccessorDestroy(libmv_FrameAccessor* frame_accessor) {
139   LIBMV_OBJECT_DELETE(frame_accessor, LibmvFrameAccessor);
140 }
141
142 int64_t libmv_frameAccessorgetTransformKey(const libmv_FrameTransform *transform) {
143   return ((FrameAccessor::Transform*) transform)->key();
144 }
145
146 void libmv_frameAccessorgetTransformRun(const libmv_FrameTransform *transform,
147                                         const libmv_FloatImage *input_image,
148                                         libmv_FloatImage *output_image) {
149   const FloatImage input(input_image->buffer,
150                          input_image->width,
151                          input_image->height,
152                          input_image->channels);
153
154   FloatImage output;
155   ((FrameAccessor::Transform*) transform)->run(input,
156                                                &output);
157
158   int num_pixels = output.Width() *output.Height() * output.Depth();
159   output_image->buffer = new float[num_pixels];
160   memcpy(output_image->buffer, output.Data(), num_pixels * sizeof(float));
161   output_image->width = output.Width();
162   output_image->height = output.Height();
163   output_image->channels = output.Depth();
164 }