Merge CV, ver=5.1; ops/methods from HV, and interface from CV where possible
[goodguy/history.git] / cinelerra-5.0 / plugins / deinterlace-cv / deinterlace-cv.C
diff --git a/cinelerra-5.0/plugins/deinterlace-cv/deinterlace-cv.C b/cinelerra-5.0/plugins/deinterlace-cv/deinterlace-cv.C
deleted file mode 100644 (file)
index cdd2ccc..0000000
+++ /dev/null
@@ -1,658 +0,0 @@
-
-/*
- * CINELERRA
- * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- */
-
-#include "clip.h"
-#include "bchash.h"
-#include "deinterlace-cv.h"
-#include "deinterwindow-cv.h"
-#include "filexml.h"
-#include "keyframe.h"
-#include "language.h"
-#include "vframe.h"
-
-
-
-
-
-
-
-
-
-#include <stdint.h>
-#include <string.h>
-#include <math.h>
-
-REGISTER_PLUGIN(DeInterlaceMain)
-
-
-
-
-DeInterlaceConfig::DeInterlaceConfig()
-{
-       mode = DEINTERLACE_AVG;
-       dominance = 0;
-       adaptive = 1;
-       threshold = 40;
-}
-
-int DeInterlaceConfig::equivalent(DeInterlaceConfig &that)
-{
-       return mode == that.mode &&
-               dominance == that.dominance &&
-               adaptive == that.adaptive &&
-               threshold == that.threshold;
-}
-
-void DeInterlaceConfig::copy_from(DeInterlaceConfig &that)
-{
-       mode = that.mode;
-       dominance = that.dominance;
-       adaptive = that.adaptive;
-       threshold = that.threshold;
-}
-
-void DeInterlaceConfig::interpolate(DeInterlaceConfig &prev, 
-       DeInterlaceConfig &next, 
-       int64_t prev_frame, 
-       int64_t next_frame, 
-       int64_t current_frame)
-{
-       copy_from(prev);
-}
-
-
-
-
-DeInterlaceMain::DeInterlaceMain(PluginServer *server)
- : PluginVClient(server)
-{
-//     temp = 0;
-       temp_prevframe=0;
-}
-
-DeInterlaceMain::~DeInterlaceMain()
-{
-//     if(temp) delete temp;
-       if(temp_prevframe) delete temp_prevframe;
-}
-
-const char* DeInterlaceMain::plugin_title() { return _("Deinterlace-CV"); }
-int DeInterlaceMain::is_realtime() { return 1; }
-
-
-
-#define DEINTERLACE_TOP_MACRO(type, components, dominance) \
-{ \
-       int w = input->get_w(); \
-       int h = input->get_h(); \
- \
-       for(int i = 0; i < h - 1; i += 2) \
-       { \
-               type *input_row = (type*)input->get_rows()[dominance ? i + 1 : i]; \
-               type *output_row1 = (type*)output->get_rows()[i]; \
-               type *output_row2 = (type*)output->get_rows()[i + 1]; \
-               memcpy(output_row1, input_row, w * components * sizeof(type)); \
-               memcpy(output_row2, input_row, w * components * sizeof(type)); \
-       } \
-}
-
-#define DEINTERLACE_AVG_TOP_MACRO(type, temp_type, components, dominance) \
-{ \
-       int w = input->get_w(); \
-       int h = input->get_h(); \
-       changed_rows = 0; \
- \
-       type **in_rows = (type**)input->get_rows(); \
-       type **out_rows = (type**)temp->get_rows(); \
-       int max_h = h - 1; \
-       temp_type abs_diff = 0, total = 0; \
- \
-       for(int i = 0; i < max_h; i += 2) \
-       { \
-               int in_number1 = dominance ? i - 1 : i + 0; \
-               int in_number2 = dominance ? i + 1 : i + 2; \
-               int out_number1 = dominance ? i - 1 : i; \
-               int out_number2 = dominance ? i : i + 1; \
-               in_number1 = MAX(in_number1, 0); \
-               in_number2 = MIN(in_number2, max_h); \
-               out_number1 = MAX(out_number1, 0); \
-               out_number2 = MIN(out_number2, max_h); \
- \
-               type *input_row1 = in_rows[in_number1]; \
-               type *input_row2 = in_rows[in_number2]; \
-               type *input_row3 = in_rows[out_number2]; \
-               type *temp_row1 = out_rows[out_number1]; \
-               type *temp_row2 = out_rows[out_number2]; \
-               temp_type sum = 0; \
-               temp_type accum_r, accum_b, accum_g, accum_a; \
- \
-               memcpy(temp_row1, input_row1, w * components * sizeof(type)); \
-               for(int j = 0; j < w; j++) \
-               { \
-                       accum_r = (*input_row1++) + (*input_row2++); \
-                       accum_g = (*input_row1++) + (*input_row2++); \
-                       accum_b = (*input_row1++) + (*input_row2++); \
-                       if(components == 4) \
-                               accum_a = (*input_row1++) + (*input_row2++); \
-                       accum_r /= 2; \
-                       accum_g /= 2; \
-                       accum_b /= 2; \
-                       accum_a /= 2; \
- \
-                       total += *input_row3; \
-                       sum = ((temp_type)*input_row3++) - accum_r; \
-                       abs_diff += (sum < 0 ? -sum : sum); \
-                       *temp_row2++ = accum_r; \
- \
-                       total += *input_row3; \
-                       sum = ((temp_type)*input_row3++) - accum_g; \
-                       abs_diff += (sum < 0 ? -sum : sum); \
-                       *temp_row2++ = accum_g; \
- \
-                       total += *input_row3; \
-                       sum = ((temp_type)*input_row3++) - accum_b; \
-                       abs_diff += (sum < 0 ? -sum : sum); \
-                       *temp_row2++ = accum_b; \
- \
-                       if(components == 4) \
-                       { \
-                               total += *input_row3; \
-                               sum = ((temp_type)*input_row3++) - accum_a; \
-                               abs_diff += (sum < 0 ? -sum : sum); \
-                               *temp_row2++ = accum_a; \
-                       } \
-               } \
-       } \
- \
-       temp_type threshold = (temp_type)total * config.threshold / THRESHOLD_SCALAR; \
-/* printf("total=%lld threshold=%lld abs_diff=%lld\n", total, threshold, abs_diff); */ \
-       if(abs_diff > threshold || !config.adaptive) \
-       { \
-               output->copy_from(temp); \
-               changed_rows = 240; \
-       } \
-       else \
-       { \
-               output->copy_from(input); \
-               changed_rows = 0; \
-       } \
- \
-}
-
-#define DEINTERLACE_AVG_MACRO(type, temp_type, components) \
-{ \
-       int w = input->get_w(); \
-       int h = input->get_h(); \
- \
-       for(int i = 0; i < h - 1; i += 2) \
-       { \
-               type *input_row1 = (type*)input->get_rows()[i]; \
-               type *input_row2 = (type*)input->get_rows()[i + 1]; \
-               type *output_row1 = (type*)output->get_rows()[i]; \
-               type *output_row2 = (type*)output->get_rows()[i + 1]; \
-               type result; \
- \
-               for(int j = 0; j < w * components; j++) \
-               { \
-                       result = ((temp_type)input_row1[j] + input_row2[j]) / 2; \
-                       output_row1[j] = result; \
-                       output_row2[j] = result; \
-               } \
-       } \
-}
-
-#define DEINTERLACE_SWAP_MACRO(type, components, dominance) \
-{ \
-       int w = input->get_w(); \
-       int h = input->get_h(); \
- \
-       for(int i = dominance; i < h - 1; i += 2) \
-       { \
-               type *input_row1 = (type*)input->get_rows()[i]; \
-               type *input_row2 = (type*)input->get_rows()[i + 1]; \
-               type *output_row1 = (type*)output->get_rows()[i]; \
-               type *output_row2 = (type*)output->get_rows()[i + 1]; \
-               type temp1, temp2; \
- \
-               for(int j = 0; j < w * components; j++) \
-               { \
-                       temp1 = input_row1[j]; \
-                       temp2 = input_row2[j]; \
-                       output_row1[j] = temp2; \
-                       output_row2[j] = temp1; \
-               } \
-       } \
-}
-
-
-#define DEINTERLACE_TEMPORALSWAP_MACRO(type, components, dominance) \
-{ \
-       int w = input->get_w(); \
-       int h = input->get_h(); \
- \
-       for(int i = 0; i < h - 1; i += 2) \
-       { \
-               type *input_row1;\
-               type *input_row2; \
-               type *output_row1 = (type*)output->get_rows()[i]; \
-               type *output_row2 = (type*)output->get_rows()[i + 1]; \
-               type temp1, temp2; \
-               \
-               if (dominance) { \
-                       input_row1 = (type*)input->get_rows()[i]; \
-                       input_row2 = (type*)prevframe->get_rows()[i+1]; \
-               } \
-               else  {\
-                       input_row1 = (type*)prevframe->get_rows()[i]; \
-                       input_row2 = (type*)input->get_rows()[i+1]; \
-               } \
- \
-               for(int j = 0; j < w * components; j++) \
-               { \
-                       temp1 = input_row1[j]; \
-                       temp2 = input_row2[j]; \
-                       output_row1[j] = temp1; \
-                       output_row2[j] = temp2; \
-               } \
-       } \
-}
-
-
-/* Bob & Weave deinterlacer:
-
-For each pixel, 
-       if it's similar to the previous frame 
-       then keep it
-       else average with line above and below
-
-Similar is defined as in abs(difference)/(sum) < threshold
-*/
-// cplr warns, #define FABS(a) (((a)<0)?(0-(a)):(a))
-static inline int FABS(int8_t v) { return v<0 ? -v : v; }
-static inline int FABS(uint8_t v) { return v; }
-static inline int FABS(int16_t v) { return v<0 ? -v : v; }
-static inline int FABS(uint16_t v) { return v; }
-static inline int FABS(int32_t v) { return v<0 ? -v : v; }
-static inline int64_t FABS(uint32_t v) { return v; }
-static inline int64_t FABS(int64_t v) { return v<0 ? -v : v; }
-static inline int64_t FABS(uint64_t v) { return v; }
-static inline float FABS(float v) { return v<0 ? -v : v; }
-static inline double FABS(double v) { return v<0 ? -v : v; }
-#define FMAX(a,b) (((a)>(b))?(a):(b))
-#define FMIN(a,b) (((a)<(b))?(a):(b))
-
-#define SQ(a) ((a)*(a))
-// threshold < 100 -> a-b/a+b <
-
-#define DEINTERLACE_BOBWEAVE_MACRO(type, temp_type, components, dominance, threshold, noise_threshold) \
-{ \
-       /* Ooooohh, I like fudge factors */ \
-       double exp_threshold=exp(((double)threshold - 50 )/2);\
-       int w = input->get_w(); \
-       int h = input->get_h(); \
-       type *row_above=(type*)input->get_rows()[0]; \
-       for(int i = dominance ?0:1; i < h - 1; i += 2) \
-       { \
-               type *input_row;\
-               type *input_row2; \
-               type *old_row; \
-               type *output_row1 = (type*)output->get_rows()[i]; \
-               type *output_row2 = (type*)output->get_rows()[i + 1]; \
-               temp_type pixel, below, old, above; \
-               \
-               input_row = (type*)input->get_rows()[i]; \
-               input_row2 = (type*)input->get_rows()[i+1]; \
-               old_row = (type*)prevframe->get_rows()[i]; \
-\
-               for(int j = 0; j < w * components; j++) \
-               { \
-                       pixel = input_row[j]; \
-                       below = input_row2[j]; \
-                       old = old_row[j]; \
-                       above = row_above[j]; \
-\
-                       if  ( ( FABS(pixel-old) <= noise_threshold )  \
-                       || ((pixel+old != 0) && (((FABS((double) pixel-old))/((double) pixel+old)) >= exp_threshold )) \
-                       || ((above+below != 0) && (((FABS((double) pixel-old))/((double) above+below)) >= exp_threshold )) \
-                       ) {\
-                               pixel=(above+below)/2 ;\
-                       }\
-                       output_row1[j] = pixel; \
-                       output_row2[j] = below; \
-               } \
-               row_above=input_row2; \
-       } \
-}
-
-
-void DeInterlaceMain::deinterlace_top(VFrame *input, VFrame *output, int dominance)
-{
-       switch(input->get_color_model())
-       {
-               case BC_RGB888:
-               case BC_YUV888:
-                       DEINTERLACE_TOP_MACRO(unsigned char, 3, dominance);
-                       break;
-               case BC_RGB_FLOAT:
-                       DEINTERLACE_TOP_MACRO(float, 3, dominance);
-                       break;
-               case BC_RGBA8888:
-               case BC_YUVA8888:
-                       DEINTERLACE_TOP_MACRO(unsigned char, 4, dominance);
-                       break;
-               case BC_RGBA_FLOAT:
-                       DEINTERLACE_TOP_MACRO(float, 4, dominance);
-                       break;
-               case BC_RGB161616:
-               case BC_YUV161616:
-                       DEINTERLACE_TOP_MACRO(uint16_t, 3, dominance);
-                       break;
-               case BC_RGBA16161616:
-               case BC_YUVA16161616:
-                       DEINTERLACE_TOP_MACRO(uint16_t, 4, dominance);
-                       break;
-       }
-}
-
-void DeInterlaceMain::deinterlace_avg_top(VFrame *input, VFrame *output, int dominance)
-{
-       switch(input->get_color_model())
-       {
-               case BC_RGB888:
-               case BC_YUV888:
-                       DEINTERLACE_AVG_TOP_MACRO(unsigned char, int64_t, 3, dominance);
-                       break;
-               case BC_RGB_FLOAT:
-                       DEINTERLACE_AVG_TOP_MACRO(float, double, 3, dominance);
-                       break;
-               case BC_RGBA8888:
-               case BC_YUVA8888:
-                       DEINTERLACE_AVG_TOP_MACRO(unsigned char, int64_t, 4, dominance);
-                       break;
-               case BC_RGBA_FLOAT:
-                       DEINTERLACE_AVG_TOP_MACRO(float, double, 4, dominance);
-                       break;
-               case BC_RGB161616:
-               case BC_YUV161616:
-                       DEINTERLACE_AVG_TOP_MACRO(uint16_t, int64_t, 3, dominance);
-                       break;
-               case BC_RGBA16161616:
-               case BC_YUVA16161616:
-                       DEINTERLACE_AVG_TOP_MACRO(uint16_t, int64_t, 4, dominance);
-                       break;
-       }
-}
-
-void DeInterlaceMain::deinterlace_avg(VFrame *input, VFrame *output)
-{
-       switch(input->get_color_model())
-       {
-               case BC_RGB888:
-               case BC_YUV888:
-                       DEINTERLACE_AVG_MACRO(unsigned char, uint64_t, 3);
-                       break;
-               case BC_RGB_FLOAT:
-                       DEINTERLACE_AVG_MACRO(float, double, 3);
-                       break;
-               case BC_RGBA8888:
-               case BC_YUVA8888:
-                       DEINTERLACE_AVG_MACRO(unsigned char, uint64_t, 4);
-                       break;
-               case BC_RGBA_FLOAT:
-                       DEINTERLACE_AVG_MACRO(float, double, 4);
-                       break;
-               case BC_RGB161616:
-               case BC_YUV161616:
-                       DEINTERLACE_AVG_MACRO(uint16_t, uint64_t, 3);
-                       break;
-               case BC_RGBA16161616:
-               case BC_YUVA16161616:
-                       DEINTERLACE_AVG_MACRO(uint16_t, uint64_t, 4);
-                       break;
-       }
-}
-
-void DeInterlaceMain::deinterlace_swap(VFrame *input, VFrame *output, int dominance)
-{
-       switch(input->get_color_model())
-       {
-               case BC_RGB888:
-               case BC_YUV888:
-                       DEINTERLACE_SWAP_MACRO(unsigned char, 3, dominance);
-                       break;
-               case BC_RGB_FLOAT:
-                       DEINTERLACE_SWAP_MACRO(float, 3, dominance);
-                       break;
-               case BC_RGBA8888:
-               case BC_YUVA8888:
-                       DEINTERLACE_SWAP_MACRO(unsigned char, 4, dominance);
-                       break;
-               case BC_RGBA_FLOAT:
-                       DEINTERLACE_SWAP_MACRO(float, 4, dominance);
-                       break;
-               case BC_RGB161616:
-               case BC_YUV161616:
-                       DEINTERLACE_SWAP_MACRO(uint16_t, 3, dominance);
-                       break;
-               case BC_RGBA16161616:
-               case BC_YUVA16161616:
-                       DEINTERLACE_SWAP_MACRO(uint16_t, 4, dominance);
-                       break;
-       }
-}
-
-void DeInterlaceMain::deinterlace_temporalswap(VFrame *input, VFrame *prevframe, VFrame *output, int dominance)
-{
-       switch(input->get_color_model())
-       {
-               case BC_RGB888:
-               case BC_YUV888:
-                       DEINTERLACE_TEMPORALSWAP_MACRO(unsigned char, 3, dominance);
-                       break;
-               case BC_RGB_FLOAT:
-                       DEINTERLACE_TEMPORALSWAP_MACRO(float, 3, dominance);
-                       break;
-               case BC_RGBA8888:
-               case BC_YUVA8888:
-                       DEINTERLACE_TEMPORALSWAP_MACRO(unsigned char, 4, dominance);
-                       break;
-               case BC_RGBA_FLOAT:
-                       DEINTERLACE_TEMPORALSWAP_MACRO(float, 4, dominance);
-                       break;
-               case BC_RGB161616:
-               case BC_YUV161616:
-                       DEINTERLACE_TEMPORALSWAP_MACRO(uint16_t, 3, dominance);
-                       break;
-               case BC_RGBA16161616:
-               case BC_YUVA16161616:
-                       DEINTERLACE_TEMPORALSWAP_MACRO(uint16_t, 4, dominance);
-                       break;
-       }
-}
-
-void DeInterlaceMain::deinterlace_bobweave(VFrame *input, VFrame *prevframe, VFrame *output, int dominance)
-{
-       int threshold=config.threshold;
-       int noise_threshold=0;
-
-       switch(input->get_color_model())
-       {
-               case BC_RGB888:
-               case BC_YUV888:
-                       DEINTERLACE_BOBWEAVE_MACRO(unsigned char, uint64_t, 3, dominance, threshold, noise_threshold);
-                       break;
-               case BC_RGB_FLOAT:
-                       DEINTERLACE_BOBWEAVE_MACRO(float, double, 3, dominance, threshold, noise_threshold);
-                       break;
-               case BC_RGBA8888:
-               case BC_YUVA8888:
-                       DEINTERLACE_BOBWEAVE_MACRO(unsigned char, uint64_t, 4, dominance, threshold, noise_threshold);
-                       break;
-               case BC_RGBA_FLOAT:
-                       DEINTERLACE_BOBWEAVE_MACRO(float, double, 4, dominance, threshold, noise_threshold);
-                       break;
-               case BC_RGB161616:
-               case BC_YUV161616:
-                       DEINTERLACE_BOBWEAVE_MACRO(uint16_t, uint64_t, 3, dominance, threshold, noise_threshold);
-                       break;
-               case BC_RGBA16161616:
-               case BC_YUVA16161616:
-                       DEINTERLACE_BOBWEAVE_MACRO(uint16_t, uint64_t, 4, dominance, threshold, noise_threshold);
-                       break;
-       }
-}
-
-
-int DeInterlaceMain::process_buffer(VFrame *frame,
-       int64_t start_position,
-       double frame_rate)
-{
-       changed_rows = frame->get_h();
-       load_configuration();
-
-
-       read_frame(frame, 0, start_position, frame_rate, 0);
-
-// Temp was used for adaptive deinterlacing where it took deinterlacing
-// an entire frame to decide if the deinterlaced output should be used.
-       temp = frame;
-
-//     if(!temp)
-//             temp = new VFrame(
-//                     frame->get_w(),
-//                     frame->get_h(),
-//                     frame->get_color_model());
-       if(!temp_prevframe)
-               temp_prevframe = new VFrame(
-                       frame->get_w(),
-                       frame->get_h(),
-                       frame->get_color_model());
-
-       switch(config.mode)
-       {
-               case DEINTERLACE_NONE:
-//                     output->copy_from(input);
-                       break;
-               case DEINTERLACE_KEEP:
-                       deinterlace_top(frame, frame, config.dominance);
-                       break;
-               case DEINTERLACE_AVG:
-                       deinterlace_avg(frame, frame);
-                       break;
-               case DEINTERLACE_AVG_1F:
-                       deinterlace_avg_top(frame, frame, config.dominance);
-                       break;
-               case DEINTERLACE_SWAP:
-                       deinterlace_swap(frame, frame, config.dominance);
-                       break;
-               case DEINTERLACE_BOBWEAVE:
-                       if (get_source_position()==0)
-                               read_frame(temp_prevframe,0, get_source_position(), get_framerate(), 0);
-                       else 
-                               read_frame(temp_prevframe,0, get_source_position()-1, get_framerate(), 0);
-                       deinterlace_bobweave(frame, temp_prevframe, frame, config.dominance);
-                       break;
-               case DEINTERLACE_TEMPORALSWAP:
-                       if (get_source_position()==0)
-                               read_frame(temp_prevframe,0, get_source_position(), get_framerate(), 0);
-                       else 
-                               read_frame(temp_prevframe,0, get_source_position()-1, get_framerate(), 0);
-                       deinterlace_temporalswap(frame, temp_prevframe, frame, config.dominance);
-                       break; 
-       }
-       send_render_gui(&changed_rows);
-       return 0;
-}
-
-
-void DeInterlaceMain::render_gui(void *data)
-{
-       if(thread)
-       {
-               thread->window->lock_window();
-               char string[BCTEXTLEN];
-               DeInterlaceWindow *window = (DeInterlaceWindow *)thread->window;
-               window->get_status_string(string, *(int*)data);
-               window->status->update(string);
-               window->flush();
-               window->unlock_window();
-       }
-}
-
-NEW_WINDOW_MACRO(DeInterlaceMain, DeInterlaceWindow)
-LOAD_CONFIGURATION_MACRO(DeInterlaceMain, DeInterlaceConfig)
-
-
-
-void DeInterlaceMain::save_data(KeyFrame *keyframe)
-{
-       FileXML output;
-       output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
-       output.tag.set_title("DEINTERLACE");
-       output.tag.set_property("MODE", config.mode);
-       output.tag.set_property("DOMINANCE", config.dominance);
-       output.tag.set_property("ADAPTIVE", config.adaptive);
-       output.tag.set_property("THRESHOLD", config.threshold);
-       output.append_tag();
-       output.tag.set_title("/DEINTERLACE");
-       output.append_tag();
-       output.terminate_string();
-}
-
-void DeInterlaceMain::read_data(KeyFrame *keyframe)
-{
-       FileXML input;  char *data = keyframe->get_data();
-       input.set_shared_input(data, strlen(data));
-
-       while(!input.read_tag())
-       {
-               if(input.tag.title_is("DEINTERLACE"))
-               {
-                       config.mode = input.tag.get_property("MODE", config.mode);
-                       config.dominance = input.tag.get_property("DOMINANCE", config.dominance);
-                       config.adaptive = input.tag.get_property("ADAPTIVE", config.adaptive);
-                       config.threshold = input.tag.get_property("THRESHOLD", config.threshold);
-               }
-       }
-
-}
-
-void DeInterlaceMain::update_gui()
-{
-       if(thread) 
-       {
-               load_configuration();
-               DeInterlaceWindow *window = (DeInterlaceWindow *)thread->window;
-               window->lock_window();
-               window->set_mode(config.mode, 1);
-               if (window->dominance_top)
-                       window->dominance_top->update(config.dominance?0:BC_Toggle::TOGGLE_CHECKED);
-               if (window->dominance_bottom)
-                       window->dominance_bottom->update(config.dominance?BC_Toggle::TOGGLE_CHECKED:0);
-               if (window->adaptive)
-                       window->adaptive->update(config.adaptive);
-               if (window->threshold)
-                       window->threshold->update(config.threshold);
-               window->unlock_window();
-       }
-}
-