Credit Andrew - updating patches for FFmpeg 7.0 as needed since 6.1, now at 7.0,...
[goodguy/cinelerra.git] / cinelerra-5.1 / plugins / flip / flip.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  * Copyright (C) 2003-2016 Cinelerra CV contributors
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22
23 #include "clip.h"
24 #include "bccmodels.h"
25 #include "bchash.h"
26 #include "filexml.h"
27 #include "flip.h"
28 #include "flipwindow.h"
29 #include "language.h"
30
31 #include <stdint.h>
32 #include <string.h>
33
34 REGISTER_PLUGIN(FlipMain)
35
36
37
38
39
40
41 FlipConfig::FlipConfig()
42 {
43         flip_horizontal = 0;
44         flip_vertical = 0;
45 }
46
47 void FlipConfig::copy_from(FlipConfig &that)
48 {
49         flip_horizontal = that.flip_horizontal;
50         flip_vertical = that.flip_vertical;
51 }
52
53 int FlipConfig::equivalent(FlipConfig &that)
54 {
55         return flip_horizontal == that.flip_horizontal &&
56                 flip_vertical == that.flip_vertical;
57 }
58
59 void FlipConfig::interpolate(FlipConfig &prev,
60         FlipConfig &next,
61         long prev_frame,
62         long next_frame,
63         long current_frame)
64 {
65         this->flip_horizontal = prev.flip_horizontal;
66         this->flip_vertical = prev.flip_vertical;
67 }
68
69
70
71
72
73
74
75
76
77
78 FlipMain::FlipMain(PluginServer *server)
79  : PluginVClient(server)
80 {
81
82 }
83
84 FlipMain::~FlipMain()
85 {
86
87 }
88
89 const char* FlipMain::plugin_title() { return N_("Flip"); }
90 int FlipMain::is_realtime() { return 1; }
91
92
93 #define SWAP_PIXELS(type, components, in, out) \
94 { \
95         type temp = in[0]; \
96         in[0] = out[0]; \
97         out[0] = temp; \
98  \
99         temp = in[1]; \
100         in[1] = out[1]; \
101         out[1] = temp; \
102  \
103         temp = in[2]; \
104         in[2] = out[2]; \
105         out[2] = temp; \
106  \
107         if(components == 4) \
108         { \
109                 temp = in[3]; \
110                 in[3] = out[3]; \
111                 out[3] = temp; \
112         } \
113 }
114
115 #define FLIP_MACRO(type, components) \
116 { \
117         type **input_rows, **output_rows; \
118         type *input_row, *output_row; \
119         input_rows = ((type**)frame->get_rows()); \
120         output_rows = ((type**)frame->get_rows()); \
121  \
122         if(config.flip_vertical) \
123         { \
124                 for(i = 0, j = h - 1; i < h / 2; i++, j--) \
125                 { \
126                         input_row = input_rows[i]; \
127                         output_row = output_rows[j]; \
128                         for(k = 0; k < w; k++) \
129                         { \
130                                 SWAP_PIXELS(type, components, output_row, input_row); \
131                                 output_row += components; \
132                                 input_row += components; \
133                         } \
134                 } \
135         } \
136  \
137         if(config.flip_horizontal) \
138         { \
139                 for(i = 0; i < h; i++) \
140                 { \
141                         input_row = input_rows[i]; \
142                         output_row = output_rows[i] + (w - 1) * components; \
143                         for(k = 0; k < w / 2; k++) \
144                         { \
145                                 SWAP_PIXELS(type, components, output_row, input_row); \
146                                 input_row += components; \
147                                 output_row -= components; \
148                         } \
149                 } \
150         } \
151 }
152
153 int FlipMain::process_buffer(VFrame *frame,
154                 int64_t start_position,
155                 double frame_rate)
156 {
157         int i, j, k;
158         int w = frame->get_w();
159         int h = frame->get_h();
160         int colormodel = frame->get_color_model();
161
162         load_configuration();
163
164         read_frame(frame,
165                 0,
166                 get_source_position(),
167                 get_framerate(),
168                 get_use_opengl());
169
170
171
172         if(get_use_opengl())
173         {
174                 if(config.flip_vertical || config.flip_horizontal)
175                         return run_opengl();
176                 else
177                         return 0;
178         }
179
180         switch(colormodel)
181         {
182                 case BC_RGB888:
183                 case BC_YUV888:
184                         FLIP_MACRO(unsigned char, 3);
185                         break;
186                 case BC_RGB_FLOAT:
187                         FLIP_MACRO(float, 3);
188                         break;
189                 case BC_RGB161616:
190                 case BC_YUV161616:
191                         FLIP_MACRO(uint16_t, 3);
192                         break;
193                 case BC_RGBA8888:
194                 case BC_YUVA8888:
195                         FLIP_MACRO(unsigned char, 4);
196                         break;
197                 case BC_RGBA_FLOAT:
198                         FLIP_MACRO(float, 4);
199                         break;
200                 case BC_RGBA16161616:
201                 case BC_YUVA16161616:
202                         FLIP_MACRO(uint16_t, 4);
203                         break;
204         }
205         return 0;
206 }
207
208
209 NEW_WINDOW_MACRO(FlipMain, FlipWindow)
210 LOAD_CONFIGURATION_MACRO(FlipMain, FlipConfig)
211
212 void FlipMain::update_gui()
213 {
214         if(thread)
215         {
216                 load_configuration();
217                 thread->window->lock_window();
218                 ((FlipWindow*)thread->window)->flip_vertical->update((int)config.flip_vertical);
219                 ((FlipWindow*)thread->window)->flip_horizontal->update((int)config.flip_horizontal);
220                 thread->window->unlock_window();
221         }
222 }
223
224 void FlipMain::save_data(KeyFrame *keyframe)
225 {
226         FileXML output;
227
228 // cause data to be stored directly in text
229         output.set_shared_output(keyframe->xbuf);
230         output.tag.set_title("FLIP");
231         output.append_tag();
232         if(config.flip_vertical)
233         {
234                 output.tag.set_title("VERTICAL");
235                 output.append_tag();
236                 output.tag.set_title("/VERTICAL");
237                 output.append_tag();
238         }
239
240         if(config.flip_horizontal)
241         {
242                 output.tag.set_title("HORIZONTAL");
243                 output.append_tag();
244                 output.tag.set_title("/HORIZONTAL");
245                 output.append_tag();
246         }
247         output.tag.set_title("/FLIP");
248         output.append_tag();
249         output.append_newline();
250         output.terminate_string();
251 // data is now in *text
252 }
253
254 void FlipMain::read_data(KeyFrame *keyframe)
255 {
256         FileXML input;
257
258         input.set_shared_input(keyframe->xbuf);
259
260         int result = 0;
261         config.flip_vertical = config.flip_horizontal = 0;
262
263         while(!result)
264         {
265                 result = input.read_tag();
266
267                 if(!result)
268                 {
269                         if(input.tag.title_is("VERTICAL"))
270                         {
271                                 config.flip_vertical = 1;
272                         }
273                         else
274                         if(input.tag.title_is("HORIZONTAL"))
275                         {
276                                 config.flip_horizontal = 1;
277                         }
278                 }
279         }
280 }
281
282
283 int FlipMain::handle_opengl()
284 {
285 #ifdef HAVE_GL
286         get_output()->to_texture();
287         get_output()->enable_opengl();
288         get_output()->init_screen();
289         get_output()->bind_texture(0);
290
291         if(config.flip_vertical && !config.flip_horizontal)
292         {
293                 get_output()->draw_texture(0,
294                         0,
295                         get_output()->get_w(),
296                         get_output()->get_h(),
297                         0,
298                         get_output()->get_h(),
299                         get_output()->get_w(),
300                         0);
301         }
302
303         if(config.flip_horizontal && !config.flip_vertical)
304         {
305                 get_output()->draw_texture(0,
306                         0,
307                         get_output()->get_w(),
308                         get_output()->get_h(),
309                         get_output()->get_w(),
310                         0,
311                         0,
312                         get_output()->get_h());
313         }
314
315         if(config.flip_vertical && config.flip_horizontal)
316         {
317                 get_output()->draw_texture(0,
318                         0,
319                         get_output()->get_w(),
320                         get_output()->get_h(),
321                         get_output()->get_w(),
322                         get_output()->get_h(),
323                         0,
324                         0);
325         }
326
327         get_output()->set_opengl_state(VFrame::SCREEN);
328 #endif
329         return 0;
330 }
331
332
333